From d2f49ca175c21c6ab7556ec3de0c09e4fbbad906 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Fri, 10 Nov 2023 04:14:27 -0800 Subject: [PATCH] Improve mkdeps Our makefile generator now accepts badly formatted include lines. It's now more hermetic with better error checking in the cosmo repo, and it can be configured to not be hermetic at all. --- Makefile | 2 +- bin/fatcosmocc | 12 + build/bootstrap/mkdeps.com | Bin 235854 -> 272022 bytes libc/calls/getrlimit.c | 1 + libc/calls/internal.h | 4 - libc/calls/ioctl.c | 2 +- libc/calls/ischardev.c | 2 +- libc/calls/pthread_yield.c | 3 +- libc/calls/read-nt.c | 20 +- libc/calls/setrlimit.c | 1 + libc/calls/sig.c | 2 - libc/calls/sigtimedwait.c | 1 - libc/calls/sync.c | 1 + libc/calls/sys_ptrace.c | 1 + libc/calls/winexec.c | 5 +- libc/intrin/__getenv.c | 1 + libc/intrin/createfile.c | 4 - libc/intrin/cxalock.c | 7 +- libc/intrin/ftrace_enabled.c | 2 +- libc/intrin/isdebuggerpresent.c | 2 +- libc/intrin/kprintf.greg.c | 2 +- libc/intrin/pthread_mutex_lock.c | 5 +- libc/intrin/pthread_next.c | 4 +- libc/intrin/pthread_tid.c | 4 +- libc/intrin/strace.internal.h | 78 ++-- libc/intrin/strace_enabled.c | 2 +- libc/intrin/strace_enter.c | 31 -- libc/intrin/stracef.greg.c | 9 +- libc/nexgen32e/yield.h | 16 - libc/proc/execve.c | 1 + libc/proc/fork-nt.c | 10 +- libc/proc/fork.c | 1 - libc/proc/proc.c | 7 +- libc/runtime/runtime.h | 5 +- libc/runtime/zipos-get.c | 1 - libc/sock/kntwsadata.c | 1 - libc/sock/sendmsg.c | 4 +- libc/stdio/fread.c | 2 +- libc/stdio/fseek.c | 2 +- libc/stdio/fwrite.c | 2 +- libc/stdio/stdio.mk | 2 + libc/sysv/systemfive.S | 2 + libc/testlib/testmain.c | 2 + libc/testlib/testrunner.c | 4 +- libc/thread/thread.h | 9 + test/libc/stdio/test.mk | 4 +- third_party/dlmalloc/dlmalloc.c | 1 - third_party/dlmalloc/locks.inc | 2 +- third_party/double-conversion/test/checks.h | 2 +- third_party/libcxx/__functional_base | 2 +- third_party/libcxx/__functional_base_03 | 223 ----------- third_party/libcxx/__locale | 23 -- third_party/libcxx/__threading_support | 2 +- third_party/libcxx/algorithm | 2 +- third_party/libcxx/execution | 2 +- third_party/libcxx/functional | 2 +- third_party/libcxx/locale | 4 +- third_party/libcxx/memory | 2 +- third_party/libcxx/numeric | 2 +- third_party/lua/lua.mk | 5 + third_party/python/python.mk | 1 + third_party/sqlite3/.clang-format | 2 + third_party/sqlite3/fts3_tokenizer.c | 4 +- third_party/sqlite3/sqliteInt.h | 4 +- third_party/unzip/fileio.c | 4 - third_party/unzip/globals.h | 4 - tool/build/mkdeps.c | 417 +++++++++++++++----- tool/net/net.mk | 1 + tool/viz/rlimit.c | 5 +- 69 files changed, 466 insertions(+), 533 deletions(-) delete mode 100644 libc/intrin/strace_enter.c mode change 100644 => 100755 libc/nexgen32e/yield.h delete mode 100644 third_party/libcxx/__functional_base_03 create mode 100644 third_party/sqlite3/.clang-format diff --git a/Makefile b/Makefile index 80ef2288a..317d95270 100644 --- a/Makefile +++ b/Makefile @@ -329,7 +329,7 @@ o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $( o/$(MODE)/incs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(INCS) $(INCS),$(dir $(x)))) $(INCS) $(INCS) $(file >$@,$(INCS)) o/$(MODE)/depend: o/$(MODE)/.x o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt o/$(MODE)/incs.txt $(SRCS) $(HDRS) $(INCS) - $(COMPILE) -AMKDEPS -L320 $(MKDEPS) -o $@ -r o/$(MODE)/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt @o/$(MODE)/incs.txt + $(COMPILE) -AMKDEPS -L320 $(MKDEPS) -o $@ -s -r o/$(MODE)/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt @o/$(MODE)/incs.txt o/$(MODE)/srcs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x)))) $(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x))) diff --git a/bin/fatcosmocc b/bin/fatcosmocc index ca7e9a9bf..7c2345c32 100755 --- a/bin/fatcosmocc +++ b/bin/fatcosmocc @@ -240,6 +240,8 @@ NEED_JOIN= NEED_EQUAL= NEED_OUTPUT= APELINKFLAGS= +FLAGS_X86_64= +FLAGS_AARCH64= INPUT_FILE_COUNT=0 for x; do if [ x"$x" != x"${x#* }" ]; then @@ -335,6 +337,14 @@ for x; do continue elif [ x"$x" = x"-march=native" ]; then fatal_error "-march=native can't be used when building fat binaries" + elif [ x"$x" != x"${x#-Xx86_64}" ]; then + x=${x#-Xx86_64} # e.g. -Xx86_64,-msse3,-mavx,-mavx2,-mf16c,-mfma + FLAGS_X86_64="$FLAGS_X86_64 ${x//,/ }" + continue + elif [ x"$x" != x"${x#-Xaarch64}" ]; then + x=${x#-Xaarch64} + FLAGS_aarch64="$FLAGS_aarch64 ${x//,/ }" + continue elif [ x"$x" = x"-dumpversion" ]; then echo $GCC_VERSION Exit 0 @@ -473,6 +483,7 @@ build_object() { $CFLAGS_X86_64 \ $CPPFLAGS_X86_64 \ "$@" \ + $FLAGS_X86_64 \ $PRECIOUS log_command "$@" "$@" || exit @@ -492,6 +503,7 @@ build_object() { $CFLAGS_AARCH64 \ $CPPFLAGS_AARCH64 \ "$@" \ + $FLAGS_AARCH64 \ $PRECIOUS && log_command "$@" "$@" || exit diff --git a/build/bootstrap/mkdeps.com b/build/bootstrap/mkdeps.com index e850c2ae161b8a41ae933bce8f51332ac4ffc21e..6b1e5b74f0e2b0bea2d0912672c8c2a65831b246 100755 GIT binary patch delta 80240 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 L+)sZi#uxlI1n#ir diff --git a/libc/calls/getrlimit.c b/libc/calls/getrlimit.c index 4ba4ea41d..72420395c 100644 --- a/libc/calls/getrlimit.c +++ b/libc/calls/getrlimit.c @@ -23,6 +23,7 @@ #include "libc/intrin/asan.internal.h" #include "libc/intrin/describeflags.internal.h" #include "libc/intrin/strace.internal.h" +#include "libc/runtime/runtime.h" #include "libc/runtime/stack.h" #include "libc/runtime/syslib.internal.h" #include "libc/sysv/consts/rlimit.h" diff --git a/libc/calls/internal.h b/libc/calls/internal.h index f2fa4d731..f5c980256 100644 --- a/libc/calls/internal.h +++ b/libc/calls/internal.h @@ -31,10 +31,6 @@ int64_t GetConsoleOutputHandle(void); int IsWindowsExecutable(int64_t, const char16_t *); void InterceptTerminalCommands(const char *, size_t); -forceinline int64_t __getfdhandleactual(int fd) { - return g_fds.p[fd].handle; -} - forceinline bool __isfdopen(int fd) { return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind != kFdEmpty; } diff --git a/libc/calls/ioctl.c b/libc/calls/ioctl.c index 819416fec..6b31c3d96 100644 --- a/libc/calls/ioctl.c +++ b/libc/calls/ioctl.c @@ -75,7 +75,7 @@ static int ioctl_default(int fd, unsigned long request, void *arg) { return sys_ioctl(fd, request, arg); } else if (__isfdopen(fd)) { if (g_fds.p[fd].kind == kFdSocket) { - handle = __getfdhandleactual(fd); + handle = g_fds.p[fd].handle; if ((rc = _weaken(__sys_ioctlsocket_nt)(handle, request, arg)) != -1) { return rc; } else { diff --git a/libc/calls/ischardev.c b/libc/calls/ischardev.c index 06e026531..da7ad7641 100644 --- a/libc/calls/ischardev.c +++ b/libc/calls/ischardev.c @@ -56,6 +56,6 @@ bool32 ischardev(int fd) { } else { return __isfdkind(fd, kFdConsole) || __isfdkind(fd, kFdDevNull) || (__isfdkind(fd, kFdFile) && - GetFileType(__getfdhandleactual(fd)) == kNtFileTypeChar); + GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar); } } diff --git a/libc/calls/pthread_yield.c b/libc/calls/pthread_yield.c index 20462fe79..f3dfd002a 100644 --- a/libc/calls/pthread_yield.c +++ b/libc/calls/pthread_yield.c @@ -18,7 +18,6 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/dce.h" -#include "libc/nexgen32e/yield.h" #include "libc/runtime/runtime.h" #include "libc/runtime/syslib.internal.h" #include "libc/thread/thread.h" @@ -32,7 +31,7 @@ int pthread_yield(void) { if (IsXnuSilicon()) { __syslib->__pthread_yield_np(); } else if (IsOpenbsd()) { - spin_yield(); // sched_yield() is punishingly slow on OpenBSD + pthread_pause_np(); // sched_yield() is punishingly slow on OpenBSD } else { sched_yield(); } diff --git a/libc/calls/read-nt.c b/libc/calls/read-nt.c index 1924ee002..8ffe0a346 100644 --- a/libc/calls/read-nt.c +++ b/libc/calls/read-nt.c @@ -142,7 +142,7 @@ struct Keystrokes { static struct Keystrokes __keystroke; -textwindows void __keystroke_wipe(void) { +textwindows void WipeKeystrokes(void) { bzero(&__keystroke, sizeof(__keystroke)); } @@ -754,8 +754,8 @@ static textwindows ssize_t ReadFromConsole(struct Fd *f, void *data, return rc; } -textwindows ssize_t sys_read_nt_impl(int fd, void *data, size_t size, - int64_t offset, sigset_t waitmask) { +textwindows ssize_t ReadBuffer(int fd, void *data, size_t size, int64_t offset, + sigset_t waitmask) { // switch to terminal polyfill if reading from win32 console struct Fd *f = g_fds.p + fd; @@ -786,9 +786,9 @@ textwindows ssize_t sys_read_nt_impl(int fd, void *data, size_t size, } } -static textwindows ssize_t sys_read_nt2(int fd, const struct iovec *iov, - size_t iovlen, int64_t opt_offset, - sigset_t waitmask) { +static textwindows ssize_t ReadIovecs(int fd, const struct iovec *iov, + size_t iovlen, int64_t opt_offset, + sigset_t waitmask) { ssize_t rc; size_t i, total; if (opt_offset < -1) return einval(); @@ -796,8 +796,8 @@ static textwindows ssize_t sys_read_nt2(int fd, const struct iovec *iov, if (iovlen) { for (total = i = 0; i < iovlen; ++i) { if (!iov[i].iov_len) continue; - rc = sys_read_nt_impl(fd, iov[i].iov_base, iov[i].iov_len, opt_offset, - waitmask); + rc = + ReadBuffer(fd, iov[i].iov_base, iov[i].iov_len, opt_offset, waitmask); if (rc == -1) { if (total && errno != ECANCELED) { return total; @@ -811,7 +811,7 @@ static textwindows ssize_t sys_read_nt2(int fd, const struct iovec *iov, } return total; } else { - return sys_read_nt_impl(fd, NULL, 0, opt_offset, waitmask); + return ReadBuffer(fd, NULL, 0, opt_offset, waitmask); } } @@ -819,7 +819,7 @@ textwindows ssize_t sys_read_nt(int fd, const struct iovec *iov, size_t iovlen, int64_t opt_offset) { ssize_t rc; sigset_t m = __sig_block(); - rc = sys_read_nt2(fd, iov, iovlen, opt_offset, m); + rc = ReadIovecs(fd, iov, iovlen, opt_offset, m); __sig_unblock(m); return rc; } diff --git a/libc/calls/setrlimit.c b/libc/calls/setrlimit.c index 2883c5f72..6e1b1fb39 100644 --- a/libc/calls/setrlimit.c +++ b/libc/calls/setrlimit.c @@ -25,6 +25,7 @@ #include "libc/intrin/describeflags.internal.h" #include "libc/intrin/strace.internal.h" #include "libc/macros.internal.h" +#include "libc/runtime/runtime.h" #include "libc/runtime/syslib.internal.h" #include "libc/sysv/consts/rlimit.h" #include "libc/sysv/errfuns.h" diff --git a/libc/calls/sig.c b/libc/calls/sig.c index 8c620ee93..c6e208e25 100644 --- a/libc/calls/sig.c +++ b/libc/calls/sig.c @@ -201,7 +201,6 @@ textwindows int __sig_raise(volatile int sig, int sic) { STRACE("__sig_raise(%G, %t) mask %s", sig, __sig_handler(rva), (DescribeSigset)(ssbuf, 0, (sigset_t *)&pt->tib->tib_sigmask)); __sig_handler(rva)(sig, &si, &ctx); - (void)ssbuf; // record this handler if (flags & SA_RESTART) { @@ -271,7 +270,6 @@ static textwindows wontreturn void __sig_tramp(struct SignalFrame *sf) { (DescribeSigset)(ssbuf[0], 0, &sf->ctx.uc_sigmask), (DescribeSigset)(ssbuf[1], 0, (sigset_t *)&tib->tib_sigmask)); __sig_handler(sf->rva)(sig, &sf->si, &sf->ctx); - (void)ssbuf; // restore the signal mask that was used by the interrupted code // this may have been modified by the signal handler in the callback diff --git a/libc/calls/sigtimedwait.c b/libc/calls/sigtimedwait.c index 051d91a95..1b47e61ad 100644 --- a/libc/calls/sigtimedwait.c +++ b/libc/calls/sigtimedwait.c @@ -51,7 +51,6 @@ int sigtimedwait(const sigset_t *set, siginfo_t *info, struct timespec ts; union siginfo_meta si = {0}; BEGIN_CANCELATION_POINT; - (void)strsig; if (IsAsan() && (!__asan_is_valid(set, sizeof(*set)) || (info && !__asan_is_valid(info, sizeof(*info))) || diff --git a/libc/calls/sync.c b/libc/calls/sync.c index 9fa35a520..809158269 100644 --- a/libc/calls/sync.c +++ b/libc/calls/sync.c @@ -21,6 +21,7 @@ #include "libc/calls/syscall-sysv.internal.h" #include "libc/dce.h" #include "libc/intrin/strace.internal.h" +#include "libc/runtime/runtime.h" /** * Flushes file system changes to disk by any means necessary. diff --git a/libc/calls/sys_ptrace.c b/libc/calls/sys_ptrace.c index 6abdb9703..bdecfc2ea 100644 --- a/libc/calls/sys_ptrace.c +++ b/libc/calls/sys_ptrace.c @@ -22,6 +22,7 @@ #include "libc/intrin/describeflags.internal.h" #include "libc/intrin/likely.h" #include "libc/intrin/strace.internal.h" +#include "libc/runtime/runtime.h" #define IsPeek(request) (IsLinux() && (request)-1u < 3) diff --git a/libc/calls/winexec.c b/libc/calls/winexec.c index c8c96cb7d..5cd1d5141 100644 --- a/libc/calls/winexec.c +++ b/libc/calls/winexec.c @@ -28,9 +28,10 @@ #include "libc/str/tab.internal.h" #include "third_party/linenoise/linenoise.h" -#define EXT(s) READ32LE(s "\0\0") +#define Read32(s) (s[3] << 24 | s[2] << 16 | s[1] << 8 | s[0]) +#define EXT(s) Read32(s "\0\0") -static bool IsGraph(wint_t c) { +static inline bool IsGraph(wint_t c) { return 0x21 <= c && c <= 0x7E; } diff --git a/libc/intrin/__getenv.c b/libc/intrin/__getenv.c index d8c382a91..c76632727 100644 --- a/libc/intrin/__getenv.c +++ b/libc/intrin/__getenv.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/dce.h" #include "libc/intrin/getenv.internal.h" +#include "libc/intrin/kprintf.h" privileged struct Env __getenv(char **p, const char *k) { char *t; diff --git a/libc/intrin/createfile.c b/libc/intrin/createfile.c index 2aab825be..4b092c4b9 100644 --- a/libc/intrin/createfile.c +++ b/libc/intrin/createfile.c @@ -49,13 +49,9 @@ CreateFile(const char16_t *lpFileName, // int64_t hHandle; uint32_t micros = 1; char buf_accessflags[512]; - (void)buf_accessflags; char buf_shareflags[64]; - (void)buf_shareflags; char buf_secattr[32]; - (void)buf_secattr; char buf_flagattr[256]; - (void)buf_flagattr; TryAgain: hHandle = __imp_CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, opt_lpSecurity, dwCreationDisposition, diff --git a/libc/intrin/cxalock.c b/libc/intrin/cxalock.c index 632698675..7142f5c2f 100644 --- a/libc/intrin/cxalock.c +++ b/libc/intrin/cxalock.c @@ -33,7 +33,10 @@ void __cxa_unlock(void) { pthread_mutex_unlock(&__cxa_lock_obj); } -__attribute__((__constructor__)) static void __cxa_init(void) { - __cxa_wipe(); +static textstartup void __cxa_init() { pthread_atfork(__cxa_lock, __cxa_unlock, __cxa_wipe); } + +const void *const __cxa_ctor[] initarray = { + __cxa_init, +}; diff --git a/libc/intrin/ftrace_enabled.c b/libc/intrin/ftrace_enabled.c index 1e448fbe6..1313f01fa 100644 --- a/libc/intrin/ftrace_enabled.c +++ b/libc/intrin/ftrace_enabled.c @@ -25,7 +25,7 @@ * @param delta is added to enabled state * @return enabled state before `delta` was applied */ -dontinstrument int ftrace_enabled(int delta) { +dontinstrument int(ftrace_enabled)(int delta) { int res; struct CosmoTib *tib; if (__tls_enabled) { diff --git a/libc/intrin/isdebuggerpresent.c b/libc/intrin/isdebuggerpresent.c index 7ee193002..e455d55e5 100644 --- a/libc/intrin/isdebuggerpresent.c +++ b/libc/intrin/isdebuggerpresent.c @@ -50,7 +50,7 @@ int IsDebuggerPresent(bool force) { int e, fd, res; char *p, buf[1024]; if (!force && IsGenuineBlink()) return 0; - if (!force && __getenv(environ, "HEISENDEBUG").s) return 0; + if (!force && environ && __getenv(environ, "HEISENDEBUG").s) return 0; if (IsWindows()) return IsBeingDebugged(); if (__isworker) return false; if (!PLEDGED(RPATH)) return false; diff --git a/libc/intrin/kprintf.greg.c b/libc/intrin/kprintf.greg.c index 1cefe2480..41306f305 100644 --- a/libc/intrin/kprintf.greg.c +++ b/libc/intrin/kprintf.greg.c @@ -345,7 +345,7 @@ privileged long kloghandle(void) { // it's too early in the initialization process for kprintf return -1; } - path = __getenv(__envp, "KPRINTF_LOG").s; + path = environ ? __getenv(environ, "KPRINTF_LOG").s : 0; closefd = false; if (!path) { fd = STDERR_FILENO; diff --git a/libc/intrin/pthread_mutex_lock.c b/libc/intrin/pthread_mutex_lock.c index d61b5c9b8..01ca6cb0e 100644 --- a/libc/intrin/pthread_mutex_lock.c +++ b/libc/intrin/pthread_mutex_lock.c @@ -22,7 +22,6 @@ #include "libc/intrin/atomic.h" #include "libc/intrin/strace.internal.h" #include "libc/intrin/weaken.h" -#include "libc/nexgen32e/yield.h" #include "libc/runtime/internal.h" #include "libc/thread/thread.h" #include "libc/thread/tls.h" @@ -83,7 +82,7 @@ errno_t pthread_mutex_lock(pthread_mutex_t *mutex) { if (mutex->_type == PTHREAD_MUTEX_NORMAL) { while (atomic_exchange_explicit(&mutex->_lock, 1, memory_order_acquire)) { - spin_yield(); + pthread_pause_np(); } return 0; } @@ -103,7 +102,7 @@ errno_t pthread_mutex_lock(pthread_mutex_t *mutex) { } while (atomic_exchange_explicit(&mutex->_lock, 1, memory_order_acquire)) { - spin_yield(); + pthread_pause_np(); } mutex->_depth = 0; diff --git a/libc/intrin/pthread_next.c b/libc/intrin/pthread_next.c index 59f906a35..82d0d46d3 100644 --- a/libc/intrin/pthread_next.c +++ b/libc/intrin/pthread_next.c @@ -19,8 +19,8 @@ #include "libc/assert.h" #include "libc/dce.h" #include "libc/intrin/atomic.h" -#include "libc/nexgen32e/yield.h" #include "libc/thread/posixthread.internal.h" +#include "libc/thread/thread.h" intptr_t _pthread_syshand(struct PosixThread *pt) { intptr_t syshand; @@ -28,6 +28,6 @@ intptr_t _pthread_syshand(struct PosixThread *pt) { for (;;) { syshand = atomic_load_explicit(&pt->tib->tib_syshand, memory_order_acquire); if (syshand) return syshand; - spin_yield(); + pthread_pause_np(); } } diff --git a/libc/intrin/pthread_tid.c b/libc/intrin/pthread_tid.c index 726e46436..4f1a8b16e 100644 --- a/libc/intrin/pthread_tid.c +++ b/libc/intrin/pthread_tid.c @@ -17,13 +17,13 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/intrin/atomic.h" -#include "libc/nexgen32e/yield.h" #include "libc/thread/posixthread.internal.h" +#include "libc/thread/thread.h" int _pthread_tid(struct PosixThread *pt) { int tid = 0; while (pt && !(tid = atomic_load_explicit(&pt->ptid, memory_order_acquire))) { - spin_yield(); + pthread_pause_np(); } return tid; } diff --git a/libc/intrin/strace.internal.h b/libc/intrin/strace.internal.h index 92cc9101e..5ad187324 100644 --- a/libc/intrin/strace.internal.h +++ b/libc/intrin/strace.internal.h @@ -1,7 +1,9 @@ #ifndef COSMOPOLITAN_LIBC_CALLS_STRACE_INTERNAL_H_ #define COSMOPOLITAN_LIBC_CALLS_STRACE_INTERNAL_H_ -#include "libc/intrin/likely.h" -#include "libc/runtime/runtime.h" + +#ifndef SYSDEBUG +#define SYSDEBUG 1 +#endif #define _NTTRACE 0 /* not configurable w/ flag yet */ #define _POLLTRACE 0 /* not configurable w/ flag yet */ @@ -16,60 +18,40 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -#ifdef SYSDEBUG -#define STRACE(FMT, ...) \ - do { \ - if (UNLIKELY(strace_enter())) { \ - __stracef(STRACE_PROLOGUE FMT "\n", ##__VA_ARGS__); \ - ftrace_enabled(+1); \ - } \ - } while (0) -#else -#define STRACE(FMT, ...) (void)0 -#endif +#define STRACE(FMT, ...) \ + ((void)(SYSDEBUG && strace_enabled(0) > 0 && \ + (__stracef(STRACE_PROLOGUE FMT "\n", ##__VA_ARGS__), 0))) -#if defined(SYSDEBUG) && _DATATRACE -#define DATATRACE(FMT, ...) STRACE(FMT, ##__VA_ARGS__) -#else -#define DATATRACE(FMT, ...) (void)0 -#endif +#define DATATRACE(FMT, ...) \ + ((void)(SYSDEBUG && _DATATRACE && strace_enabled(0) > 0 && \ + (__stracef(STRACE_PROLOGUE FMT "\n", ##__VA_ARGS__), 0))) -#if defined(SYSDEBUG) && _POLLTRACE -#define POLLTRACE(FMT, ...) STRACE(FMT, ##__VA_ARGS__) -#else -#define POLLTRACE(FMT, ...) (void)0 -#endif +#define POLLTRACE(FMT, ...) \ + ((void)(SYSDEBUG && _POLLTRACE && strace_enabled(0) > 0 && \ + (__stracef(STRACE_PROLOGUE FMT "\n", ##__VA_ARGS__), 0))) -#if defined(SYSDEBUG) && _KERNTRACE -#define KERNTRACE(FMT, ...) STRACE(FMT, ##__VA_ARGS__) -#else -#define KERNTRACE(FMT, ...) (void)0 -#endif +#define KERNTRACE(FMT, ...) \ + ((void)(SYSDEBUG && _KERNTRACE && strace_enabled(0) > 0 && \ + (__stracef(STRACE_PROLOGUE FMT "\n", ##__VA_ARGS__), 0))) -#if defined(SYSDEBUG) && _STDIOTRACE -#define STDIOTRACE(FMT, ...) STRACE(FMT, ##__VA_ARGS__) -#else -#define STDIOTRACE(FMT, ...) (void)0 -#endif +#define STDIOTRACE(FMT, ...) \ + ((void)(SYSDEBUG && _STDIOTRACE && strace_enabled(0) > 0 && \ + (__stracef(STRACE_PROLOGUE FMT "\n", ##__VA_ARGS__), 0))) -#if defined(SYSDEBUG) && _NTTRACE -#define NTTRACE(FMT, ...) STRACE("\e[2m" FMT "\e[0m", ##__VA_ARGS__) -#else -#define NTTRACE(FMT, ...) (void)0 -#endif +#define NTTRACE(FMT, ...) \ + ((void)(SYSDEBUG && _NTTRACE && strace_enabled(0) > 0 && \ + (__stracef(STRACE_PROLOGUE "\e[2m" FMT "\e[0m\n", ##__VA_ARGS__), \ + 0))) -#if defined(SYSDEBUG) && _LOCKTRACE -#define LOCKTRACE(FMT, ...) STRACE(FMT, ##__VA_ARGS__) -#else -#define LOCKTRACE(FMT, ...) (void)0 -#endif +#define LOCKTRACE(FMT, ...) \ + ((void)(SYSDEBUG && _LOCKTRACE && strace_enabled(0) > 0 && \ + (__stracef(STRACE_PROLOGUE FMT "\n", ##__VA_ARGS__), 0))) -#if defined(SYSDEBUG) && _TIMETRACE -#define TIMETRACE(FMT, ...) STRACE(FMT, ##__VA_ARGS__) -#else -#define TIMETRACE(FMT, ...) (void)0 -#endif +#define TIMETRACE(FMT, ...) \ + ((void)(SYSDEBUG && _TIMETRACE && strace_enabled(0) > 0 && \ + (__stracef(STRACE_PROLOGUE FMT "\n", ##__VA_ARGS__), 0))) +int strace_enabled(int); void __stracef(const char *, ...); COSMOPOLITAN_C_END_ diff --git a/libc/intrin/strace_enabled.c b/libc/intrin/strace_enabled.c index e3783b36c..a04d3d6c1 100644 --- a/libc/intrin/strace_enabled.c +++ b/libc/intrin/strace_enabled.c @@ -25,7 +25,7 @@ * @param delta is added to enabled state * @return enabled state before `delta` was applied */ -dontinstrument int strace_enabled(int delta) { +dontinstrument int(strace_enabled)(int delta) { int res; struct CosmoTib *tib; if (__tls_enabled) { diff --git a/libc/intrin/strace_enter.c b/libc/intrin/strace_enter.c deleted file mode 100644 index 64e4c9e59..000000000 --- a/libc/intrin/strace_enter.c +++ /dev/null @@ -1,31 +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/runtime/runtime.h" -#ifdef SYSDEBUG - -dontinstrument bool strace_enter(void) { - if (strace_enabled(0) > 0) { - ftrace_enabled(-1); - return true; - } else { - return false; - } -} - -#endif /* SYSDEBUG */ diff --git a/libc/intrin/stracef.greg.c b/libc/intrin/stracef.greg.c index 874bd9ce1..4dadf3375 100644 --- a/libc/intrin/stracef.greg.c +++ b/libc/intrin/stracef.greg.c @@ -19,15 +19,10 @@ #include "libc/intrin/kprintf.h" #include "libc/intrin/strace.internal.h" #include "libc/runtime/runtime.h" -#include "libc/thread/tls.h" -#include "libc/thread/tls2.internal.h" -privileged void __stracef(const char *fmt, ...) { +dontinstrument void __stracef(const char *fmt, ...) { va_list v; - if (__strace <= 0 || - (__tls_enabled && __get_tls_privileged()->tib_strace <= 0)) { - return; - } + if (strace_enabled(0) <= 0) return; va_start(v, fmt); kvprintf(fmt, v); va_end(v); diff --git a/libc/nexgen32e/yield.h b/libc/nexgen32e/yield.h old mode 100644 new mode 100755 index 221b70ece..e69de29bb --- a/libc/nexgen32e/yield.h +++ b/libc/nexgen32e/yield.h @@ -1,16 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_YIELD_H_ -#define COSMOPOLITAN_LIBC_YIELD_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) -#ifdef _COSMO_SOURCE - -static inline void spin_yield(void) { -#if defined(__GNUC__) && defined(__aarch64__) - __asm__ volatile("yield"); -#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) - __asm__ volatile("pause"); -#endif -} - -#endif /* _COSMO_SOURCE */ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_YIELD_H_ */ diff --git a/libc/proc/execve.c b/libc/proc/execve.c index 586c71ead..a90d934e7 100644 --- a/libc/proc/execve.c +++ b/libc/proc/execve.c @@ -29,6 +29,7 @@ #include "libc/intrin/strace.internal.h" #include "libc/intrin/weaken.h" #include "libc/log/libfatal.internal.h" +#include "libc/runtime/runtime.h" #include "libc/runtime/zipos.internal.h" #include "libc/sysv/consts/o.h" #include "libc/sysv/errfuns.h" diff --git a/libc/proc/fork-nt.c b/libc/proc/fork-nt.c index 1be406dd1..61aec9c0d 100644 --- a/libc/proc/fork-nt.c +++ b/libc/proc/fork-nt.c @@ -58,7 +58,7 @@ #include "libc/thread/tls.h" #ifdef __x86_64__ -void __keystroke_wipe(void); +void WipeKeystrokes(void); static textwindows wontreturn void AbortFork(const char *func) { #ifdef SYSDEBUG @@ -310,9 +310,9 @@ textwindows int sys_fork_nt(uint32_t dwCreationFlags) { bzero(&startinfo, sizeof(startinfo)); startinfo.cb = sizeof(struct NtStartupInfo); startinfo.dwFlags = kNtStartfUsestdhandles; - startinfo.hStdInput = __getfdhandleactual(0); - startinfo.hStdOutput = __getfdhandleactual(1); - startinfo.hStdError = __getfdhandleactual(2); + startinfo.hStdInput = g_fds.p[0].handle; + startinfo.hStdOutput = g_fds.p[1].handle; + startinfo.hStdError = g_fds.p[2].handle; args = __argv; #ifdef SYSDEBUG // If --strace was passed to this program, then propagate it the @@ -395,7 +395,7 @@ textwindows int sys_fork_nt(uint32_t dwCreationFlags) { } // reset core runtime services __proc_wipe(); - __keystroke_wipe(); + WipeKeystrokes(); if (_weaken(__itimer_wipe)) { _weaken(__itimer_wipe)(); } diff --git a/libc/proc/fork.c b/libc/proc/fork.c index ac69bbd0c..87fb1c75f 100644 --- a/libc/proc/fork.c +++ b/libc/proc/fork.c @@ -44,7 +44,6 @@ int _fork(uint32_t dwCreationFlags) { struct Dll *e; int ax, dx, tid, parent; parent = __pid; - (void)parent; BLOCK_SIGNALS; if (IsWindows()) __proc_lock(); if (__threaded && _weaken(_pthread_onfork_prepare)) { diff --git a/libc/proc/proc.c b/libc/proc/proc.c index 10a8a80ee..2449927ad 100644 --- a/libc/proc/proc.c +++ b/libc/proc/proc.c @@ -269,10 +269,9 @@ textwindows void __proc_wipe(void) { textwindows struct Proc *__proc_new(void) { struct Dll *e; struct Proc *proc = 0; - int i, n = ARRAYLEN(__proc.pool); - if (atomic_load_explicit(&__proc.allocated, memory_order_acquire) < n && - (i = atomic_fetch_add(&__proc.allocated, 1)) < n) { - proc = __proc.pool + i; + // fork() + wait() don't depend on malloc() so neither shall we + if (__proc.allocated < ARRAYLEN(__proc.pool)) { + proc = __proc.pool + __proc.allocated++; } else { if ((e = dll_first(__proc.free))) { proc = PROC_CONTAINER(e); diff --git a/libc/runtime/runtime.h b/libc/runtime/runtime.h index 9417c9f48..be91f9b8a 100644 --- a/libc/runtime/runtime.h +++ b/libc/runtime/runtime.h @@ -91,7 +91,6 @@ void ShowCrashReports(void); int ftrace_install(void); int ftrace_enabled(int); int strace_enabled(int); -bool strace_enter(void); void __print_maps(void); void __printargs(const char *); /* builtin sh-like system/popen dsl */ @@ -139,10 +138,10 @@ __funline int __trace_disabled(int x) { return 0; } #ifndef FTRACE -#define ftrace_enabled __trace_disabled +#define ftrace_enabled(...) __trace_disabled(__VA_ARGS__) #endif #ifndef SYSDEBUG -#define strace_enabled __trace_disabled +#define strace_enabled(...) __trace_disabled(__VA_ARGS__) #endif #endif /* _COSMO_SOURCE */ diff --git a/libc/runtime/zipos-get.c b/libc/runtime/zipos-get.c index 397fc5e12..0a2385a32 100644 --- a/libc/runtime/zipos-get.c +++ b/libc/runtime/zipos-get.c @@ -152,7 +152,6 @@ static void __zipos_init(void) { progpath = 0; msg = -777; } - (void)msg; STRACE("__zipos_get(%#s) → %d% m", progpath, msg); } diff --git a/libc/sock/kntwsadata.c b/libc/sock/kntwsadata.c index 660819021..d8456aa24 100644 --- a/libc/sock/kntwsadata.c +++ b/libc/sock/kntwsadata.c @@ -38,7 +38,6 @@ struct NtWsaData kNtWsaData; static textwindows void WinSockCleanup(void) { int rc; - (void)rc; rc = WSACleanup(); NTTRACE("WSACleanup() → %d% lm", rc); } diff --git a/libc/sock/sendmsg.c b/libc/sock/sendmsg.c index 280ec1854..be3033c81 100644 --- a/libc/sock/sendmsg.c +++ b/libc/sock/sendmsg.c @@ -27,6 +27,7 @@ #include "libc/intrin/describeflags.internal.h" #include "libc/intrin/kprintf.h" #include "libc/intrin/strace.internal.h" +#include "libc/runtime/runtime.h" #include "libc/sock/internal.h" #include "libc/sock/sock.h" #include "libc/sock/struct/msghdr.h" @@ -87,7 +88,8 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) { END_CANCELATION_POINT; #if defined(SYSDEBUG) && _DATATRACE - if (__strace > 0 && strace_enabled(0) > 0) { + // TODO(jart): Write a DescribeMsg() function. + if (strace_enabled(0) > 0) { kprintf(STRACE_PROLOGUE "sendmsg("); if ((!IsAsan() && kisdangerous(msg)) || (IsAsan() && !__asan_is_valid(msg, sizeof(*msg)))) { diff --git a/libc/stdio/fread.c b/libc/stdio/fread.c index ee82f8275..58564cd46 100644 --- a/libc/stdio/fread.c +++ b/libc/stdio/fread.c @@ -19,7 +19,7 @@ #include "libc/intrin/describeflags.internal.h" #include "libc/intrin/strace.internal.h" #include "libc/runtime/runtime.h" -#include "libc/stdio/stdio.h" +#include "libc/stdio/internal.h" /** * Reads data from stream. diff --git a/libc/stdio/fseek.c b/libc/stdio/fseek.c index 0da8e521b..b29f7cfd5 100644 --- a/libc/stdio/fseek.c +++ b/libc/stdio/fseek.c @@ -18,7 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/intrin/describeflags.internal.h" #include "libc/intrin/strace.internal.h" -#include "libc/stdio/stdio.h" +#include "libc/stdio/internal.h" /** * Repositions open file stream. diff --git a/libc/stdio/fwrite.c b/libc/stdio/fwrite.c index 7888be1b7..972b92508 100644 --- a/libc/stdio/fwrite.c +++ b/libc/stdio/fwrite.c @@ -18,7 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/intrin/describeflags.internal.h" #include "libc/intrin/strace.internal.h" -#include "libc/stdio/stdio.h" +#include "libc/stdio/internal.h" /** * Writes data to stream. diff --git a/libc/stdio/stdio.mk b/libc/stdio/stdio.mk index fb67da936..d18ea53b6 100644 --- a/libc/stdio/stdio.mk +++ b/libc/stdio/stdio.mk @@ -8,6 +8,7 @@ LIBC_STDIO = $(LIBC_STDIO_A_DEPS) $(LIBC_STDIO_A) LIBC_STDIO_A = o/$(MODE)/libc/stdio/stdio.a LIBC_STDIO_A_FILES := $(wildcard libc/stdio/*) LIBC_STDIO_A_HDRS = $(filter %.h,$(LIBC_STDIO_A_FILES)) +LIBC_STDIO_A_INCS = $(filter %.inc,$(LIBC_STDIO_A_FILES)) LIBC_STDIO_A_SRCS_S = $(filter %.S,$(LIBC_STDIO_A_FILES)) LIBC_STDIO_A_SRCS_C = $(filter %.c,$(LIBC_STDIO_A_FILES)) @@ -68,6 +69,7 @@ o/$(MODE)/libc/stdio/mt19937.o: private \ LIBC_STDIO_LIBS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x))) LIBC_STDIO_SRCS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_SRCS)) LIBC_STDIO_HDRS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_HDRS)) +LIBC_STDIO_INCS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_INCS)) LIBC_STDIO_CHECKS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_CHECKS)) LIBC_STDIO_OBJS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_OBJS)) $(LIBC_STDIO_OBJS): $(BUILD_FILES) libc/stdio/stdio.mk diff --git a/libc/sysv/systemfive.S b/libc/sysv/systemfive.S index 978c448db..cb489d966 100644 --- a/libc/sysv/systemfive.S +++ b/libc/sysv/systemfive.S @@ -399,7 +399,9 @@ _init_systemfive_magnums: jz 5f ezlea .Llog,di mov %r8d,%esi + push %rax call *%rax + pop %rax 5: pop %rsi pop %rdi #endif /* DEBUGSYS */ diff --git a/libc/testlib/testmain.c b/libc/testlib/testmain.c index ccec6f593..676140eda 100644 --- a/libc/testlib/testmain.c +++ b/libc/testlib/testmain.c @@ -33,6 +33,7 @@ #include "libc/log/log.h" #include "libc/macros.internal.h" #include "libc/mem/mem.h" +#include "libc/nexgen32e/nexgen32e.h" #include "libc/runtime/runtime.h" #include "libc/runtime/symbols.internal.h" #include "libc/str/str.h" @@ -122,6 +123,7 @@ dontasan int main(int argc, char *argv[]) { } // run tests + CheckStackIsAligned(); testlib_runalltests(); // run benchmarks diff --git a/libc/testlib/testrunner.c b/libc/testlib/testrunner.c index f30eaafe8..7ffaf918b 100644 --- a/libc/testlib/testrunner.c +++ b/libc/testlib/testrunner.c @@ -91,8 +91,10 @@ void testlib_runtestcases(const testfn_t *start, const testfn_t *end, // the linker sorts into an array. char host[64]; struct Dll *e; + const char *user; const testfn_t *fn; struct TestAspect *a; + user = getenv("USER"); strcpy(host, "unknown"); gethostname(host, sizeof(host)), errno = 0; for (fn = start; fn != end; ++fn) { @@ -111,7 +113,7 @@ void testlib_runtestcases(const testfn_t *start, const testfn_t *end, if (warmup) warmup(); testlib_clearxmmregisters(); STRACE(""); - STRACE("# running test %t on %s@%s", fn, __getenv(environ, "USER").s, host); + STRACE("# running test %t on %s@%s", fn, user, host); (*fn)(); STRACE(""); STRACE("# tearing down %t", fn); diff --git a/libc/thread/thread.h b/libc/thread/thread.h index c15383111..068b3d42e 100644 --- a/libc/thread/thread.h +++ b/libc/thread/thread.h @@ -213,6 +213,14 @@ void pthread_testcancel(void); pthread_cleanup_pop(&_buffer, (execute)); \ } +#if defined(__GNUC__) && defined(__aarch64__) +#define pthread_pause_np() __asm__ volatile("yield") +#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) +#define pthread_pause_np() __asm__ volatile("pause") +#else +#define pthread_pause_np() (void)0 +#endif + #if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407 && \ !defined(__STRICT_ANSI__) && !defined(MODE_DBG) extern const errno_t EBUSY; @@ -220,6 +228,7 @@ extern const errno_t EBUSY; ({ \ pthread_spinlock_t *_s = pSpin; \ while (__atomic_test_and_set(&_s->_lock, __ATOMIC_ACQUIRE)) { \ + pthread_pause_np(); \ } \ 0; \ }) diff --git a/test/libc/stdio/test.mk b/test/libc/stdio/test.mk index 7d83a8de1..9c41ebdbd 100644 --- a/test/libc/stdio/test.mk +++ b/test/libc/stdio/test.mk @@ -3,7 +3,9 @@ PKGS += TEST_LIBC_STDIO -TEST_LIBC_STDIO_SRCS := $(wildcard test/libc/stdio/*.c) +TEST_LIBC_STDIO_FILES := $(wildcard test/libc/stdio/*) +TEST_LIBC_STDIO_SRCS = $(filter %.c,$(TEST_LIBC_STDIO_FILES)) +TEST_LIBC_STDIO_INCS = $(filter %.inc,$(TEST_LIBC_STDIO_FILES)) TEST_LIBC_STDIO_SRCS_TEST = $(filter %_test.c,$(TEST_LIBC_STDIO_SRCS)) TEST_LIBC_STDIO_OBJS = \ diff --git a/third_party/dlmalloc/dlmalloc.c b/third_party/dlmalloc/dlmalloc.c index bee028cfd..7f9f738f8 100644 --- a/third_party/dlmalloc/dlmalloc.c +++ b/third_party/dlmalloc/dlmalloc.c @@ -11,7 +11,6 @@ #include "libc/macros.internal.h" #include "libc/mem/mem.h" #include "libc/nexgen32e/rdtsc.h" -#include "libc/nexgen32e/yield.h" #include "libc/runtime/internal.h" #include "libc/runtime/runtime.h" #include "libc/runtime/sysconf.h" diff --git a/third_party/dlmalloc/locks.inc b/third_party/dlmalloc/locks.inc index ee73aa2e9..15313b7b0 100644 --- a/third_party/dlmalloc/locks.inc +++ b/third_party/dlmalloc/locks.inc @@ -45,7 +45,7 @@ static int malloc_lock(MLOCK_T *lk) { if (!__threaded) return 0; #ifdef TINY while (atomic_exchange_explicit(lk, 1, memory_order_acquire)) { - spin_yield(); + pthread_pause_np(); } #else nsync_mu_lock(lk); diff --git a/third_party/double-conversion/test/checks.h b/third_party/double-conversion/test/checks.h index cbf90a43b..6314ae8c8 100644 --- a/third_party/double-conversion/test/checks.h +++ b/third_party/double-conversion/test/checks.h @@ -26,7 +26,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef V8_CHECKS_H_ #define V8_CHECKS_H_ -#include "third_party/double-conversion/test/flags.h" +//#include "third_party/double-conversion/test/flags.h" // clang-format off extern "C" void V8_Fatal(const char* file, int line, const char* format, ...); diff --git a/third_party/libcxx/__functional_base b/third_party/libcxx/__functional_base index cb7ddda5c..a6b69b084 100644 --- a/third_party/libcxx/__functional_base +++ b/third_party/libcxx/__functional_base @@ -303,7 +303,7 @@ struct __invoke_return #else // defined(_LIBCPP_CXX03_LANG) -#include "third_party/libcxx/__functional_base_03" +//#include "third_party/libcxx/__functional_base_03" #endif // !defined(_LIBCPP_CXX03_LANG) diff --git a/third_party/libcxx/__functional_base_03 b/third_party/libcxx/__functional_base_03 deleted file mode 100644 index e6dac90c8..000000000 --- a/third_party/libcxx/__functional_base_03 +++ /dev/null @@ -1,223 +0,0 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP_FUNCTIONAL_BASE_03 -#define _LIBCPP_FUNCTIONAL_BASE_03 - -// manual variadic expansion for - -// __invoke - -template -struct __enable_invoke_imp; - -template -struct __enable_invoke_imp<_Ret, _T1, true, true> { - typedef _Ret _Bullet1; - typedef _Bullet1 type; -}; - -template -struct __enable_invoke_imp<_Ret, _T1, true, false> { - typedef _Ret _Bullet2; - typedef _Bullet2 type; -}; - -template -struct __enable_invoke_imp<_Ret, _T1, false, true> { - typedef typename add_lvalue_reference< - typename __apply_cv<_T1, _Ret>::type - >::type _Bullet3; - typedef _Bullet3 type; -}; - -template -struct __enable_invoke_imp<_Ret, _T1, false, false> { - typedef typename add_lvalue_reference< - typename __apply_cv()), _Ret>::type - >::type _Bullet4; - typedef _Bullet4 type; -}; - -template -struct __enable_invoke_imp<_Ret, _T1*, false, false> { - typedef typename add_lvalue_reference< - typename __apply_cv<_T1, _Ret>::type - >::type _Bullet4; - typedef _Bullet4 type; -}; - -template , - class _Ret = typename _Traits::_ReturnType, - class _Class = typename _Traits::_ClassType> -struct __enable_invoke : __enable_invoke_imp< - _Ret, _T1, - is_member_function_pointer<_Fn>::value, - is_base_of<_Class, typename remove_reference<_T1>::type>::value> -{ -}; - -__nat __invoke(__any, ...); - -// first bullet - -template -inline _LIBCPP_INLINE_VISIBILITY -typename __enable_invoke<_Fn, _T1>::_Bullet1 -__invoke(_Fn __f, _T1& __t1) { - return (__t1.*__f)(); -} - -template -inline _LIBCPP_INLINE_VISIBILITY -typename __enable_invoke<_Fn, _T1>::_Bullet1 -__invoke(_Fn __f, _T1& __t1, _A0& __a0) { - return (__t1.*__f)(__a0); -} - -template -inline _LIBCPP_INLINE_VISIBILITY -typename __enable_invoke<_Fn, _T1>::_Bullet1 -__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) { - return (__t1.*__f)(__a0, __a1); -} - -template -inline _LIBCPP_INLINE_VISIBILITY -typename __enable_invoke<_Fn, _T1>::_Bullet1 -__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) { - return (__t1.*__f)(__a0, __a1, __a2); -} - -template -inline _LIBCPP_INLINE_VISIBILITY -typename __enable_invoke<_Fn, _T1>::_Bullet2 -__invoke(_Fn __f, _T1& __t1) { - return ((*__t1).*__f)(); -} - -template -inline _LIBCPP_INLINE_VISIBILITY -typename __enable_invoke<_Fn, _T1>::_Bullet2 -__invoke(_Fn __f, _T1& __t1, _A0& __a0) { - return ((*__t1).*__f)(__a0); -} - -template -inline _LIBCPP_INLINE_VISIBILITY -typename __enable_invoke<_Fn, _T1>::_Bullet2 -__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) { - return ((*__t1).*__f)(__a0, __a1); -} - -template -inline _LIBCPP_INLINE_VISIBILITY -typename __enable_invoke<_Fn, _T1>::_Bullet2 -__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) { - return ((*__t1).*__f)(__a0, __a1, __a2); -} - -template -inline _LIBCPP_INLINE_VISIBILITY -typename __enable_invoke<_Fn, _T1>::_Bullet3 -__invoke(_Fn __f, _T1& __t1) { - return __t1.*__f; -} - -template -inline _LIBCPP_INLINE_VISIBILITY -typename __enable_invoke<_Fn, _T1>::_Bullet4 -__invoke(_Fn __f, _T1& __t1) { - return (*__t1).*__f; -} - -// fifth bullet - -template -inline _LIBCPP_INLINE_VISIBILITY -decltype(_VSTD::declval<_Fp&>()()) -__invoke(_Fp& __f) -{ - return __f(); -} - -template -inline _LIBCPP_INLINE_VISIBILITY -decltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>())) -__invoke(_Fp& __f, _A0& __a0) -{ - return __f(__a0); -} - -template -inline _LIBCPP_INLINE_VISIBILITY -decltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>(), _VSTD::declval<_A1&>())) -__invoke(_Fp& __f, _A0& __a0, _A1& __a1) -{ - return __f(__a0, __a1); -} - -template -inline _LIBCPP_INLINE_VISIBILITY -decltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>(), _VSTD::declval<_A1&>(), _VSTD::declval<_A2&>())) -__invoke(_Fp& __f, _A0& __a0, _A1& __a1, _A2& __a2) -{ - return __f(__a0, __a1, __a2); -} - -template >::value> -struct __invoke_return -{ - typedef typename __weak_result_type<_Fp>::result_type type; -}; - -template -struct __invoke_return<_Fp, false> -{ - typedef decltype(__invoke(_VSTD::declval<_Fp&>())) type; -}; - -template -struct __invoke_return0 -{ - typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>())) type; -}; - -template -struct __invoke_return0<_Rp _Tp::*, _A0> -{ - typedef typename __enable_invoke<_Rp _Tp::*, _A0>::type type; -}; - -template -struct __invoke_return1 -{ - typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>(), - _VSTD::declval<_A1&>())) type; -}; - -template -struct __invoke_return1<_Rp _Class::*, _A0, _A1> { - typedef typename __enable_invoke<_Rp _Class::*, _A0>::type type; -}; - -template -struct __invoke_return2 -{ - typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>(), - _VSTD::declval<_A1&>(), - _VSTD::declval<_A2&>())) type; -}; - -template -struct __invoke_return2<_Ret _Class::*, _A0, _A1, _A2> { - typedef typename __enable_invoke<_Ret _Class::*, _A0>::type type; -}; -#endif // _LIBCPP_FUNCTIONAL_BASE_03 diff --git a/third_party/libcxx/__locale b/third_party/libcxx/__locale index 7e2d0c88a..e0ff7ab79 100644 --- a/third_party/libcxx/__locale +++ b/third_party/libcxx/__locale @@ -18,29 +18,6 @@ #include "third_party/libcxx/cstdint" #include "third_party/libcxx/cctype" #include "third_party/libcxx/locale.h" -#if defined(_LIBCPP_MSVCRT_LIKE) -# include "third_party/libcxx/cstring" -# include "third_party/libcxx/support/win32/locale_win32.h" -#elif defined(_AIX) -# include "third_party/libcxx/support/ibm/xlocale.h" -#elif defined(__ANDROID__) -# include "third_party/libcxx/support/android/locale_bionic.h" -#elif defined(__sun__) -# include "third_party/libcxx/xlocale.h" -# include "third_party/libcxx/support/solaris/xlocale.h" -#elif defined(_NEWLIB_VERSION) -# include "third_party/libcxx/support/newlib/xlocale.h" -#elif (defined(__APPLE__) || defined(__FreeBSD__) \ - || defined(__EMSCRIPTEN__) || defined(__IBMCPP__)) -# include "third_party/libcxx/xlocale.h" -#elif defined(__Fuchsia__) -# include "third_party/libcxx/support/fuchsia/xlocale.h" -#elif defined(__wasi__) -// WASI libc uses musl's locales support. -# include "third_party/libcxx/support/musl/xlocale.h" -#elif defined(_LIBCPP_HAS_MUSL_LIBC) -# include "third_party/libcxx/support/musl/xlocale.h" -#endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header diff --git a/third_party/libcxx/__threading_support b/third_party/libcxx/__threading_support index 52ba3a9eb..f21862c22 100644 --- a/third_party/libcxx/__threading_support +++ b/third_party/libcxx/__threading_support @@ -22,7 +22,7 @@ #endif #if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) -# include "third_party/libcxx/__external_threading" +//# include "third_party/libcxx/__external_threading" #elif !defined(_LIBCPP_HAS_NO_THREADS) #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) diff --git a/third_party/libcxx/algorithm b/third_party/libcxx/algorithm index bf8f3b9f1..505c4238e 100644 --- a/third_party/libcxx/algorithm +++ b/third_party/libcxx/algorithm @@ -23,7 +23,7 @@ #include "third_party/libcxx/version" #if defined(_LIBCPP_HAS_PARALLEL_ALGORITHMS) && _LIBCPP_STD_VER >= 17 -# include "third_party/libcxx/__pstl_algorithm" +//# include "third_party/libcxx/__pstl_algorithm" #endif #include "third_party/libcxx/__debug" diff --git a/third_party/libcxx/execution b/third_party/libcxx/execution index c9ef9edde..f497d122e 100644 --- a/third_party/libcxx/execution +++ b/third_party/libcxx/execution @@ -14,7 +14,7 @@ #include "third_party/libcxx/__config" #if defined(_LIBCPP_HAS_PARALLEL_ALGORITHMS) && _LIBCPP_STD_VER >= 17 -# include "third_party/libcxx/__pstl_execution" +//# include "third_party/libcxx/__pstl_execution" #endif #endif // _LIBCPP_EXECUTION diff --git a/third_party/libcxx/functional b/third_party/libcxx/functional index ff98a20e3..5b191efba 100644 --- a/third_party/libcxx/functional +++ b/third_party/libcxx/functional @@ -2528,7 +2528,7 @@ swap(function<_Rp(_ArgTypes...)>& __x, function<_Rp(_ArgTypes...)>& __y) _NOEXCE #else // _LIBCPP_CXX03_LANG -# include "third_party/libcxx/__functional_03" +//# include "third_party/libcxx/__functional_03" #endif diff --git a/third_party/libcxx/locale b/third_party/libcxx/locale index bef8d232f..9a47138ab 100644 --- a/third_party/libcxx/locale +++ b/third_party/libcxx/locale @@ -26,11 +26,11 @@ #include "third_party/libcxx/cstdio" #ifdef _LIBCPP_HAS_CATOPEN # include "libc/str/locale.h" -# include "third_party/libcxx/nl_types.h" +//# include "third_party/libcxx/nl_types.h" #endif #ifdef _LIBCPP_LOCALE__L_EXTENSIONS -# include "third_party/libcxx/__bsd_locale_defaults.h" +//# include "third_party/libcxx/__bsd_locale_defaults.h" #else #include "third_party/libcxx/__bsd_locale_fallbacks.h" #endif diff --git a/third_party/libcxx/memory b/third_party/libcxx/memory index a1634471c..60205548b 100644 --- a/third_party/libcxx/memory +++ b/third_party/libcxx/memory @@ -5364,7 +5364,7 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS #if defined(_LIBCPP_HAS_PARALLEL_ALGORITHMS) && _LIBCPP_STD_VER >= 17 -# include "third_party/libcxx/__pstl_memory" +//# include "third_party/libcxx/__pstl_memory" #endif #endif // _LIBCPP_MEMORY diff --git a/third_party/libcxx/numeric b/third_party/libcxx/numeric index 554eef98c..01a268b7a 100644 --- a/third_party/libcxx/numeric +++ b/third_party/libcxx/numeric @@ -587,7 +587,7 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS #if defined(_LIBCPP_HAS_PARALLEL_ALGORITHMS) && _LIBCPP_STD_VER >= 17 -# include "third_party/libcxx/__pstl_numeric" +//# include "third_party/libcxx/__pstl_numeric" #endif #endif // _LIBCPP_NUMERIC diff --git a/third_party/lua/lua.mk b/third_party/lua/lua.mk index 8abd0148d..494483b9e 100644 --- a/third_party/lua/lua.mk +++ b/third_party/lua/lua.mk @@ -63,6 +63,10 @@ THIRD_PARTY_LUA_A_HDRS = \ third_party/lua/tms.h \ third_party/lua/visitor.h +THIRD_PARTY_LUA_A_INCS = \ + third_party/lua/ljumptab.inc \ + third_party/lua/lopnames.inc + THIRD_PARTY_LUA_A_SRCS = \ third_party/lua/lapi.c \ third_party/lua/lauxlib.c \ @@ -294,6 +298,7 @@ THIRD_PARTY_LUA_SRCS = \ THIRD_PARTY_LUA_LIBS = $(foreach x,$(THIRD_PARTY_LUA_ARTIFACTS),$($(x))) THIRD_PARTY_LUA_HDRS = $(foreach x,$(THIRD_PARTY_LUA_ARTIFACTS),$($(x)_HDRS)) +THIRD_PARTY_LUA_INCS = $(foreach x,$(THIRD_PARTY_LUA_ARTIFACTS),$($(x)_INCS)) THIRD_PARTY_LUA_OBJS = $(foreach x,$(THIRD_PARTY_LUA_ARTIFACTS),$($(x)_OBJS)) $(THIRD_PARTY_LUA_OBJS): third_party/lua/lua.mk diff --git a/third_party/python/python.mk b/third_party/python/python.mk index fba778e6f..dcaf2d867 100644 --- a/third_party/python/python.mk +++ b/third_party/python/python.mk @@ -297,6 +297,7 @@ THIRD_PARTY_PYTHON_INCS = \ third_party/python/Modules/clinic/_pickle.inc \ third_party/python/Modules/clinic/cmathmodule.inc \ third_party/python/Modules/clinic/_elementtree.inc \ + third_party/python/Modules/clinic/_struct.inc \ third_party/python/Modules/clinic/pwdmodule.inc \ third_party/python/Modules/clinic/audioop.inc diff --git a/third_party/sqlite3/.clang-format b/third_party/sqlite3/.clang-format new file mode 100644 index 000000000..47a38a93f --- /dev/null +++ b/third_party/sqlite3/.clang-format @@ -0,0 +1,2 @@ +DisableFormat: true +SortIncludes: Never diff --git a/third_party/sqlite3/fts3_tokenizer.c b/third_party/sqlite3/fts3_tokenizer.c index 769407108..fbd251957 100644 --- a/third_party/sqlite3/fts3_tokenizer.c +++ b/third_party/sqlite3/fts3_tokenizer.c @@ -227,9 +227,9 @@ int sqlite3Fts3InitTokenizer( #ifdef SQLITE_TEST #if defined(INCLUDE_SQLITE_TCL_H) -# include "sqlite_tcl.h" +//# include "sqlite_tcl.h" #else -# include "tcl.h" +//# include "tcl.h" #endif #include diff --git a/third_party/sqlite3/sqliteInt.h b/third_party/sqlite3/sqliteInt.h index e5607827d..a6a511f85 100644 --- a/third_party/sqlite3/sqliteInt.h +++ b/third_party/sqlite3/sqliteInt.h @@ -165,9 +165,9 @@ ** disabled. */ #if defined(_HAVE_MINGW_H) -# include "mingw.h" +//# include "mingw.h" #elif defined(_HAVE__MINGW_H) -# include "_mingw.h" +//# include "_mingw.h" #endif /* diff --git a/third_party/unzip/fileio.c b/third_party/unzip/fileio.c index 6a447eaf1..354d5a600 100644 --- a/third_party/unzip/fileio.c +++ b/third_party/unzip/fileio.c @@ -67,10 +67,6 @@ #define st_mtime st_mtim.tv_sec -#if defined( UNIX) && defined( __APPLE__) -#include "third_party/unzip/unix/macosx.h" -#endif /* defined( UNIX) && defined( __APPLE__) */ - /* setup of codepage conversion for decryption passwords */ #if CRYPT # if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY)) diff --git a/third_party/unzip/globals.h b/third_party/unzip/globals.h index 841a76b24..485538186 100644 --- a/third_party/unzip/globals.h +++ b/third_party/unzip/globals.h @@ -152,10 +152,6 @@ #include "third_party/bzip2/bzlib.h" #endif -#if defined( UNIX) && defined( __APPLE__) -#include "third_party/unzip/unix/macosx.h" -#endif /* defined( UNIX) && defined( __APPLE__) */ - /*************/ /* Globals */ diff --git a/tool/build/mkdeps.c b/tool/build/mkdeps.c index 3af37a3aa..f8d1e92bc 100644 --- a/tool/build/mkdeps.c +++ b/tool/build/mkdeps.c @@ -17,10 +17,12 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" +#include "libc/calls/struct/stat.h" #include "libc/errno.h" #include "libc/fmt/libgen.h" #include "libc/fmt/magnumstrs.internal.h" #include "libc/intrin/bits.h" +#include "libc/intrin/kprintf.h" #include "libc/limits.h" #include "libc/macros.internal.h" #include "libc/mem/alg.h" @@ -30,60 +32,65 @@ #include "libc/stdio/append.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" +#include "libc/str/tab.internal.h" #include "libc/sysv/consts/map.h" #include "libc/sysv/consts/o.h" #include "libc/sysv/consts/prot.h" +#include "libc/sysv/consts/s.h" #include "third_party/getopt/getopt.internal.h" #include "tool/build/lib/getargs.h" #define VERSION \ - "cosmopolitan mkdeps v2.0\n" \ + "cosmopolitan mkdeps v3.0\n" \ "copyright 2023 justine tunney\n" \ "https://github.com/jart/cosmopolitan\n" -#define MANUAL \ - " -r o// -o OUTPUT INPUT...\n" \ - "\n" \ - "DESCRIPTION\n" \ - "\n" \ - " Generates makefile defining header dependencies.\n" \ - "\n" \ - " Includes look like this:\n" \ - "\n" \ - " - #include \"root/of/repository/foo.h\"\n" \ - " - .include \"root/of/repository/foo.inc\"\n" \ - "\n" \ - " They do NOT look like this:\n" \ - "\n" \ - " - #include \n" \ - " - #include \"foo.h\"\n" \ - " - # include \"foo.h\"\n" \ - " - #include \"foo.h\"\n" \ - "\n" \ - " Your generated make code looks like this:\n" \ - "\n" \ - " o//package/foo.o: \\\n" \ - " package/foo.c \\\n" \ - " package/foo.h \\\n" \ - " package/bar.h\n" \ - " o//package/bar.o: \\\n" \ - " package/bar.c \\\n" \ - " package/bar.h\n" \ - "\n" \ - "FLAGS\n" \ - "\n" \ - " -h show usage\n" \ - " -o OUTPUT set output path\n" \ - " -r ROOT set build output prefix, e.g. o//\n" \ - "\n" \ - "ARGUMENTS\n" \ - "\n" \ - " OUTPUT shall be makefile code\n" \ - " INPUT should be source or @args.txt\n" \ +#define MANUAL \ + " -r o// -o OUTPUT INPUT...\n" \ + "\n" \ + "DESCRIPTION\n" \ + "\n" \ + " Generates header file dependencies for your makefile\n" \ + "\n" \ + " This tool computes the transitive closure of included paths\n" \ + " for every source file in your repository. This program does\n" \ + " it orders of a magnitude faster than `gcc -M` on each file.\n" \ + "\n" \ + " Includes look like this:\n" \ + "\n" \ + " - #include \n" \ + " - #include \"samedir.h\"\n" \ + " - #include \"root/of/repository/foo.h\"\n" \ + " - .include \"asm/x86_64/foo.s\"\n" \ + "\n" \ + " Your generated make code looks like this:\n" \ + "\n" \ + " o//package/foo.o: \\\n" \ + " package/foo.c \\\n" \ + " package/foo.h \\\n" \ + " package/bar.h \\\n" \ + " libc/isystem/stdio.h\n" \ + " o//package/bar.o: \\\n" \ + " package/bar.c \\\n" \ + " package/bar.h\n" \ + "\n" \ + "FLAGS\n" \ + "\n" \ + " -h show usage\n" \ + " -o OUTPUT set output path\n" \ + " -g ROOT set generated path [default: o/]\n" \ + " -r ROOT set build output path, e.g. o/$(MODE)/\n" \ + " -S PATH isystem include path [default: libc/isystem/]\n" \ + " -s hermetically sealed mode [repeatable]\n" \ + "\n" \ + "ARGUMENTS\n" \ + "\n" \ + " OUTPUT shall be makefile code\n" \ + " INPUT should be source or @args.txt\n" \ "\n" -#define kIncludePrefix "include " -#define kSystemIncludes "libc/isystem/" +#define Read32(s) (s[3] << 24 | s[2] << 16 | s[1] << 8 | s[0]) +#define EXT(s) Read32(s "\0\0") struct Source { unsigned hash; @@ -111,17 +118,34 @@ struct Edges { struct Edge *p; }; -static const char kSourceExts[][5] = {".s", ".S", ".c", ".cc", ".cpp"}; +static const uint32_t kSourceExts[] = { + EXT("s"), // assembly + EXT("S"), // assembly with c preprocessor + EXT("c"), // c + EXT("cc"), // c++ + EXT("cpp"), // c++ +}; static char *names; +static int hermetic; static unsigned counter; static const char *prog; static struct Edges edges; static struct Sauce *sauces; static struct Sources sources; +static const char *systempath; static const char *buildroot; +static const char *genroot; static const char *outpath; +static inline bool IsBlank(int c) { + return c == ' ' || c == '\t'; +} + +static inline bool IsGraph(wint_t c) { + return 0x21 <= c && c <= 0x7E; +} + static wontreturn void Die(const char *reason) { tinyprint(2, prog, ": ", reason, "\n", NULL); exit(1); @@ -132,6 +156,11 @@ static wontreturn void DieSys(const char *thing) { exit(1); } +static wontreturn void DiePathTooLong(const char *path) { + errno = ENAMETOOLONG; + DieSys(path); +} + static wontreturn void DieOom(void) { Die("out of memory"); } @@ -233,7 +262,7 @@ static void Rehash(void) { free(old.p); } -static unsigned GetSourceId(const char *name, size_t len) { +static int HashSource(const char *name, size_t len, bool create) { unsigned hash; size_t i, step; i = 0; @@ -249,6 +278,7 @@ static unsigned GetSourceId(const char *name, size_t len) { step++; } while (sources.p[i].hash); } + if (!create) return -1; if (++sources.i >= (sources.n >> 1)) { Rehash(); step = 0; @@ -264,21 +294,118 @@ static unsigned GetSourceId(const char *name, size_t len) { return (sources.p[i].id = counter++); } +static int CreateSourceId(const char *name) { + return HashSource(name, strlen(name), true); +} + +static int GetSourceId(const char *name) { + return HashSource(name, strlen(name), false); +} + +// `p` should point to substring "include " +// `map` and `mapsize` define legal memory range +// returns pointer to path, or null if `p` isn't an include +// +// syntax like the following is supported: +// +// - `#include "foo.h"` +// - `#include ` +// - `# include ` +// - `#include ` +// - ` #include ` +// - `.include "foo.h"` (for .s files only) +// +// known issues: +// +// - we can't tell if it's inside a /* comment */ +// - whitespace like vertical tab isn't supported +// +static const char *FindIncludePath(const char *map, size_t mapsize, + const char *p, bool is_assembly) { + const char *q = p; + + // scan backwards for hash character + for (;;) { + if (q == map) { + return false; + } + if (IsBlank(q[-1])) { + --q; + continue; + } + if (q[-1] == '#' && !is_assembly) { + --q; + break; + } else if (q[-1] == '.' && is_assembly) { + --q; + break; + } else { + return false; + } + } + + // scan backwards for newline character + if (!is_assembly) { + for (;;) { + if (q == map) { + break; + } + if (IsBlank(q[-1])) { + --q; + continue; + } + if (q[-1] == '\n') { + break; + } else { + return false; + } + } + } + + // scan forward for path + q = p + strlen("include "); + for (;;) { + if (q >= map + mapsize) { + break; + } + if (IsBlank(*q)) { + ++q; + continue; + } + if (*q == '"' || (*q == '<' && !is_assembly)) { + ++q; + break; + } else { + return false; + } + } + + // return pointer to path + return q; +} + static void LoadRelationships(int argc, char *argv[]) { int fd; char *map; ssize_t rc; + size_t size; + bool is_assembly; struct GetArgs ga; - char srcdirbuf[256]; - size_t n, size, inclen; - unsigned srcid, dependency; + int srcid, dependency; + static char srcdirbuf[PATH_MAX]; const char *p, *pe, *src, *path, *pathend, *srcdir; getargs_init(&ga, argv + optind); - inclen = strlen(kIncludePrefix); while ((src = getargs_next(&ga))) { - n = strlen(src); - srcid = GetSourceId(src, n); - strlcpy(srcdirbuf, src, sizeof(srcdirbuf)); + CreateSourceId(src); + } + getargs_destroy(&ga); + getargs_init(&ga, argv + optind); + while ((src = getargs_next(&ga))) { + is_assembly = endswith(src, ".s"); + srcid = GetSourceId(src); + if (strlcpy(srcdirbuf, src, PATH_MAX) >= PATH_MAX) { + DiePathTooLong(src); + } srcdir = dirname(srcdirbuf); if ((fd = open(src, O_RDONLY)) == -1) { if (errno == ENOENT && ga.path) { @@ -296,45 +423,66 @@ static void LoadRelationships(int argc, char *argv[]) { DieSys(src); } if ((size = rc)) { - map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0); + // repeatedly map to same fixed address so in order to weasel out + // of incurring the additional overhead of all these munmap calls + map = mmap((void *)0x311987030000, size, PROT_READ, + MAP_SHARED | MAP_FIXED, fd, 0); if (map == MAP_FAILED) { DieSys(src); } - for (p = map + 1, pe = map + size; p < pe; ++p) { - int right; - char juf[256], *jb; - char buf[256], *bp = buf; - if (!(p = memmem(p, pe - p, kIncludePrefix, inclen))) break; - path = p + inclen + 1; - if (path[-1] == '"') { - right = '"'; - } else if (path[-1] == '<') { - bp = mempcpy(bp, kSystemIncludes, strlen(kSystemIncludes)); + for (p = map, pe = map + size; p < pe; ++p) { + char *bp; + char right; + char buf[PATH_MAX]; + if (!(p = memmem(p, pe - p, "include ", 8))) break; + if (!(path = FindIncludePath(map, size, p, is_assembly))) continue; + bp = buf; + if (path[-1] == '<') { + if (!systempath) continue; + bp = stpcpy(bp, systempath); right = '>'; } else { - continue; + right = '"'; } - pathend = memchr(path, right, pe - path); - if (pathend && pathend - path > 0 && // - (p[-1] == '#' || p[-1] == '.') && // - (p - map == 1 || p[-2] == '\n') && // - (bp - buf) + (pathend - path) < sizeof(buf)) { // + if ((pathend = memchr(path, right, pe - path))) { + const char *final; + char juf[PATH_MAX]; + if ((bp - buf) + (pathend - path) >= PATH_MAX) { + tinyprint(2, src, ": include path too long\n", NULL); + exit(1); + } *(bp = mempcpy(bp, path, pathend - path)) = 0; - if (right == '>' && !isregularfile(buf)) continue; - if (!strchr(buf, '/') && !isregularfile(buf)) { - if (!(jb = __join_paths(juf, sizeof(juf), srcdir, buf))) continue; - if (!isregularfile(jb)) continue; - dependency = GetSourceId(jb, strlen(jb)); - } else { - dependency = GetSourceId(buf, bp - buf); + // let foo/bar.c say `#include "foo/hdr.h"` + dependency = GetSourceId((final = buf)); + // let foo/bar.c say `#include "hdr.h"` + if (dependency == -1 && right == '"' && !strchr(buf, '/')) { + if (!(final = __join_paths(juf, PATH_MAX, srcdir, buf))) { + DiePathTooLong(buf); + } + dependency = GetSourceId(final); + } + if (dependency == -1) { + if (startswith(buf, genroot)) { + dependency = CreateSourceId(src); + } else if (!hermetic) { + continue; + } else if (hermetic == 1 && right == '>') { + // chances are the `#include ` is in some #ifdef + // that'll never actually be executed; thus we ignore + // since landlock make unveil() shall catch it anyway + continue; + } else { + tinyprint( + 2, final, + ": path not specified by HDRS/SRCS/INCS make variables\n", + NULL); + exit(1); + } } AppendEdge(&edges, dependency, srcid); - p = pathend; + p = pathend + 1; } } - if (munmap(map, size)) { - DieSys(src); - } } if (close(fd)) { DieSys(src); @@ -350,14 +498,35 @@ static wontreturn void ShowUsage(int rc, int fd) { static void GetOpts(int argc, char *argv[]) { int opt; - while ((opt = getopt(argc, argv, "hno:r:")) != -1) { + while ((opt = getopt(argc, argv, "hnsgS:o:r:")) != -1) { switch (opt) { + case 's': + ++hermetic; + break; + case 'S': + if (systempath) { + Die("multiple system paths not supported yet"); + } + systempath = optarg; + break; case 'o': + if (outpath) { + Die("multiple output paths specified"); + } outpath = optarg; break; case 'r': + if (buildroot) { + Die("multiple build roots specified"); + } buildroot = optarg; break; + case 'g': + if (genroot) { + Die("multiple generated roots specified"); + } + genroot = optarg; + break; case 'n': exit(0); case 'h': @@ -366,29 +535,83 @@ static void GetOpts(int argc, char *argv[]) { ShowUsage(1, 2); } } - if (!outpath) { - Die("need output path"); - } - if (!buildroot) { - Die("need build output prefix"); - } if (optind == argc) { Die("missing input argument"); } + if (!genroot) { + genroot = "o/"; + } + if (!endswith(genroot, "/")) { + Die("generated output path must end with slash"); + } + if (!buildroot) { + Die("need build output path"); + } + if (!endswith(buildroot, "/")) { + Die("build output path must end with slash"); + } + if (!startswith(buildroot, genroot)) { + Die("build output path must start with generated output path"); + } + if (!systempath && hermetic) { + systempath = "libc/isystem/"; + } + if (systempath && !hermetic) { + Die("system path can only be specified in hermetic mode"); + } + if (systempath) { + size_t n; + struct stat st; + if (stat(systempath, &st)) { + DieSys(systempath); + } + if (!S_ISDIR(st.st_mode)) { + errno = ENOTDIR; + DieSys(systempath); + } + if ((n = strlen(systempath)) >= PATH_MAX) { + DiePathTooLong(systempath); + } + if (!n || systempath[n - 1] != '/') { + Die("system path must end with slash"); + } + } } -static const char *StripExt(char pathbuf[PATH_MAX + 1], const char *s) { +static const char *StripExt(char pathbuf[hasatleast PATH_MAX], const char *s) { static char *dot; - strlcpy(pathbuf, s, PATH_MAX + 1); + if (strlcpy(pathbuf, s, PATH_MAX) >= PATH_MAX) { + DiePathTooLong(s); + } dot = strrchr(pathbuf, '.'); if (dot) *dot = '\0'; return pathbuf; } +static uint32_t GetFileExtension(const char *s) { + uint32_t w; + size_t i, n; + n = s ? strlen(s) : 0; + for (i = w = 0; n--;) { + wint_t c = s[n]; + if (!IsGraph(c)) return 0; + if (c == '.') break; + if (++i > 4) return 0; + w <<= 8; + w |= kToLower[c]; + } + return w; +} + static bool IsObjectSource(const char *name) { int i; - for (i = 0; i < ARRAYLEN(kSourceExts); ++i) { - if (endswith(name, kSourceExts[i])) return true; + uint32_t ext; + if ((ext = GetFileExtension(name))) { + for (i = 0; i < ARRAYLEN(kSourceExts); ++i) { + if (ext == kSourceExts[i]) { + return true; + } + } } return false; } @@ -416,17 +639,16 @@ static char *Explore(void) { unsigned *visited; size_t i, visilen; char *makefile = 0; - char buf[PATH_MAX + 1]; + char buf[PATH_MAX]; visilen = (sources.i + sizeof(*visited) * CHAR_BIT - 1) / (sizeof(*visited) * CHAR_BIT); visited = Malloc(visilen * sizeof(*visited)); for (i = 0; i < sources.i; ++i) { path = names + sauces[i].name; if (!IsObjectSource(path)) continue; + if (startswith(path, genroot)) continue; Appendw(&makefile, '\n'); - if (!startswith(path, "o/")) { - Appends(&makefile, buildroot); - } + Appends(&makefile, buildroot); Appends(&makefile, StripExt(buf, path)); Appendw(&makefile, READ64LE(".o: \\\n\t")); Appends(&makefile, path); @@ -441,7 +663,7 @@ static char *Explore(void) { } int main(int argc, char *argv[]) { - int fd; + int fd = 1; ssize_t rc; size_t i, n; char *makefile; @@ -454,7 +676,8 @@ int main(int argc, char *argv[]) { LoadRelationships(argc, argv); Crunch(); makefile = Explore(); - if ((fd = open(outpath, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) { + if (outpath && + (fd = open(outpath, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) { DieSys(outpath); } n = appendz(makefile).i; @@ -463,7 +686,7 @@ int main(int argc, char *argv[]) { DieSys(outpath); } } - if (close(fd)) { + if (outpath && close(fd)) { DieSys(outpath); } free(makefile); diff --git a/tool/net/net.mk b/tool/net/net.mk index 82b262d92..b1869d369 100644 --- a/tool/net/net.mk +++ b/tool/net/net.mk @@ -6,6 +6,7 @@ PKGS += TOOL_NET TOOL_NET_FILES := $(wildcard tool/net/*) TOOL_NET_SRCS = $(filter %.c,$(TOOL_NET_FILES)) TOOL_NET_HDRS = $(filter %.h,$(TOOL_NET_FILES)) +TOOL_NET_INCS = $(filter %.inc,$(TOOL_NET_FILES)) TOOL_NET_OBJS = \ $(TOOL_NET_SRCS:%.c=o/$(MODE)/%.o) diff --git a/tool/viz/rlimit.c b/tool/viz/rlimit.c index 2dac60cf2..0cedfe648 100644 --- a/tool/viz/rlimit.c +++ b/tool/viz/rlimit.c @@ -7,13 +7,14 @@ │ • http://creativecommons.org/publicdomain/zero/1.0/ │ ╚─────────────────────────────────────────────────────────────────*/ #endif -#include "libc/calls/calls.h" -#include "libc/intrin/strace.internal.h" #include "libc/calls/struct/rlimit.h" +#include "libc/calls/calls.h" #include "libc/errno.h" #include "libc/intrin/describeflags.internal.h" +#include "libc/intrin/strace.internal.h" #include "libc/log/color.internal.h" #include "libc/macros.internal.h" +#include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" #include "libc/sysv/consts/rlim.h"