mirror of
https://github.com/jart/cosmopolitan.git
synced 2026-11-08 08:08:04 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3093f0e467 | ||
|
|
3609f65de3 | ||
|
|
9906f299bb | ||
|
|
1d8f37a2f0 | ||
|
|
e677460d14 | ||
|
|
4937843f70 | ||
|
|
b003888696 | ||
|
|
2ca491dc56 | ||
|
|
9aa353d88b | ||
|
|
c67faf61df | ||
|
|
165c6b37e2 | ||
|
|
dcd626edf8 | ||
|
|
f032b5570b | ||
|
|
ea081b262c | ||
|
|
fae1c32267 | ||
|
|
9b6718ac99 | ||
|
|
cd672e251f | ||
|
|
500a47bc2f | ||
|
|
e4d25d68e4 | ||
|
|
f31a98d50a | ||
|
|
2816df59b2 | ||
|
|
a05ce3ad9d | ||
|
|
7c8df05042 | ||
|
|
4c77acdfcf | ||
|
|
b74b974cfd | ||
|
|
07cef612c3 | ||
|
|
deaef81463 | ||
|
|
c638eabfe0 | ||
|
|
8e68384e15 | ||
|
|
2f4ca71f26 | ||
|
|
07004ebf04 | ||
|
|
086d7006da | ||
|
|
0a51241f7a | ||
|
|
c68f6599e5 | ||
|
|
af3f62a71a | ||
|
|
6cf9b9e0fc | ||
|
|
1d4b452839 | ||
|
|
c2db3b703a | ||
|
|
edb03b89d8 | ||
|
|
7724664b13 | ||
|
|
1df4296208 | ||
|
|
ce9aeb2aed | ||
|
|
ed93fc3dd7 | ||
|
|
5f61d273e4 | ||
|
|
bf3531de81 | ||
|
|
3b0ea2db4d | ||
|
|
f029375d39 | ||
|
|
9b87dd2b87 | ||
|
|
787b04f752 | ||
|
|
0768807935 | ||
|
|
0b59f01b43 | ||
|
|
cf70a44756 | ||
|
|
a52792c59f | ||
|
|
65c9b28e99 | ||
|
|
4292348707 | ||
|
|
2ec20b6c4c | ||
|
|
47183551d6 | ||
|
|
42891e82bb | ||
|
|
624119ea38 | ||
|
|
2f3c6e7cc3 | ||
|
|
13b9ecd537 | ||
|
|
6659981457 | ||
|
|
ae2a7ac844 | ||
|
|
793393a341 | ||
|
|
952b9009e8 | ||
|
|
8f18b3ad65 | ||
|
|
56e0fd9d1d |
No files matched your search
@@ -0,0 +1,23 @@
|
||||
# Run this command to always ignore formatting commits in git blame
|
||||
# git config blame.ignoreRevsFile .git-blame-ignore-revs
|
||||
|
||||
# Ran clang-format
|
||||
f032b5570b4cd87c6bb4abb54c0b98e69c939955
|
||||
# Applied clang-format update to repo
|
||||
6e6fc38935054db0534d5af4fb99c6193305b946
|
||||
# revert retabbing
|
||||
2b315626f3af765cdfbc61114647412cdb798b3a
|
||||
# more modeline errata
|
||||
3a8e01a77a7c97af0b16fb1651b230cee7f7d4c6
|
||||
# fix more vi modelines
|
||||
2fc507c98f53a76718f61f9a36602f86b5ac0cc9
|
||||
# flip et/noet in modelines
|
||||
e16a7d8f3b8f906c3ef76e79f57f3adfc7f25186
|
||||
# fix vi modelines
|
||||
394d998315f613a888cc6b6c051d4163bdf5cd6f
|
||||
# clang-format
|
||||
c0eacf2eb1e1c0b3bd4f71f12fef258f5b249c3f
|
||||
# ape-m1 formatting cleanup
|
||||
da8baf2aa5ce93b958aca90a0ae69f537806324b
|
||||
# Run clang-format on most sources
|
||||
369f9740de4534c28d0e81ab2afc99decbb9a3e6
|
||||
Vendored
-108
@@ -1,108 +0,0 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Win32",
|
||||
"includePath": [
|
||||
"${workspaceFolder}"
|
||||
],
|
||||
"cStandard": "c11",
|
||||
"cppStandard": "c++11",
|
||||
"forcedInclude": ["${workspaceFolder}/.vscode/vscode.h"],
|
||||
"defines": [
|
||||
"libcesque=",
|
||||
"pureconst=",
|
||||
"paramsnonnull(x)=",
|
||||
"alignas(x)",
|
||||
"alignof(x)",
|
||||
"artificial=",
|
||||
"__wur=",
|
||||
"mayalias=",
|
||||
"forceinline=",
|
||||
"forcealign(x)=",
|
||||
"scanfesque(x)=",
|
||||
"strftimeesque(x)=",
|
||||
"wontreturn=",
|
||||
"textreal=",
|
||||
"mallocesque=",
|
||||
"callocesque=",
|
||||
"vallocesque=",
|
||||
"reallocesque=",
|
||||
"strlenesque=",
|
||||
"memcpyesque=",
|
||||
"hasatleast=",
|
||||
"noinline=",
|
||||
"textexit=",
|
||||
"returnstwice=",
|
||||
"textwindows=",
|
||||
"privileged=",
|
||||
"dontinstrument=",
|
||||
"nodebuginfo=",
|
||||
"interruptfn=",
|
||||
"optimizespeed=",
|
||||
"forcealignargpointer=",
|
||||
"dontasan=",
|
||||
"dontubsan=",
|
||||
"donothing=",
|
||||
"nosideeffect=",
|
||||
"unreachable=",,
|
||||
"notpossible=",
|
||||
"thatispacked=",
|
||||
"dontthrow=",
|
||||
"dontcallback=",
|
||||
"relegated=",
|
||||
"hidden=",
|
||||
"textstartup=",
|
||||
"returnsnonnull=",
|
||||
"returnspointerwithnoaliases=",
|
||||
"printfesque(x)=",
|
||||
"attributeallocsize(x)=",
|
||||
"returnsaligned(x)=",
|
||||
"attributeallocalign(x)=",
|
||||
"nullterminated(x)="
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}"
|
||||
],
|
||||
"cStandard": "gnu17",
|
||||
"compilerPath": "${workspaceFolder}/o/third_party/gcc/bin/x86_64-linux-musl-gcc",
|
||||
"compilerArgs": [
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
"-fdebug-prefix-map=${workspaceFolder}=",
|
||||
"-frecord-gcc-switches",
|
||||
"-Wa,-W",
|
||||
"-Wa,-I.",
|
||||
"-Wa,--noexecstack",
|
||||
"-Og",
|
||||
"-g",
|
||||
"-gdescribe-dies",
|
||||
"-msse3",
|
||||
"-mno-red-zone",
|
||||
"-fno-math-errno",
|
||||
"-fno-trapping-math",
|
||||
"-fno-fp-int-builtin-inexact",
|
||||
"-fno-ident",
|
||||
"-fno-common",
|
||||
"-fno-gnu-unique",
|
||||
"-fstrict-aliasing",
|
||||
"-fstrict-overflow",
|
||||
"-fno-semantic-interposition",
|
||||
"-mno-omit-leaf-frame-pointer",
|
||||
"-fno-jump-tables",
|
||||
"-nostdinc",
|
||||
"-iquote."
|
||||
],
|
||||
"forcedInclude": [
|
||||
"libc/integral/normalize.inc"
|
||||
],
|
||||
"defines": [
|
||||
"COSMO",
|
||||
"MODE="
|
||||
]
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
Vendored
-2
@@ -1,2 +0,0 @@
|
||||
#define __VSCODE_INTELLISENSE__ 1
|
||||
#include "libc/integral/normalize.inc"
|
||||
@@ -133,7 +133,7 @@ endif
|
||||
|
||||
ifneq ($(findstring aarch64,$(MODE)),)
|
||||
ARCH = aarch64
|
||||
HOSTS ?= pi pi5 studio freebsdarm
|
||||
HOSTS ?= pi studio freebsdarm
|
||||
else
|
||||
ARCH = x86_64
|
||||
HOSTS ?= freebsd rhel7 xnu openbsd netbsd win10
|
||||
@@ -149,9 +149,9 @@ export MODE
|
||||
export SOURCE_DATE_EPOCH
|
||||
export TMPDIR
|
||||
|
||||
COSMOCC = .cosmocc/3.3.3
|
||||
COSMOCC = .cosmocc/3.3.5
|
||||
TOOLCHAIN = $(COSMOCC)/bin/$(ARCH)-linux-cosmo-
|
||||
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.3.3 e4d0fa63cd79cc3bfff6c2d015f1776db081409907625aea8ad40cefc1996d08)
|
||||
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.3.5 db78fd8d3f8706e9dff4be72bf71d37a3f12062f212f407e1c33bc4af3780dd0)
|
||||
|
||||
AS = $(TOOLCHAIN)as
|
||||
CC = $(TOOLCHAIN)gcc
|
||||
@@ -174,6 +174,7 @@ all: o
|
||||
o: o/$(MODE)
|
||||
o/$(MODE): \
|
||||
o/$(MODE)/ape \
|
||||
o/$(MODE)/ctl \
|
||||
o/$(MODE)/dsp \
|
||||
o/$(MODE)/net \
|
||||
o/$(MODE)/libc \
|
||||
@@ -255,6 +256,7 @@ include third_party/nsync/mem/BUILD.mk # │ You can now use stdio
|
||||
include libc/proc/BUILD.mk # │ You can now use threads
|
||||
include libc/dlopen/BUILD.mk # │ You can now use processes
|
||||
include libc/thread/BUILD.mk # │ You can finally call malloc()
|
||||
include ctl/BUILD.mk # │
|
||||
include third_party/zlib/BUILD.mk # │
|
||||
include libc/stdio/BUILD.mk # │
|
||||
include tool/hello/BUILD.mk # │
|
||||
@@ -299,6 +301,7 @@ include tool/viz/lib/BUILD.mk
|
||||
include tool/args/BUILD.mk
|
||||
include test/math/BUILD.mk
|
||||
include test/posix/BUILD.mk
|
||||
include test/ctl/BUILD.mk
|
||||
include test/libcxx/BUILD.mk
|
||||
include test/tool/args/BUILD.mk
|
||||
include third_party/linenoise/BUILD.mk
|
||||
@@ -362,7 +365,6 @@ include test/libc/fmt/BUILD.mk
|
||||
include test/libc/time/BUILD.mk
|
||||
include test/libc/proc/BUILD.mk
|
||||
include test/libc/stdio/BUILD.mk
|
||||
include test/libc/release/BUILD.mk
|
||||
include test/libc/BUILD.mk
|
||||
include test/net/http/BUILD.mk
|
||||
include test/net/https/BUILD.mk
|
||||
@@ -452,6 +454,7 @@ COSMOPOLITAN_OBJECTS = \
|
||||
LIBC_THREAD \
|
||||
LIBC_PROC \
|
||||
THIRD_PARTY_NSYNC_MEM \
|
||||
CTL \
|
||||
LIBC_MEM \
|
||||
THIRD_PARTY_DLMALLOC \
|
||||
LIBC_DLOPEN \
|
||||
@@ -520,6 +523,7 @@ COSMOPOLITAN_H_PKGS = \
|
||||
|
||||
COSMOCC_PKGS = \
|
||||
$(COSMOPOLITAN_H_PKGS) \
|
||||
CTL \
|
||||
THIRD_PARTY_AARCH64 \
|
||||
THIRD_PARTY_LIBCXX \
|
||||
THIRD_PARTY_LIBCXXABI \
|
||||
@@ -542,15 +546,6 @@ COSMOPOLITAN_H_ROOT_HDRS = \
|
||||
libc/integral/normalize.inc \
|
||||
$(foreach x,$(COSMOPOLITAN_H_PKGS),$($(x)_HDRS))
|
||||
|
||||
o/cosmopolitan.h.txt: Makefile
|
||||
$(file >$@, $(call uniq,$(COSMOPOLITAN_H_ROOT_HDRS)))
|
||||
|
||||
o/cosmopolitan.h: o/cosmopolitan.h.txt \
|
||||
$(wildcard libc/integral/*) \
|
||||
$(foreach x,$(COSMOPOLITAN_H_PKGS),$($(x)_HDRS)) \
|
||||
$(foreach x,$(COSMOPOLITAN_H_PKGS),$($(x)_INCS))
|
||||
@$(COMPILE) -AROLLUP -T$@ build/bootstrap/rollup @$< >>$@
|
||||
|
||||
o/cosmopolitan.html: private .UNSANDBOXED = 1
|
||||
o/cosmopolitan.html: \
|
||||
o/$(MODE)/third_party/chibicc/chibicc.dbg \
|
||||
@@ -572,7 +567,6 @@ $(SRCS): \
|
||||
|
||||
ifeq ($(ARCH), x86_64)
|
||||
TOOLCHAIN_ARTIFACTS = \
|
||||
o/cosmopolitan.h \
|
||||
o/$(MODE)/ape/ape.lds \
|
||||
o/$(MODE)/libc/crt/crt.o \
|
||||
o/$(MODE)/ape/ape.elf \
|
||||
|
||||
+18
-1
@@ -254,7 +254,24 @@ o/$(MODE)/ape: $(APE_CHECKS) \
|
||||
endif
|
||||
|
||||
# these assembly files are safe to build on aarch64
|
||||
o/$(MODE)/ape/ape.o: ape/ape.S
|
||||
o/$(MODE)/ape/ape.o: \
|
||||
ape/ape.S \
|
||||
ape/ape.h \
|
||||
libc/dce.h \
|
||||
libc/elf/def.h \
|
||||
ape/relocations.h \
|
||||
libc/thread/tls.h \
|
||||
ape/ape.internal.h \
|
||||
ape/macros.internal.h \
|
||||
libc/macho.internal.h \
|
||||
libc/macros.internal.h \
|
||||
libc/sysv/consts/prot.h \
|
||||
libc/nt/pedef.internal.h \
|
||||
libc/runtime/pc.internal.h \
|
||||
libc/runtime/e820.internal.h \
|
||||
libc/runtime/mman.internal.h \
|
||||
libc/nexgen32e/uart.internal.h \
|
||||
libc/calls/metalfile.internal.h
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
|
||||
o/$(MODE)/ape/ape.lds: \
|
||||
|
||||
+3
-4
@@ -293,7 +293,6 @@ _tdata_size = _tdata_end - _tdata_start;
|
||||
_tbss_size = _tbss_end - _tbss_start;
|
||||
_tbss_offset = _tbss_start - _tdata_start;
|
||||
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
|
||||
_tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
|
||||
|
||||
ASSERT(ALIGNOF(.tdata) <= TLS_ALIGNMENT && ALIGNOF(.tbss) <= TLS_ALIGNMENT,
|
||||
"_Thread_local _Alignof can't exceed TLS_ALIGNMENT");
|
||||
_tdata_align = ALIGNOF(.tdata);
|
||||
_tbss_align = ALIGNOF(.tbss);
|
||||
_tls_align = MAX(TLS_ALIGNMENT, MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)));
|
||||
@@ -1036,7 +1036,7 @@ ape_pe: .ascin "PE",4
|
||||
.quad ape_pe_base // ImageBase
|
||||
.long ape_pe_sectionalignment // SectionAlignment
|
||||
.long ape_pe_filealignment // FileAlignment
|
||||
.short v_ntversion // MajorOperatingSystemVersion
|
||||
.short 10 // MajorOperatingSystemVersion
|
||||
.short 0 // MinorOperatingSystemVersion
|
||||
.short 0 // MajorImageVersion
|
||||
.short 0 // MinorImageVersion
|
||||
|
||||
+3
-2
@@ -553,7 +553,9 @@ _tdata_size = _tdata_end - _tdata_start;
|
||||
_tbss_size = _tbss_end - _tbss_start;
|
||||
_tbss_offset = _tbss_start - _tdata_start;
|
||||
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
|
||||
_tls_align = 1;
|
||||
_tdata_align = ALIGNOF(.tdata);
|
||||
_tbss_align = ALIGNOF(.tbss);
|
||||
_tls_align = MAX(TLS_ALIGNMENT, MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)));
|
||||
|
||||
ape_cod_offset = 0;
|
||||
ape_cod_vaddr = ADDR(.head);
|
||||
@@ -713,7 +715,6 @@ ape_idataz = LINK_WINDOWS ? RVA(ape_idata_iat) : 0;
|
||||
ape_idata_iatsize = LINK_WINDOWS ? ape_idata_iatend - ape_idata_iat : 0;
|
||||
ape_idata = LINK_WINDOWS ? RVA(ape_idata_idt) : 0;
|
||||
ape_idata_idtsize = LINK_WINDOWS ? ape_idata_idtend - ape_idata_idt : 0;
|
||||
v_ntversion = LINK_WINDOWS ? 6 : 1;
|
||||
v_ntdllchar = LINK_WINDOWS ? 288 : 0;
|
||||
v_ntsubversion = LINK_WINDOWS ? 6 : 5;
|
||||
v_ntsubsystem = (LINK_WINDOWS
|
||||
|
||||
+11
-4
@@ -137,13 +137,20 @@ if [ x"$(uname -s)" = xLinux ]; then
|
||||
echo done >&2
|
||||
fi
|
||||
|
||||
uname_r="$(uname -r)"
|
||||
if printf '%s\n%s\n' 5.12 "$uname_r" | sort -CV; then
|
||||
FLAGS=FP
|
||||
else
|
||||
FLAGS=F
|
||||
fi
|
||||
|
||||
echo >&2
|
||||
echo registering APE with binfmt_misc >&2
|
||||
echo you may need to edit configs to persist across reboot >&2
|
||||
echo '$SUDO sh -c "echo '"'"':APE:M::MZqFpD::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
||||
$SUDO sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||
echo '$SUDO sh -c "echo '"'"':APE-jart:M::jartsr::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
||||
$SUDO sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||
echo '$SUDO sh -c "echo '"'"':APE:M::MZqFpD::/usr/bin/ape:'"$FLAGS'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
||||
$SUDO sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:$FLAGS' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||
echo '$SUDO sh -c "echo '"'"':APE-jart:M::jartsr::/usr/bin/ape:'"$FLAGS'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
||||
$SUDO sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:$FLAGS' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||
echo done >&2
|
||||
|
||||
if [ x"$(cat /proc/sys/fs/binfmt_misc/status)" = xdisabled ]; then
|
||||
|
||||
+15
-26
@@ -132,7 +132,7 @@
|
||||
#define SHSTUB2(SYM, X) \
|
||||
HIDDEN(SYM##_bcs0 = BCD_LEFT(X)); \
|
||||
HIDDEN(SYM##_bcs1 = BCD_RIGHT(X))
|
||||
#define BCD_SMEAR(X) ((X) + (X) * 10000)
|
||||
#define BCD_SMEAR(X) ((X) + (X)*10000)
|
||||
#define BCD_LEFT(X) \
|
||||
(((X)) < 10000 ? BCD_RIGHT(BCD_SMEAR(X)) | 0x10 \
|
||||
: (X) < 100000 ? BCD_RIGHT(BCD_SMEAR((X) / 10)) \
|
||||
@@ -140,23 +140,16 @@
|
||||
: (X) < 10000000 ? BCD_RIGHT(BCD_SMEAR((X) / 1000)) \
|
||||
: (X) < 100000000 ? BCD_RIGHT(BCD_SMEAR((X) / 10000)) \
|
||||
: 0xffffffffffffffff)
|
||||
#define BCD_RIGHT(X) \
|
||||
(((X)) < 10000 ? 0x20202020 \
|
||||
: (X) < 100000 ? 0x20202030 + \
|
||||
(X) % 10 \
|
||||
: (X) < 1000000 ? 0x20203030 + \
|
||||
((X) / 10) % 10 + \
|
||||
(X) % 10 * 0x100 \
|
||||
: (X) < 10000000 ? 0x20303030 + \
|
||||
((X) / 100) % 10 + \
|
||||
((X) / 10) % 10 * 0x100 + \
|
||||
(X) % 10 * 0x10000 \
|
||||
: (X) < 100000000 ? 0x30303030 + \
|
||||
((X) / 1000) % 10 + \
|
||||
((X) / 100) % 10 * 0x100 + \
|
||||
((X) / 10) % 10 * 0x10000 + \
|
||||
(X) % 10 * 0x1000000 \
|
||||
: 0xffffffffffffffff)
|
||||
#define BCD_RIGHT(X) \
|
||||
(((X)) < 10000 ? 0x20202020 \
|
||||
: (X) < 100000 ? 0x20202030 + (X) % 10 \
|
||||
: (X) < 1000000 ? 0x20203030 + ((X) / 10) % 10 + (X) % 10 * 0x100 \
|
||||
: (X) < 10000000 ? 0x20303030 + ((X) / 100) % 10 + \
|
||||
((X) / 10) % 10 * 0x100 + (X) % 10 * 0x10000 \
|
||||
: (X) < 100000000 \
|
||||
? 0x30303030 + ((X) / 1000) % 10 + ((X) / 100) % 10 * 0x100 + \
|
||||
((X) / 10) % 10 * 0x10000 + (X) % 10 * 0x1000000 \
|
||||
: 0xffffffffffffffff)
|
||||
|
||||
/**
|
||||
* Laying out the GDT entries for a TSS for bare metal operation.
|
||||
@@ -165,15 +158,11 @@
|
||||
HIDDEN(SYM##_desc_ent0 = TSSDESC_ENT0(BASE, LIM)); \
|
||||
HIDDEN(SYM##_desc_ent1 = TSSDESC_ENT1(BASE)); \
|
||||
ASSERT((LIM) >= 0 && (LIM) <= 0xffff, "bare metal TSS is suspiciously fat")
|
||||
#define TSSDESC_ENT0(BASE, LIM) \
|
||||
(((LIM) << 0 & 0x000000000000ffff) | \
|
||||
((BASE) << 16 & 0x000000ffffff0000) | \
|
||||
0x89 << 40 | \
|
||||
((LIM) >> 16 << 48 & 0x000f000000000000) | \
|
||||
0x2 << 52 | \
|
||||
#define TSSDESC_ENT0(BASE, LIM) \
|
||||
(((LIM) << 0 & 0x000000000000ffff) | ((BASE) << 16 & 0x000000ffffff0000) | \
|
||||
0x89 << 40 | ((LIM) >> 16 << 48 & 0x000f000000000000) | 0x2 << 52 | \
|
||||
((BASE) >> 24 << 56 & 0xff00000000000000))
|
||||
#define TSSDESC_ENT1(BASE) \
|
||||
((BASE) >> 32 << 0 & 0x00000000ffffffff)
|
||||
#define TSSDESC_ENT1(BASE) ((BASE) >> 32 << 0 & 0x00000000ffffffff)
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* APE_MACROS_H_ */
|
||||
@@ -16,6 +16,8 @@ extern unsigned char _tdata_end[] __attribute__((__weak__));
|
||||
extern unsigned char _tbss_start[] __attribute__((__weak__));
|
||||
extern unsigned char _tbss_end[] __attribute__((__weak__));
|
||||
extern unsigned char _tls_align[] __attribute__((__weak__));
|
||||
extern unsigned char _tdata_align[] __attribute__((__weak__));
|
||||
extern unsigned char _tbss_align[] __attribute__((__weak__));
|
||||
extern unsigned char __test_start[] __attribute__((__weak__));
|
||||
extern unsigned char __ro[] __attribute__((__weak__));
|
||||
extern unsigned char __data_start[] __attribute__((__weak__));
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
+11
-11
@@ -11,20 +11,20 @@
|
||||
#
|
||||
ifeq ($(MODE),)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CCFLAGS += -O2 $(BACKTRACES)
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||
TARGET_ARCH ?= -msse3
|
||||
endif
|
||||
ifeq ($(MODE), x86_64)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CCFLAGS += -O2 $(BACKTRACES)
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||
endif
|
||||
ifeq ($(MODE), aarch64)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CCFLAGS += -O2 $(BACKTRACES)
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||
endif
|
||||
@@ -38,13 +38,13 @@ endif
|
||||
#
|
||||
ifeq ($(MODE), zero)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
OVERRIDE_CFLAGS += -O0
|
||||
OVERRIDE_CXXFLAGS += -O0
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||
endif
|
||||
ifeq ($(MODE), aarch64-zero)
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
OVERRIDE_CFLAGS += -O0 -fdce
|
||||
OVERRIDE_CXXFLAGS += -O0 -fdce
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||
@@ -81,7 +81,7 @@ endif
|
||||
#
|
||||
ifeq ($(MODE), opt)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -O3 -fmerge-all-constants
|
||||
TARGET_ARCH ?= -march=native
|
||||
@@ -98,7 +98,7 @@ endif
|
||||
# - Turns off support for other operating systems
|
||||
#
|
||||
ifeq ($(MODE), optlinux)
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG -DSUPPORT_VECTOR=1
|
||||
CONFIG_CCFLAGS += -O3 -fmerge-all-constants
|
||||
CONFIG_COPTS += -mred-zone
|
||||
@@ -140,7 +140,7 @@ endif
|
||||
#
|
||||
ifeq ($(MODE), asan)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CPPFLAGS += -D__SANITIZE_ADDRESS__
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -O2 -DSYSDEBUG
|
||||
CONFIG_COPTS += -fsanitize=address
|
||||
@@ -160,7 +160,7 @@ endif
|
||||
#
|
||||
ifeq ($(MODE), dbg)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_ADDRESS__ -D__SANITIZE_UNDEFINED__
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline
|
||||
CONFIG_COPTS += -fsanitize=address -fsanitize=undefined
|
||||
@@ -170,7 +170,7 @@ QUOTA ?= -C64 -L300
|
||||
endif
|
||||
ifeq ($(MODE), aarch64-dbg)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_UNDEFINED__
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline -fdce
|
||||
CONFIG_COPTS += -fsanitize=undefined
|
||||
@@ -189,7 +189,7 @@ endif
|
||||
#
|
||||
ifeq ($(MODE), sysv)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -O2
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG -DSUPPORT_VECTOR=121
|
||||
TARGET_ARCH ?= -msse3
|
||||
|
||||
@@ -60,13 +60,10 @@ TMPSAFE = $(TMPDIR)/
|
||||
endif
|
||||
|
||||
BACKTRACES = \
|
||||
-fno-schedule-insns2 \
|
||||
-fno-optimize-sibling-calls \
|
||||
-mno-omit-leaf-frame-pointer
|
||||
|
||||
ifneq ($(ARCH), aarch64)
|
||||
BACKTRACES += -fno-schedule-insns2
|
||||
endif
|
||||
|
||||
SANITIZER = \
|
||||
-fsanitize=address
|
||||
|
||||
@@ -148,12 +145,14 @@ DEFAULT_CFLAGS = \
|
||||
-std=gnu2x
|
||||
|
||||
DEFAULT_CXXFLAGS = \
|
||||
-std=gnu++20 \
|
||||
-fno-rtti \
|
||||
-fno-exceptions \
|
||||
-fuse-cxa-atexit \
|
||||
-Wno-int-in-bool-context \
|
||||
-Wno-narrowing \
|
||||
-Wno-literal-suffix
|
||||
-Wno-literal-suffix \
|
||||
-isystem third_party/libcxx
|
||||
|
||||
DEFAULT_ASFLAGS = \
|
||||
-W \
|
||||
@@ -260,12 +259,12 @@ LD.libs = \
|
||||
$(LIBS)
|
||||
|
||||
COMPILE.c.flags = $(cc.flags) $(copt.flags) $(cpp.flags) $(c.flags)
|
||||
COMPILE.cxx.flags = $(cc.flags) $(copt.flags) $(cpp.flags) $(cxx.flags)
|
||||
COMPILE.cxx.flags = $(cc.flags) $(copt.flags) $(cxx.flags) $(cpp.flags)
|
||||
COMPILE.i.flags = $(cc.flags) $(copt.flags) $(c.flags)
|
||||
COMPILE.ii.flags = $(cc.flags) $(copt.flags) $(cxx.flags)
|
||||
LINK.flags = $(DEFAULT_LDFLAGS) $(CONFIG_LDFLAGS) $(LDFLAGS)
|
||||
OBJECTIFY.c.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags) $(copt.flags) $(c.flags)
|
||||
OBJECTIFY.cxx.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags) $(copt.flags) $(cxx.flags)
|
||||
OBJECTIFY.cxx.flags = $(cc.flags) $(o.flags) $(S.flags) $(cxx.flags) $(cpp.flags) $(copt.flags)
|
||||
OBJECTIFY.s.flags = $(ASONLYFLAGS) $(s.flags)
|
||||
OBJECTIFY.S.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags)
|
||||
PREPROCESS.flags = -E $(copt.flags) $(cc.flags) $(cpp.flags)
|
||||
|
||||
+8
-8
@@ -6,14 +6,14 @@ if [ -n "$OBJDUMP" ]; then
|
||||
fi
|
||||
|
||||
find_objdump() {
|
||||
if [ -x .cosmocc/3.3.2/bin/$1-linux-cosmo-objdump ]; then
|
||||
OBJDUMP=.cosmocc/3.3.2/bin/$1-linux-cosmo-objdump
|
||||
elif [ -x .cosmocc/3.3.2/bin/$1-linux-musl-objdump ]; then
|
||||
OBJDUMP=.cosmocc/3.3.2/bin/$1-linux-musl-objdump
|
||||
elif [ -x "$COSMO/.cosmocc/3.3.2/bin/$1-linux-cosmo-objdump" ]; then
|
||||
OBJDUMP="$COSMO/.cosmocc/3.3.2/bin/$1-linux-cosmo-objdump"
|
||||
elif [ -x "$COSMO/.cosmocc/3.3.2/bin/$1-linux-musl-objdump" ]; then
|
||||
OBJDUMP="$COSMO/.cosmocc/3.3.2/bin/$1-linux-musl-objdump"
|
||||
if [ -x .cosmocc/3.3.5/bin/$1-linux-cosmo-objdump ]; then
|
||||
OBJDUMP=.cosmocc/3.3.5/bin/$1-linux-cosmo-objdump
|
||||
elif [ -x .cosmocc/3.3.5/bin/$1-linux-musl-objdump ]; then
|
||||
OBJDUMP=.cosmocc/3.3.5/bin/$1-linux-musl-objdump
|
||||
elif [ -x "$COSMO/.cosmocc/3.3.5/bin/$1-linux-cosmo-objdump" ]; then
|
||||
OBJDUMP="$COSMO/.cosmocc/3.3.5/bin/$1-linux-cosmo-objdump"
|
||||
elif [ -x "$COSMO/.cosmocc/3.3.5/bin/$1-linux-musl-objdump" ]; then
|
||||
OBJDUMP="$COSMO/.cosmocc/3.3.5/bin/$1-linux-musl-objdump"
|
||||
else
|
||||
echo "error: toolchain not found (try running 'cosmocc --update' or 'make' in the cosmo monorepo)" >&2
|
||||
exit 1
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
BasedOnStyle: Mozilla
|
||||
IndentWidth: 4
|
||||
ColumnLimit: 80
|
||||
---
|
||||
Language: Cpp
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AlignTrailingComments: false
|
||||
AlignEscapedNewlines: DontAlign
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
FixNamespaceComments: true
|
||||
---
|
||||
@@ -0,0 +1,48 @@
|
||||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
|
||||
|
||||
PKGS += CTL
|
||||
|
||||
CTL_ARTIFACTS += CTL_A
|
||||
CTL = $(CTL_A_DEPS) $(CTL_A)
|
||||
CTL_A = o/$(MODE)/ctl/ctl.a
|
||||
CTL_A_FILES := $(wildcard ctl/*)
|
||||
CTL_A_HDRS = $(filter %.h,$(CTL_A_FILES))
|
||||
CTL_A_SRCS = $(filter %.cc,$(CTL_A_FILES))
|
||||
CTL_A_OBJS = $(CTL_A_SRCS:%.cc=o/$(MODE)/%.o)
|
||||
|
||||
CTL_A_CHECKS = \
|
||||
$(CTL_A).pkg \
|
||||
$(CTL_A_HDRS:%=o/$(MODE)/%.okk) \
|
||||
|
||||
CTL_A_DIRECTDEPS = \
|
||||
LIBC_INTRIN \
|
||||
LIBC_MEM \
|
||||
LIBC_STR \
|
||||
|
||||
CTL_A_DEPS := $(call uniq,$(foreach x,$(CTL_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(CTL_A): ctl/ \
|
||||
$(CTL_A).pkg \
|
||||
$(CTL_A_OBJS)
|
||||
|
||||
$(CTL_A).pkg: \
|
||||
$(CTL_A_OBJS) \
|
||||
$(foreach x,$(CTL_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
$(CTL_A_OBJS): private \
|
||||
OVERRIDE_CXXFLAGS += \
|
||||
-Wframe-larger-than=4096 \
|
||||
-Walloca-larger-than=4096 \
|
||||
-ffunction-sections \
|
||||
-fdata-sections \
|
||||
|
||||
CTL_LIBS = $(foreach x,$(CTL_ARTIFACTS),$($(x)))
|
||||
CTL_SRCS = $(foreach x,$(CTL_ARTIFACTS),$($(x)_SRCS))
|
||||
CTL_HDRS = $(foreach x,$(CTL_ARTIFACTS),$($(x)_HDRS))
|
||||
CTL_CHECKS = $(foreach x,$(CTL_ARTIFACTS),$($(x)_CHECKS))
|
||||
CTL_OBJS = $(foreach x,$(CTL_ARTIFACTS),$($(x)_OBJS))
|
||||
$(CTL_OBJS): $(BUILD_FILES) ctl/BUILD.mk
|
||||
|
||||
.PHONY: o/$(MODE)/ctl
|
||||
o/$(MODE)/ctl: $(CTL_CHECKS)
|
||||
+5015
File diff suppressed because it is too large.
Load diff
+129
@@ -0,0 +1,129 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef COSMOPOLITAN_CTL_OPTIONAL_H_
|
||||
#define COSMOPOLITAN_CTL_OPTIONAL_H_
|
||||
#include <__utility/forward.h>
|
||||
#include <__utility/move.h>
|
||||
#include <__utility/swap.h>
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
class optional
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
~optional() = default;
|
||||
|
||||
optional() noexcept : present_(false)
|
||||
{
|
||||
}
|
||||
|
||||
optional(const T& value) : present_(true), value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
optional(T&& value) : present_(true), value_(std::move(value))
|
||||
{
|
||||
}
|
||||
|
||||
optional(const optional& other) : present_(other.present_)
|
||||
{
|
||||
if (present_)
|
||||
new (&value_) T(other.value_);
|
||||
}
|
||||
|
||||
optional(optional&& other) noexcept : present_(other.present_)
|
||||
{
|
||||
if (present_)
|
||||
value_ = std::move(other.value_);
|
||||
}
|
||||
|
||||
optional& operator=(const optional& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
present_ = other.present_;
|
||||
if (present_)
|
||||
value_ = other.value_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
optional& operator=(optional&& other) noexcept
|
||||
{
|
||||
if (this != &other) {
|
||||
present_ = other.present_;
|
||||
if (present_)
|
||||
value_ = std::move(other.value_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
T& value() &
|
||||
{
|
||||
if (!present_)
|
||||
__builtin_trap();
|
||||
return value_;
|
||||
}
|
||||
|
||||
const T& value() const&
|
||||
{
|
||||
if (!present_)
|
||||
__builtin_trap();
|
||||
return value_;
|
||||
}
|
||||
|
||||
T&& value() &&
|
||||
{
|
||||
if (!present_)
|
||||
__builtin_trap();
|
||||
return std::move(value_);
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept
|
||||
{
|
||||
return present_;
|
||||
}
|
||||
|
||||
bool has_value() const noexcept
|
||||
{
|
||||
return present_;
|
||||
}
|
||||
|
||||
void reset() noexcept
|
||||
{
|
||||
if (present_) {
|
||||
value_.~T();
|
||||
present_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void emplace(Args&&... args)
|
||||
{
|
||||
present_ = true;
|
||||
value_ = T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void swap(optional& other) noexcept
|
||||
{
|
||||
if (present_ && other.present_) {
|
||||
std::swap(value_, other.value_);
|
||||
} else if (present_) {
|
||||
other.emplace(std::move(value_));
|
||||
reset();
|
||||
} else if (other.present_) {
|
||||
emplace(std::move(other.value_));
|
||||
other.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool present_;
|
||||
T value_;
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // COSMOPOLITAN_CTL_OPTIONAL_H_
|
||||
@@ -0,0 +1,44 @@
|
||||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8
|
||||
//
|
||||
// Copyright 2024 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 "string.h"
|
||||
|
||||
#include <stdckdint.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace ctl {
|
||||
|
||||
string
|
||||
strcat(const string_view lhs, const string_view rhs) noexcept
|
||||
{
|
||||
string res;
|
||||
size_t need;
|
||||
if (ckd_add(&need, lhs.n, rhs.n))
|
||||
__builtin_trap();
|
||||
if (ckd_add(&need, need, 1))
|
||||
__builtin_trap();
|
||||
res.reserve(need);
|
||||
if (lhs.n)
|
||||
memcpy(res.p, lhs.p, lhs.n);
|
||||
if (rhs.n)
|
||||
memcpy(res.p + lhs.n, rhs.p, rhs.n);
|
||||
res.p[res.n = lhs.n + rhs.n] = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
@@ -0,0 +1,43 @@
|
||||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8
|
||||
//
|
||||
// Copyright 2024 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 "string_view.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace ctl {
|
||||
|
||||
int
|
||||
strcmp(const string_view lhs, const string_view rhs) noexcept
|
||||
{
|
||||
int r;
|
||||
size_t m = lhs.n;
|
||||
if ((m = rhs.n < m ? rhs.n : m)) {
|
||||
if (!m)
|
||||
return 0;
|
||||
if ((r = memcmp(lhs.p, rhs.p, m)))
|
||||
return r;
|
||||
}
|
||||
if (lhs.n == rhs.n)
|
||||
return 0;
|
||||
if (m < lhs.n)
|
||||
return +1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
+323
@@ -0,0 +1,323 @@
|
||||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8
|
||||
//
|
||||
// Copyright 2024 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 "string.h"
|
||||
|
||||
#include <__atomic/fence.h>
|
||||
#include <stdckdint.h>
|
||||
|
||||
namespace ctl {
|
||||
|
||||
string::~string() noexcept
|
||||
{
|
||||
if (n) {
|
||||
if (n >= c)
|
||||
__builtin_trap();
|
||||
if (p[n])
|
||||
__builtin_trap();
|
||||
}
|
||||
if (c && !p)
|
||||
__builtin_trap();
|
||||
free(p);
|
||||
}
|
||||
|
||||
string::string(const char* s) noexcept
|
||||
{
|
||||
append(s, strlen(s));
|
||||
}
|
||||
|
||||
string::string(const string& s) noexcept
|
||||
{
|
||||
append(s.p, s.n);
|
||||
}
|
||||
|
||||
string::string(const string_view s) noexcept
|
||||
{
|
||||
append(s.p, s.n);
|
||||
}
|
||||
|
||||
string::string(size_t size, char ch) noexcept
|
||||
{
|
||||
resize(size, ch);
|
||||
}
|
||||
|
||||
string::string(const char* s, size_t size) noexcept
|
||||
{
|
||||
append(s, size);
|
||||
}
|
||||
|
||||
const char*
|
||||
string::c_str() const noexcept
|
||||
{
|
||||
if (!n)
|
||||
return "";
|
||||
if (n >= c)
|
||||
__builtin_trap();
|
||||
if (p[n])
|
||||
__builtin_trap();
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
string::reserve(size_t c2) noexcept
|
||||
{
|
||||
char* p2;
|
||||
if (c2 < n)
|
||||
c2 = n;
|
||||
if (ckd_add(&c2, c2, 15))
|
||||
__builtin_trap();
|
||||
c2 &= -16;
|
||||
if (!(p2 = (char*)realloc(p, c2)))
|
||||
__builtin_trap();
|
||||
std::atomic_signal_fence(std::memory_order_seq_cst);
|
||||
c = c2;
|
||||
p = p2;
|
||||
}
|
||||
|
||||
void
|
||||
string::resize(size_t n2, char ch) noexcept
|
||||
{
|
||||
size_t c2;
|
||||
if (ckd_add(&c2, n2, 1))
|
||||
__builtin_trap();
|
||||
reserve(c2);
|
||||
if (n2 > n)
|
||||
memset(p + n, ch, n2 - n);
|
||||
p[n = n2] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
string::append(char ch) noexcept
|
||||
{
|
||||
if (n + 2 > c) {
|
||||
size_t c2 = c + 2;
|
||||
c2 += c2 >> 1;
|
||||
reserve(c2);
|
||||
}
|
||||
p[n++] = ch;
|
||||
p[n] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
string::grow(size_t size) noexcept
|
||||
{
|
||||
size_t need;
|
||||
if (ckd_add(&need, n, size))
|
||||
__builtin_trap();
|
||||
if (ckd_add(&need, need, 1))
|
||||
__builtin_trap();
|
||||
if (need <= c)
|
||||
return;
|
||||
size_t c2 = c;
|
||||
if (!c2) {
|
||||
c2 = need;
|
||||
} else {
|
||||
while (c2 < need)
|
||||
if (ckd_add(&c2, c2, c2 >> 1))
|
||||
__builtin_trap();
|
||||
}
|
||||
reserve(c2);
|
||||
}
|
||||
|
||||
void
|
||||
string::append(char ch, size_t size) noexcept
|
||||
{
|
||||
grow(size);
|
||||
if (size)
|
||||
memset(p + n, ch, size);
|
||||
p[n += size] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
string::append(const void* data, size_t size) noexcept
|
||||
{
|
||||
grow(size);
|
||||
if (size)
|
||||
memcpy(p + n, data, size);
|
||||
p[n += size] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
string::pop_back() noexcept
|
||||
{
|
||||
if (!n)
|
||||
__builtin_trap();
|
||||
p[--n] = 0;
|
||||
}
|
||||
|
||||
string&
|
||||
string::operator=(string&& s) noexcept
|
||||
{
|
||||
if (p != s.p) {
|
||||
if (p) {
|
||||
clear();
|
||||
append(s.p, s.n);
|
||||
} else {
|
||||
p = s.p;
|
||||
n = s.n;
|
||||
c = s.c;
|
||||
s.p = nullptr;
|
||||
s.n = 0;
|
||||
s.c = 0;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
string::operator==(const string_view s) const noexcept
|
||||
{
|
||||
if (n != s.n)
|
||||
return false;
|
||||
if (!n)
|
||||
return true;
|
||||
return !memcmp(p, s.p, n);
|
||||
}
|
||||
|
||||
bool
|
||||
string::operator!=(const string_view s) const noexcept
|
||||
{
|
||||
if (n != s.n)
|
||||
return true;
|
||||
if (!n)
|
||||
return false;
|
||||
return !!memcmp(p, s.p, n);
|
||||
}
|
||||
|
||||
bool
|
||||
string::contains(const string_view s) const noexcept
|
||||
{
|
||||
if (!s.n)
|
||||
return true;
|
||||
return !!memmem(p, n, s.p, s.n);
|
||||
}
|
||||
|
||||
bool
|
||||
string::ends_with(const string_view s) const noexcept
|
||||
{
|
||||
if (n < s.n)
|
||||
return false;
|
||||
if (!s.n)
|
||||
return true;
|
||||
return !memcmp(p + n - s.n, s.p, s.n);
|
||||
}
|
||||
|
||||
bool
|
||||
string::starts_with(const string_view s) const noexcept
|
||||
{
|
||||
if (n < s.n)
|
||||
return false;
|
||||
if (!s.n)
|
||||
return true;
|
||||
return !memcmp(p, s.p, s.n);
|
||||
}
|
||||
|
||||
size_t
|
||||
string::find(char ch, size_t pos) const noexcept
|
||||
{
|
||||
char* q;
|
||||
if ((q = (char*)memchr(p, ch, n)))
|
||||
return q - p;
|
||||
return npos;
|
||||
}
|
||||
|
||||
size_t
|
||||
string::find(const string_view s, size_t pos) const noexcept
|
||||
{
|
||||
char* q;
|
||||
if (pos > n)
|
||||
__builtin_trap();
|
||||
if ((q = (char*)memmem(p + pos, n - pos, s.p, s.n)))
|
||||
return q - p;
|
||||
return npos;
|
||||
}
|
||||
|
||||
string
|
||||
string::substr(size_t pos, size_t count) const noexcept
|
||||
{
|
||||
size_t last;
|
||||
if (pos > n)
|
||||
__builtin_trap();
|
||||
if (count > n - pos)
|
||||
count = n - pos;
|
||||
if (ckd_add(&last, pos, count))
|
||||
last = n;
|
||||
if (last > n)
|
||||
__builtin_trap();
|
||||
return string(p + pos, count);
|
||||
}
|
||||
|
||||
string&
|
||||
string::replace(size_t pos, size_t count, const string_view& s) noexcept
|
||||
{
|
||||
size_t last;
|
||||
if (ckd_add(&last, pos, count))
|
||||
__builtin_trap();
|
||||
if (last > n)
|
||||
__builtin_trap();
|
||||
size_t need;
|
||||
if (ckd_add(&need, pos, s.n))
|
||||
__builtin_trap();
|
||||
size_t extra = n - last;
|
||||
if (ckd_add(&need, need, extra))
|
||||
__builtin_trap();
|
||||
size_t c2;
|
||||
if (ckd_add(&c2, need, 1))
|
||||
__builtin_trap();
|
||||
reserve(c2);
|
||||
if (extra)
|
||||
memmove(p + pos + s.n, p + last, extra);
|
||||
memcpy(p + pos, s.p, s.n);
|
||||
p[n = need] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
string&
|
||||
string::insert(size_t i, const string_view s) noexcept
|
||||
{
|
||||
if (i > n)
|
||||
__builtin_trap();
|
||||
size_t extra = n - i;
|
||||
size_t need;
|
||||
if (ckd_add(&need, n, s.n))
|
||||
__builtin_trap();
|
||||
if (ckd_add(&need, need, 1))
|
||||
__builtin_trap();
|
||||
reserve(need);
|
||||
if (extra)
|
||||
memmove(p + i + s.n, p + i, extra);
|
||||
memcpy(p + i, s.p, s.n);
|
||||
p[n += s.n] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
string&
|
||||
string::erase(size_t pos, size_t count) noexcept
|
||||
{
|
||||
if (pos > n)
|
||||
__builtin_trap();
|
||||
if (count > n - pos)
|
||||
count = n - pos;
|
||||
size_t extra = n - (pos + count);
|
||||
if (extra)
|
||||
memmove(p + pos, p + pos + count, extra);
|
||||
p[n = pos + extra] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
+236
@@ -0,0 +1,236 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef COSMOPOLITAN_CTL_STRING_H_
|
||||
#define COSMOPOLITAN_CTL_STRING_H_
|
||||
#include "string_view.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
struct string;
|
||||
|
||||
string
|
||||
strcat(const string_view, const string_view) noexcept __wur;
|
||||
|
||||
struct string
|
||||
{
|
||||
char* p = nullptr;
|
||||
size_t n = 0;
|
||||
size_t c = 0;
|
||||
|
||||
using iterator = char*;
|
||||
using const_iterator = const char*;
|
||||
static constexpr size_t npos = -1;
|
||||
|
||||
~string() noexcept;
|
||||
string() = default;
|
||||
string(const string_view) noexcept;
|
||||
string(const char*) noexcept;
|
||||
string(const string&) noexcept;
|
||||
string(const char*, size_t) noexcept;
|
||||
explicit string(size_t, char = 0) noexcept;
|
||||
string& operator=(string&&) noexcept;
|
||||
const char* c_str() const noexcept;
|
||||
|
||||
void pop_back() noexcept;
|
||||
void grow(size_t) noexcept;
|
||||
void reserve(size_t) noexcept;
|
||||
void resize(size_t, char = 0) noexcept;
|
||||
void append(char) noexcept;
|
||||
void append(char, size_t) noexcept;
|
||||
void append(unsigned long) noexcept;
|
||||
void append(const void*, size_t) noexcept;
|
||||
string& insert(size_t, const string_view) noexcept;
|
||||
string& erase(size_t = 0, size_t = npos) noexcept;
|
||||
string substr(size_t = 0, size_t = npos) const noexcept;
|
||||
string& replace(size_t, size_t, const string_view&) noexcept;
|
||||
bool operator==(const string_view) const noexcept;
|
||||
bool operator!=(const string_view) const noexcept;
|
||||
bool contains(const string_view) const noexcept;
|
||||
bool ends_with(const string_view) const noexcept;
|
||||
bool starts_with(const string_view) const noexcept;
|
||||
size_t find(char, size_t = 0) const noexcept;
|
||||
size_t find(const string_view, size_t = 0) const noexcept;
|
||||
|
||||
string(string&& s) noexcept : p(s.p), n(s.n), c(s.c)
|
||||
{
|
||||
s.p = nullptr;
|
||||
s.n = 0;
|
||||
s.c = 0;
|
||||
}
|
||||
|
||||
void clear() noexcept
|
||||
{
|
||||
n = 0;
|
||||
}
|
||||
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return !n;
|
||||
}
|
||||
|
||||
char* data() const noexcept
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
size_t size() const noexcept
|
||||
{
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t length() const noexcept
|
||||
{
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t capacity() const noexcept
|
||||
{
|
||||
return c;
|
||||
}
|
||||
|
||||
iterator begin() noexcept
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
iterator end() noexcept
|
||||
{
|
||||
return p + n;
|
||||
}
|
||||
|
||||
const_iterator cbegin() const noexcept
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
const_iterator cend() const noexcept
|
||||
{
|
||||
return p + n;
|
||||
}
|
||||
|
||||
char& front()
|
||||
{
|
||||
if (!n)
|
||||
__builtin_trap();
|
||||
return p[0];
|
||||
}
|
||||
|
||||
const char& front() const
|
||||
{
|
||||
if (!n)
|
||||
__builtin_trap();
|
||||
return p[0];
|
||||
}
|
||||
|
||||
char& back()
|
||||
{
|
||||
if (!n)
|
||||
__builtin_trap();
|
||||
return p[n - 1];
|
||||
}
|
||||
|
||||
const char& back() const
|
||||
{
|
||||
if (!n)
|
||||
__builtin_trap();
|
||||
return p[n - 1];
|
||||
}
|
||||
|
||||
char& operator[](size_t i) noexcept
|
||||
{
|
||||
if (i >= n)
|
||||
__builtin_trap();
|
||||
return p[i];
|
||||
}
|
||||
|
||||
const char& operator[](size_t i) const noexcept
|
||||
{
|
||||
if (i >= n)
|
||||
__builtin_trap();
|
||||
return p[i];
|
||||
}
|
||||
|
||||
void push_back(char ch) noexcept
|
||||
{
|
||||
append(ch);
|
||||
}
|
||||
|
||||
void append(const string_view s) noexcept
|
||||
{
|
||||
append(s.p, s.n);
|
||||
}
|
||||
|
||||
inline constexpr operator string_view() const noexcept
|
||||
{
|
||||
return string_view(p, n);
|
||||
}
|
||||
|
||||
string& operator=(const char* s) noexcept
|
||||
{
|
||||
clear();
|
||||
append(s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string& operator=(const string_view s) noexcept
|
||||
{
|
||||
clear();
|
||||
append(s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string& operator+=(char x) noexcept
|
||||
{
|
||||
append(x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string& operator+=(const string_view s) noexcept
|
||||
{
|
||||
append(s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string operator+(const string_view s) const noexcept
|
||||
{
|
||||
return strcat(*this, s);
|
||||
}
|
||||
|
||||
int compare(const string_view s) const noexcept
|
||||
{
|
||||
return strcmp(*this, s);
|
||||
}
|
||||
|
||||
bool operator<(const string_view s) const noexcept
|
||||
{
|
||||
return compare(s) < 0;
|
||||
}
|
||||
|
||||
bool operator<=(const string_view s) const noexcept
|
||||
{
|
||||
return compare(s) <= 0;
|
||||
}
|
||||
|
||||
bool operator>(const string_view s) const noexcept
|
||||
{
|
||||
return compare(s) > 0;
|
||||
}
|
||||
|
||||
bool operator>=(const string_view s) const noexcept
|
||||
{
|
||||
return compare(s) >= 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wliteral-suffix"
|
||||
inline ctl::string
|
||||
operator"" s(const char* s, size_t n)
|
||||
{
|
||||
return ctl::string(s, n);
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#endif // COSMOPOLITAN_CTL_STRING_H_
|
||||
@@ -0,0 +1,111 @@
|
||||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8
|
||||
//
|
||||
// Copyright 2024 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 "string_view.h"
|
||||
|
||||
#include <stdckdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "string.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
size_t
|
||||
string_view::find(char ch, size_t pos) const noexcept
|
||||
{
|
||||
char* q;
|
||||
if (n && (q = (char*)memchr(p, ch, n)))
|
||||
return q - p;
|
||||
return npos;
|
||||
}
|
||||
|
||||
size_t
|
||||
string_view::find(const string_view s, size_t pos) const noexcept
|
||||
{
|
||||
char* q;
|
||||
if (pos > n)
|
||||
__builtin_trap();
|
||||
if ((q = (char*)memmem(p + pos, n - pos, s.p, s.n)))
|
||||
return q - p;
|
||||
return npos;
|
||||
}
|
||||
|
||||
string_view
|
||||
string_view::substr(size_t pos, size_t count) const noexcept
|
||||
{
|
||||
size_t last;
|
||||
if (pos > n)
|
||||
__builtin_trap();
|
||||
if (count > n - pos)
|
||||
count = n - pos;
|
||||
if (ckd_add(&last, pos, count))
|
||||
last = n;
|
||||
if (last > n)
|
||||
__builtin_trap();
|
||||
return string_view(p + pos, count);
|
||||
}
|
||||
|
||||
bool
|
||||
string_view::operator==(const string_view s) const noexcept
|
||||
{
|
||||
if (n != s.n)
|
||||
return false;
|
||||
if (!n)
|
||||
return true;
|
||||
return !memcmp(p, s.p, n);
|
||||
}
|
||||
|
||||
bool
|
||||
string_view::operator!=(const string_view s) const noexcept
|
||||
{
|
||||
if (n != s.n)
|
||||
return true;
|
||||
if (!n)
|
||||
return false;
|
||||
return !!memcmp(p, s.p, n);
|
||||
}
|
||||
|
||||
bool
|
||||
string_view::contains(const string_view s) const noexcept
|
||||
{
|
||||
if (!s.n)
|
||||
return true;
|
||||
return !!memmem(p, n, s.p, s.n);
|
||||
}
|
||||
|
||||
bool
|
||||
string_view::ends_with(const string_view s) const noexcept
|
||||
{
|
||||
if (n < s.n)
|
||||
return false;
|
||||
if (!s.n)
|
||||
return true;
|
||||
return !memcmp(p + n - s.n, s.p, s.n);
|
||||
}
|
||||
|
||||
bool
|
||||
string_view::starts_with(const string_view s) const noexcept
|
||||
{
|
||||
if (n < s.n)
|
||||
return false;
|
||||
if (!s.n)
|
||||
return true;
|
||||
return !memcmp(p, s.p, s.n);
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
@@ -0,0 +1,159 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef COSMOPOLITAN_CTL_STRINGVIEW_H_
|
||||
#define COSMOPOLITAN_CTL_STRINGVIEW_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
struct string_view;
|
||||
|
||||
int
|
||||
strcmp(const string_view, const string_view) noexcept;
|
||||
|
||||
struct string_view
|
||||
{
|
||||
const char* p;
|
||||
size_t n;
|
||||
|
||||
using iterator = const char*;
|
||||
using const_iterator = const char*;
|
||||
static constexpr size_t npos = -1;
|
||||
|
||||
constexpr string_view() noexcept : p(nullptr), n(0)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr string_view(const char* s) noexcept
|
||||
: p(s), n(s ? __builtin_strlen(s) : 0)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr string_view(const char* s, size_t n) noexcept : p(s), n(n)
|
||||
{
|
||||
}
|
||||
|
||||
inline constexpr ~string_view() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const string_view) const noexcept;
|
||||
bool operator!=(const string_view) const noexcept;
|
||||
bool contains(const string_view) const noexcept;
|
||||
bool ends_with(const string_view) const noexcept;
|
||||
bool starts_with(const string_view) const noexcept;
|
||||
string_view substr(size_t = 0, size_t = npos) const noexcept;
|
||||
size_t find(char, size_t = 0) const noexcept;
|
||||
size_t find(const string_view, size_t = 0) const noexcept;
|
||||
|
||||
constexpr string_view& operator=(const string_view& s) noexcept
|
||||
{
|
||||
p = s.p;
|
||||
n = s.n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr bool empty() const noexcept
|
||||
{
|
||||
return !n;
|
||||
}
|
||||
|
||||
constexpr const char* data() const noexcept
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
constexpr size_t size() const noexcept
|
||||
{
|
||||
return n;
|
||||
}
|
||||
|
||||
constexpr size_t length() const noexcept
|
||||
{
|
||||
return n;
|
||||
}
|
||||
|
||||
constexpr const char& operator[](size_t i) const noexcept
|
||||
{
|
||||
if (i >= n)
|
||||
__builtin_trap();
|
||||
return p[i];
|
||||
}
|
||||
|
||||
constexpr void remove_prefix(size_t count)
|
||||
{
|
||||
if (count > n)
|
||||
__builtin_trap();
|
||||
p += count;
|
||||
n -= count;
|
||||
}
|
||||
|
||||
constexpr void remove_suffix(size_t count)
|
||||
{
|
||||
if (count > n)
|
||||
__builtin_trap();
|
||||
n -= count;
|
||||
}
|
||||
|
||||
constexpr const char& front() const
|
||||
{
|
||||
if (!n)
|
||||
__builtin_trap();
|
||||
return p[0];
|
||||
}
|
||||
|
||||
constexpr const char& back() const
|
||||
{
|
||||
if (!n)
|
||||
__builtin_trap();
|
||||
return p[n - 1];
|
||||
}
|
||||
|
||||
constexpr const_iterator begin() noexcept
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
constexpr const_iterator end() noexcept
|
||||
{
|
||||
return p + n;
|
||||
}
|
||||
|
||||
constexpr const_iterator cbegin() const noexcept
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
constexpr const_iterator cend() const noexcept
|
||||
{
|
||||
return p + n;
|
||||
}
|
||||
|
||||
int compare(const string_view s) const noexcept
|
||||
{
|
||||
return strcmp(*this, s);
|
||||
}
|
||||
|
||||
bool operator<(const string_view& s) const noexcept
|
||||
{
|
||||
return compare(s) < 0;
|
||||
}
|
||||
|
||||
bool operator<=(const string_view& s) const noexcept
|
||||
{
|
||||
return compare(s) <= 0;
|
||||
}
|
||||
|
||||
bool operator>(const string_view& s) const noexcept
|
||||
{
|
||||
return compare(s) > 0;
|
||||
}
|
||||
|
||||
bool operator>=(const string_view& s) const noexcept
|
||||
{
|
||||
return compare(s) >= 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // COSMOPOLITAN_CTL_STRINGVIEW_H_
|
||||
+246
@@ -0,0 +1,246 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef COSMOPOLITAN_CTL_OPTIONAL_H_
|
||||
#define COSMOPOLITAN_CTL_OPTIONAL_H_
|
||||
#include <__utility/forward.h>
|
||||
#include <__utility/move.h>
|
||||
#include <__utility/swap.h>
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct vector
|
||||
{
|
||||
size_t n = 0;
|
||||
size_t c = 0;
|
||||
T* p = nullptr;
|
||||
|
||||
using iterator = T*;
|
||||
using const_iterator = const T*;
|
||||
|
||||
vector() = default;
|
||||
|
||||
~vector()
|
||||
{
|
||||
delete[] p;
|
||||
}
|
||||
|
||||
vector(const vector& other)
|
||||
{
|
||||
n = other.n;
|
||||
c = other.c;
|
||||
p = new T[c];
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
new (&p[i]) T(other.p[i]);
|
||||
}
|
||||
|
||||
vector(vector&& other) noexcept
|
||||
{
|
||||
n = other.n;
|
||||
c = other.c;
|
||||
p = other.p;
|
||||
other.n = 0;
|
||||
other.c = 0;
|
||||
other.p = nullptr;
|
||||
}
|
||||
|
||||
explicit vector(size_t count, const T& value = T())
|
||||
{
|
||||
n = count;
|
||||
c = count;
|
||||
p = new T[c];
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
new (&p[i]) T(value);
|
||||
}
|
||||
|
||||
vector& operator=(const vector& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
T* newData = new T[other.c];
|
||||
for (size_t i = 0; i < other.n; ++i) {
|
||||
newData[i] = other.p[i];
|
||||
}
|
||||
delete[] p;
|
||||
p = newData;
|
||||
n = other.n;
|
||||
c = other.c;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
vector& operator=(vector&& other) noexcept
|
||||
{
|
||||
if (this != &other) {
|
||||
delete[] p;
|
||||
p = other.p;
|
||||
n = other.n;
|
||||
c = other.c;
|
||||
other.p = nullptr;
|
||||
other.n = 0;
|
||||
other.c = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return !n;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t capacity() const
|
||||
{
|
||||
return c;
|
||||
}
|
||||
|
||||
T& operator[](size_t i)
|
||||
{
|
||||
if (i >= n)
|
||||
__builtin_trap();
|
||||
return p[i];
|
||||
}
|
||||
|
||||
const T& operator[](size_t i) const
|
||||
{
|
||||
if (i >= n)
|
||||
__builtin_trap();
|
||||
return p[i];
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return p + n;
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
{
|
||||
return p + n;
|
||||
}
|
||||
|
||||
T& front()
|
||||
{
|
||||
if (!n)
|
||||
__builtin_trap();
|
||||
return p[0];
|
||||
}
|
||||
|
||||
const T& front() const
|
||||
{
|
||||
if (!n)
|
||||
__builtin_trap();
|
||||
return p[0];
|
||||
}
|
||||
|
||||
T& back()
|
||||
{
|
||||
if (!n)
|
||||
__builtin_trap();
|
||||
return p[n - 1];
|
||||
}
|
||||
|
||||
const T& back() const
|
||||
{
|
||||
if (!n)
|
||||
__builtin_trap();
|
||||
return p[n - 1];
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
p[i].~T();
|
||||
n = 0;
|
||||
}
|
||||
|
||||
void reserve(size_t c2)
|
||||
{
|
||||
if (c2 <= c)
|
||||
return;
|
||||
T* newP = new T[c2];
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
newP[i] = std::move(p[i]);
|
||||
delete[] p;
|
||||
p = newP;
|
||||
c = c2;
|
||||
}
|
||||
|
||||
void push_back(const T& e)
|
||||
{
|
||||
if (n == c) {
|
||||
size_t c2 = c + 1;
|
||||
c2 += c2 >> 1;
|
||||
reserve(c2);
|
||||
}
|
||||
new (&p[n]) T(e);
|
||||
++n;
|
||||
}
|
||||
|
||||
void push_back(T&& e)
|
||||
{
|
||||
if (n == c) {
|
||||
size_t c2 = c + 1;
|
||||
c2 += c2 >> 1;
|
||||
reserve(c2);
|
||||
}
|
||||
new (&p[n]) T(std::forward<T>(e));
|
||||
++n;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void emplace_back(Args&&... args)
|
||||
{
|
||||
if (n == c) {
|
||||
size_t c2 = c + 1;
|
||||
c2 += c2 >> 1;
|
||||
reserve(c2);
|
||||
}
|
||||
new (&p[n]) T(std::forward<Args>(args)...);
|
||||
++n;
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
if (n > 0) {
|
||||
--n;
|
||||
p[n].~T();
|
||||
}
|
||||
}
|
||||
|
||||
void resize(size_t n2)
|
||||
{
|
||||
if (n2 > n) {
|
||||
reserve(n2);
|
||||
for (size_t i = n; i < n2; ++i)
|
||||
new (&p[i]) T();
|
||||
} else if (n2 < n) {
|
||||
for (size_t i = n2; i < n; ++i)
|
||||
p[i].~T();
|
||||
}
|
||||
n = n2;
|
||||
}
|
||||
|
||||
void swap(vector& other) noexcept
|
||||
{
|
||||
std::swap(n, other.n);
|
||||
std::swap(c, other.c);
|
||||
std::swap(p, other.p);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // COSMOPOLITAN_CTL_OPTIONAL_H_
|
||||
+2
-2
@@ -9,8 +9,8 @@ int mulaw(int);
|
||||
int unmulaw(int);
|
||||
void *double2byte(long, const void *, double, double) vallocesque;
|
||||
void *byte2double(long, const void *, double, double) vallocesque;
|
||||
void *dct(float[restrict hasatleast 8][8], unsigned,
|
||||
float, float, float, float, float);
|
||||
void *dct(float[restrict hasatleast 8][8], unsigned, float, float, float, float,
|
||||
float);
|
||||
void *dctjpeg(float[restrict hasatleast 8][8], unsigned);
|
||||
double det3(const double[3][3]) nosideeffect;
|
||||
void *inv3(double[restrict 3][3], const double[restrict 3][3], double);
|
||||
|
||||
+2
-2
@@ -65,8 +65,8 @@
|
||||
*
|
||||
* @cost ~100ns
|
||||
*/
|
||||
void *dct(float M[restrict hasatleast 8][8], unsigned stride,
|
||||
float c0, float c1, float c2, float c3, float c4) {
|
||||
void *dct(float M[restrict hasatleast 8][8], unsigned stride, float c0,
|
||||
float c1, float c2, float c3, float c4) {
|
||||
unsigned y, x;
|
||||
for (y = 0; y < stride * 8; y += stride) {
|
||||
DCT(M[y][0], M[y][1], M[y][2], M[y][3], M[y][4], M[y][5], M[y][6], M[y][7],
|
||||
|
||||
+1
-1
@@ -16,8 +16,8 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
#include "dsp/core/gamma.h"
|
||||
#include "dsp/core/core.h"
|
||||
#include "libc/math.h"
|
||||
|
||||
double rgb2stdpc(double x, double g) {
|
||||
|
||||
+2
-1
@@ -64,7 +64,8 @@ forceinline bool plm_buffer_has(plm_buffer_t *b, size_t bits) {
|
||||
}
|
||||
|
||||
forceinline int plm_buffer_read(plm_buffer_t *self, int count) {
|
||||
if (!plm_buffer_has(self, count)) return 0;
|
||||
if (!plm_buffer_has(self, count))
|
||||
return 0;
|
||||
int value = 0;
|
||||
while (count) {
|
||||
int current_byte = self->bytes[self->bit_index >> 3];
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@
|
||||
#include "dsp/mpeg/mpeg.h"
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define START_PACK 0xBA
|
||||
#define START_END 0xB9
|
||||
#define START_PACK 0xBA
|
||||
#define START_END 0xB9
|
||||
#define START_SYSTEM 0xBB
|
||||
|
||||
typedef struct plm_demux_t {
|
||||
|
||||
+6
-2
@@ -24,9 +24,13 @@
|
||||
* The alternate buffer trick lets one restore the console exactly as it
|
||||
* was, once the program is done running.
|
||||
*/
|
||||
int ttyenablealtbuf(int ttyfd) { return ttysend(ttyfd, "\e[?1049h"); }
|
||||
int ttyenablealtbuf(int ttyfd) {
|
||||
return ttysend(ttyfd, "\e[?1049h");
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks teletypewriter to restore blinking box thing.
|
||||
*/
|
||||
int ttydisablealtbuf(int ttyfd) { return ttysend(ttyfd, "\e[?1049l"); }
|
||||
int ttydisablealtbuf(int ttyfd) {
|
||||
return ttysend(ttyfd, "\e[?1049l");
|
||||
}
|
||||
@@ -21,9 +21,13 @@
|
||||
/**
|
||||
* Asks teletypewriter to push current position.
|
||||
*/
|
||||
int ttysavecursor(int ttyfd) { return ttysend(ttyfd, "\e[s"); }
|
||||
int ttysavecursor(int ttyfd) {
|
||||
return ttysend(ttyfd, "\e[s");
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks teletypewriter to pop previous position.
|
||||
*/
|
||||
int ttyrestorecursor(int ttyfd) { return ttysend(ttyfd, "\e[u"); }
|
||||
int ttyrestorecursor(int ttyfd) {
|
||||
return ttysend(ttyfd, "\e[u");
|
||||
}
|
||||
+6
-2
@@ -39,8 +39,12 @@ static char *setansibgfg(char *p, unsigned bg, unsigned fg) {
|
||||
return p;
|
||||
}
|
||||
|
||||
char *setbg16_(char *p, struct TtyRgb bg) { return setansibgfg(p, bg.xt, -1u); }
|
||||
char *setfg16_(char *p, struct TtyRgb fg) { return setansibgfg(p, -1u, fg.xt); }
|
||||
char *setbg16_(char *p, struct TtyRgb bg) {
|
||||
return setansibgfg(p, bg.xt, -1u);
|
||||
}
|
||||
char *setfg16_(char *p, struct TtyRgb fg) {
|
||||
return setansibgfg(p, -1u, fg.xt);
|
||||
}
|
||||
char *setbgfg16_(char *p, struct TtyRgb bg, struct TtyRgb fg) {
|
||||
return setansibgfg(p, bg.xt, fg.xt);
|
||||
}
|
||||
+1
-1
@@ -87,7 +87,7 @@ static textexit void ttyraw_onexit(void) {
|
||||
ttyraw_disable();
|
||||
}
|
||||
|
||||
static relegated void ttyraw_onsig(int sig, struct siginfo *info,
|
||||
static relegated void ttyraw_onsig(int sig, siginfo_t *info,
|
||||
struct ucontext *ctx) {
|
||||
size_t i;
|
||||
if (g_ttyraw.noreentry)
|
||||
|
||||
@@ -91,6 +91,7 @@ EXAMPLES_DIRECTDEPS = \
|
||||
THIRD_PARTY_TZ \
|
||||
THIRD_PARTY_VQSORT \
|
||||
THIRD_PARTY_XED \
|
||||
THIRD_PARTY_LIBCXXABI \
|
||||
THIRD_PARTY_ZLIB \
|
||||
TOOL_ARGS \
|
||||
TOOL_BUILD_LIB \
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
__static_yoink("__die");
|
||||
__static_yoink("GetSymbolByAddr");
|
||||
__static_yoink("malloc_inspect_all");
|
||||
|
||||
char *lol(int n) {
|
||||
return malloc(n);
|
||||
}
|
||||
|
||||
char *(*pLol)(int) = lol;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char *s = pLol(4);
|
||||
s[4] = 1;
|
||||
}
|
||||
+11
-8
@@ -7,6 +7,7 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
@@ -26,6 +27,13 @@
|
||||
* o//examples/crashreport.com
|
||||
*/
|
||||
|
||||
int Divide(int x, int y) {
|
||||
volatile int z = 0; // force creation of stack frame
|
||||
return x / y + z;
|
||||
}
|
||||
|
||||
int (*pDivide)(int, int) = Divide;
|
||||
|
||||
dontubsan int main(int argc, char *argv[]) {
|
||||
kprintf("----------------\n");
|
||||
kprintf(" THIS IS A TEST \n");
|
||||
@@ -34,12 +42,7 @@ dontubsan int main(int argc, char *argv[]) {
|
||||
|
||||
ShowCrashReports();
|
||||
|
||||
volatile double a = 0;
|
||||
volatile double b = 23;
|
||||
volatile double c = exp(b) / a;
|
||||
(void)c;
|
||||
|
||||
volatile int x = 0;
|
||||
volatile int y = 1 / x;
|
||||
return y;
|
||||
pDivide(1, 0);
|
||||
pDivide(2, 0);
|
||||
pDivide(3, 0);
|
||||
}
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
fprintf(stderr, "%s (%s)\n", argv[0], GetProgramExecutableName());
|
||||
for (char **p = environ; *p; ++p) {
|
||||
for (char** p = environ; *p; ++p) {
|
||||
printf("%s\n", *p);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -151,7 +151,7 @@ void *Worker(void *id) {
|
||||
|
||||
// check that client message wasn't fragmented into more reads
|
||||
InitHttpMessage(&msg, kHttpRequest);
|
||||
if ((inmsglen = ParseHttpMessage(&msg, buf, got)) <= 0) {
|
||||
if ((inmsglen = ParseHttpMessage(&msg, buf, got, sizeof(buf))) <= 0) {
|
||||
if (!inmsglen) {
|
||||
LOG("%6H client sent fragmented message");
|
||||
} else {
|
||||
|
||||
+2
-2
@@ -7,11 +7,11 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "third_party/hiredis/hiredis.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "third_party/hiredis/hiredis.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Demo of using hiredis to connect to a Redis server
|
||||
|
||||
@@ -42,6 +42,7 @@ EXAMPLES_PACKAGE_OBJS = \
|
||||
EXAMPLES_PACKAGE_DIRECTDEPS = \
|
||||
EXAMPLES_PACKAGE_LIB \
|
||||
LIBC_INTRIN \
|
||||
LIBC_MEM \
|
||||
LIBC_STDIO \
|
||||
LIBC_TINYMATH
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ EXAMPLES_PACKAGE_LIB_A_CHECKS = \
|
||||
EXAMPLES_PACKAGE_LIB_A_DIRECTDEPS = \
|
||||
LIBC_INTRIN \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_MEM \
|
||||
LIBC_STDIO
|
||||
|
||||
# Evaluates variable as set of transitive package dependencies.
|
||||
|
||||
+26
-26
@@ -1,31 +1,31 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#define PARSE_AND_PRINT(type, scan_fmt, print_fmt, str) \
|
||||
do { \
|
||||
type val; int ret; \
|
||||
ret = sscanf(str, scan_fmt, &val); \
|
||||
printf("\"%s\" => " print_fmt " = %d\n", str, val, ret); \
|
||||
#define PARSE_AND_PRINT(type, scan_fmt, print_fmt, str) \
|
||||
do { \
|
||||
type val; \
|
||||
int ret; \
|
||||
ret = sscanf(str, scan_fmt, &val); \
|
||||
printf("\"%s\" => " print_fmt " = %d\n", str, val, ret); \
|
||||
} while (0)
|
||||
|
||||
int main()
|
||||
{
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "0.3715");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", ".3715");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "3715");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "111.11");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "-2.22");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "Nan");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "nAn(2)");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "-NAN(_asdfZXCV1234_)");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "-nan");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "+nan");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "inF");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "iNfINiTy");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "+inf");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "-inf");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "0X1.BC70A3D70A3D7P+6");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "1.18973e+4932zzz");
|
||||
PARSE_AND_PRINT(float, "%f", "%.10f", " -0.0000000123junk");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "junk");
|
||||
return 0;
|
||||
int main() {
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "0.3715");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", ".3715");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "3715");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "111.11");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "-2.22");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "Nan");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "nAn(2)");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "-NAN(_asdfZXCV1234_)");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "-nan");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "+nan");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "inF");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "iNfINiTy");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "+inf");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "-inf");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "0X1.BC70A3D70A3D7P+6");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "1.18973e+4932zzz");
|
||||
PARSE_AND_PRINT(float, "%f", "%.10f", " -0.0000000123junk");
|
||||
PARSE_AND_PRINT(float, "%f", "%f", "junk");
|
||||
return 0;
|
||||
}
|
||||
+16
-11
@@ -2601,7 +2601,8 @@ static int shlex() {
|
||||
case 'y':
|
||||
case 'z':
|
||||
p = buf;
|
||||
while (buf++, is_in_name(*buf));
|
||||
while (buf++, is_in_name(*buf))
|
||||
;
|
||||
yylval.name = stalloc(buf - p + 1);
|
||||
*(char *)mempcpy(yylval.name, p, buf - p) = 0;
|
||||
value = ARITH_VAR;
|
||||
@@ -7757,7 +7758,8 @@ static int ulimitcmd(int argc, char **argv) {
|
||||
what = optc;
|
||||
}
|
||||
}
|
||||
for (l = limits; l->option != what; l++);
|
||||
for (l = limits; l->option != what; l++)
|
||||
;
|
||||
set = *argptr ? 1 : 0;
|
||||
if (set) {
|
||||
char *p = *argptr;
|
||||
@@ -7986,7 +7988,8 @@ static void setparam(char **argv) {
|
||||
char **newparam;
|
||||
char **ap;
|
||||
int nparam;
|
||||
for (nparam = 0; argv[nparam]; nparam++);
|
||||
for (nparam = 0; argv[nparam]; nparam++)
|
||||
;
|
||||
ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
|
||||
while (*argv) {
|
||||
*ap++ = savestr(*argv++);
|
||||
@@ -8664,7 +8667,8 @@ static void parsefname(void) {
|
||||
if (heredoclist == NULL)
|
||||
heredoclist = here;
|
||||
else {
|
||||
for (p = heredoclist; p->next; p = p->next);
|
||||
for (p = heredoclist; p->next; p = p->next)
|
||||
;
|
||||
p->next = here;
|
||||
}
|
||||
} else if (n->type == NTOFD || n->type == NFROMFD) {
|
||||
@@ -8788,7 +8792,8 @@ static int xxreadtoken(void) {
|
||||
case '\t':
|
||||
continue;
|
||||
case '#':
|
||||
while ((c = pgetc()) != '\n' && c != PEOF);
|
||||
while ((c = pgetc()) != '\n' && c != PEOF)
|
||||
;
|
||||
pungetc();
|
||||
continue;
|
||||
case '\n':
|
||||
@@ -8912,7 +8917,7 @@ static int readtoken1(int firstc, char const *syntax, char *eofmark,
|
||||
quotef = 0;
|
||||
bqlist = NULL;
|
||||
STARTSTACKSTR(out);
|
||||
loop: { /* for each line, until end of word */
|
||||
loop : { /* for each line, until end of word */
|
||||
CHECKEND(); /* set c to PEOF if at end of here document */
|
||||
for (;;) { /* until end of line or end of word */
|
||||
CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
|
||||
@@ -9064,7 +9069,7 @@ endword:
|
||||
* is called, c is set to the first character of the next input line. If
|
||||
* we are at the end of the here document, this routine sets the c to PEOF.
|
||||
*/
|
||||
checkend: {
|
||||
checkend : {
|
||||
if (realeofmark(eofmark)) {
|
||||
int markloc;
|
||||
char *p;
|
||||
@@ -9107,7 +9112,7 @@ checkend: {
|
||||
* specifying the fd to be redirected. The variable "c" contains the
|
||||
* first character of the redirection operator.
|
||||
*/
|
||||
parseredir: {
|
||||
parseredir : {
|
||||
char fd = *out;
|
||||
union node *np;
|
||||
np = (union node *)stalloc(sizeof(struct nfile));
|
||||
@@ -9164,7 +9169,7 @@ parseredir: {
|
||||
* Parse a substitution. At this point, we have read the dollar sign
|
||||
* and nothing else.
|
||||
*/
|
||||
parsesub: {
|
||||
parsesub : {
|
||||
int subtype;
|
||||
int typeloc;
|
||||
char *p;
|
||||
@@ -9282,7 +9287,7 @@ parsesub: {
|
||||
* list of commands (passed by reference), and savelen is the number of
|
||||
* characters on the top of the stack which must be preserved.
|
||||
*/
|
||||
parsebackq: {
|
||||
parsebackq : {
|
||||
struct nodelist **nlpp;
|
||||
union node *n;
|
||||
char *str;
|
||||
@@ -9377,7 +9382,7 @@ parsebackq: {
|
||||
/*
|
||||
* Parse an arithmetic expansion (indicate start of one and set state)
|
||||
*/
|
||||
parsearith: {
|
||||
parsearith : {
|
||||
synstack_push(&synstack, synstack->prev ?: alloca(sizeof(*synstack)),
|
||||
ARISYNTAX);
|
||||
synstack->dblquote = 1;
|
||||
|
||||
+1
-1
@@ -9,11 +9,11 @@
|
||||
#endif
|
||||
#include "libc/errno.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/ftw.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/exit.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/stdio/ftw.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Directory walker example.
|
||||
|
||||
+1
-90
@@ -4,10 +4,8 @@
|
||||
PKGS += LIBC
|
||||
|
||||
LIBC_ISYSTEM = \
|
||||
libc/isystem/algorithm \
|
||||
libc/isystem/alloca.h \
|
||||
libc/isystem/ammintrin.h \
|
||||
libc/isystem/any \
|
||||
libc/isystem/ar.h \
|
||||
libc/isystem/arm_acle.h \
|
||||
libc/isystem/arm_bf16.h \
|
||||
@@ -15,51 +13,16 @@ libc/isystem/arm_fp16.h \
|
||||
libc/isystem/arm_neon.h \
|
||||
libc/isystem/arpa/inet.h \
|
||||
libc/isystem/arpa/nameser.h \
|
||||
libc/isystem/array \
|
||||
libc/isystem/assert.h \
|
||||
libc/isystem/atomic \
|
||||
libc/isystem/bit \
|
||||
libc/isystem/bitset \
|
||||
libc/isystem/byteswap.h \
|
||||
libc/isystem/cassert \
|
||||
libc/isystem/ccomplex \
|
||||
libc/isystem/cctype \
|
||||
libc/isystem/cerrno \
|
||||
libc/isystem/cfenv \
|
||||
libc/isystem/cfloat \
|
||||
libc/isystem/charconv \
|
||||
libc/isystem/chrono \
|
||||
libc/isystem/cinttypes \
|
||||
libc/isystem/ciso646 \
|
||||
libc/isystem/climits \
|
||||
libc/isystem/clocale \
|
||||
libc/isystem/clzerointrin.h \
|
||||
libc/isystem/cmath \
|
||||
libc/isystem/codecvt \
|
||||
libc/isystem/compare \
|
||||
libc/isystem/complex \
|
||||
libc/isystem/complex.h \
|
||||
libc/isystem/condition_variable \
|
||||
libc/isystem/cosmo.h \
|
||||
libc/isystem/cpio.h \
|
||||
libc/isystem/cpuid.h \
|
||||
libc/isystem/crypt.h \
|
||||
libc/isystem/csetjmp \
|
||||
libc/isystem/csignal \
|
||||
libc/isystem/cstdarg \
|
||||
libc/isystem/cstdbool \
|
||||
libc/isystem/cstddef \
|
||||
libc/isystem/cstdint \
|
||||
libc/isystem/cstdio \
|
||||
libc/isystem/cstdlib \
|
||||
libc/isystem/cstring \
|
||||
libc/isystem/ctgmath \
|
||||
libc/isystem/ctime \
|
||||
libc/isystem/ctype.h \
|
||||
libc/isystem/cwchar \
|
||||
libc/isystem/cwctype \
|
||||
libc/isystem/cxxabi.h \
|
||||
libc/isystem/deque \
|
||||
libc/isystem/dirent.h \
|
||||
libc/isystem/dlfcn.h \
|
||||
libc/isystem/elf.h \
|
||||
@@ -67,57 +30,37 @@ libc/isystem/emmintrin.h \
|
||||
libc/isystem/endian.h \
|
||||
libc/isystem/err.h \
|
||||
libc/isystem/errno.h \
|
||||
libc/isystem/exception \
|
||||
libc/isystem/execution \
|
||||
libc/isystem/fcntl.h \
|
||||
libc/isystem/features.h \
|
||||
libc/isystem/fenv.h \
|
||||
libc/isystem/filesystem \
|
||||
libc/isystem/float.h \
|
||||
libc/isystem/fnmatch.h \
|
||||
libc/isystem/forward_list \
|
||||
libc/isystem/fstream \
|
||||
libc/isystem/ftw.h \
|
||||
libc/isystem/functional \
|
||||
libc/isystem/future \
|
||||
libc/isystem/getopt.h \
|
||||
libc/isystem/glob.h \
|
||||
libc/isystem/grp.h \
|
||||
libc/isystem/iconv.h \
|
||||
libc/isystem/ifaddrs.h \
|
||||
libc/isystem/immintrin.h \
|
||||
libc/isystem/initializer_list \
|
||||
libc/isystem/inttypes.h \
|
||||
libc/isystem/iomanip \
|
||||
libc/isystem/ios \
|
||||
libc/isystem/iosfwd \
|
||||
libc/isystem/iostream \
|
||||
libc/isystem/iso646.h \
|
||||
libc/isystem/istream \
|
||||
libc/isystem/iterator \
|
||||
libc/isystem/langinfo.h \
|
||||
libc/isystem/libgen.h \
|
||||
libc/isystem/limits \
|
||||
libc/isystem/limits.h \
|
||||
libc/isystem/link.h \
|
||||
libc/isystem/linux/futex.h \
|
||||
libc/isystem/linux/limits.h \
|
||||
libc/isystem/linux/param.h \
|
||||
libc/isystem/linux/types.h \
|
||||
libc/isystem/list \
|
||||
libc/isystem/locale \
|
||||
libc/isystem/locale.h \
|
||||
libc/isystem/malloc.h \
|
||||
libc/isystem/map \
|
||||
libc/isystem/math.h \
|
||||
libc/isystem/memory \
|
||||
libc/isystem/memory.h \
|
||||
libc/isystem/mm3dnow.h \
|
||||
libc/isystem/mm_malloc.h \
|
||||
libc/isystem/mmintrin.h \
|
||||
libc/isystem/mntent.h \
|
||||
libc/isystem/monetary.h \
|
||||
libc/isystem/mutex \
|
||||
libc/isystem/mwaitxintrin.h \
|
||||
libc/isystem/net/ethernet.h \
|
||||
libc/isystem/net/if.h \
|
||||
@@ -127,7 +70,6 @@ libc/isystem/netinet/in.h \
|
||||
libc/isystem/netinet/ip.h \
|
||||
libc/isystem/netinet/tcp.h \
|
||||
libc/isystem/netinet/udp.h \
|
||||
libc/isystem/new \
|
||||
libc/isystem/nl_types.h \
|
||||
libc/isystem/nmmintrin.h \
|
||||
libc/isystem/nsync.h \
|
||||
@@ -141,12 +83,9 @@ libc/isystem/nsync_note.h \
|
||||
libc/isystem/nsync_once.h \
|
||||
libc/isystem/nsync_time.h \
|
||||
libc/isystem/nsync_waiter.h \
|
||||
libc/isystem/numeric \
|
||||
libc/isystem/omp-tools.h \
|
||||
libc/isystem/omp.h \
|
||||
libc/isystem/ompx.h \
|
||||
libc/isystem/optional \
|
||||
libc/isystem/ostream \
|
||||
libc/isystem/paths.h \
|
||||
libc/isystem/pmmintrin.h \
|
||||
libc/isystem/poll.h \
|
||||
@@ -154,27 +93,17 @@ libc/isystem/popcntintrin.h \
|
||||
libc/isystem/pthread.h \
|
||||
libc/isystem/pty.h \
|
||||
libc/isystem/pwd.h \
|
||||
libc/isystem/queue \
|
||||
libc/isystem/random \
|
||||
libc/isystem/ratio \
|
||||
libc/isystem/regex \
|
||||
libc/isystem/regex.h \
|
||||
libc/isystem/resolv.h \
|
||||
libc/isystem/sched.h \
|
||||
libc/isystem/scoped_allocator \
|
||||
libc/isystem/search.h \
|
||||
libc/isystem/semaphore.h \
|
||||
libc/isystem/set \
|
||||
libc/isystem/setjmp.h \
|
||||
libc/isystem/sgxintrin.h \
|
||||
libc/isystem/shadow.h \
|
||||
libc/isystem/shared_mutex \
|
||||
libc/isystem/signal.h \
|
||||
libc/isystem/smmintrin.h \
|
||||
libc/isystem/span \
|
||||
libc/isystem/spawn.h \
|
||||
libc/isystem/sstream \
|
||||
libc/isystem/stack \
|
||||
libc/isystem/stdalign.h \
|
||||
libc/isystem/stdarg.h \
|
||||
libc/isystem/stdatomic.h \
|
||||
@@ -182,18 +111,13 @@ libc/isystem/stdbool.h \
|
||||
libc/isystem/stdc-predef.h \
|
||||
libc/isystem/stdckdint.h \
|
||||
libc/isystem/stddef.h \
|
||||
libc/isystem/stdexcept \
|
||||
libc/isystem/stdint.h \
|
||||
libc/isystem/stdio.h \
|
||||
libc/isystem/stdio_ext.h \
|
||||
libc/isystem/stdlib.h \
|
||||
libc/isystem/stdnoreturn.h \
|
||||
libc/isystem/streambuf \
|
||||
libc/isystem/string \
|
||||
libc/isystem/string.h \
|
||||
libc/isystem/string_view \
|
||||
libc/isystem/strings.h \
|
||||
libc/isystem/strstream \
|
||||
libc/isystem/sys/auxv.h \
|
||||
libc/isystem/sys/cdefs.h \
|
||||
libc/isystem/sys/dir.h \
|
||||
@@ -238,39 +162,26 @@ libc/isystem/sys/vfs.h \
|
||||
libc/isystem/sys/wait.h \
|
||||
libc/isystem/sysexits.h \
|
||||
libc/isystem/syslog.h \
|
||||
libc/isystem/system_error \
|
||||
libc/isystem/termios.h \
|
||||
libc/isystem/tgmath.h \
|
||||
libc/isystem/thread \
|
||||
libc/isystem/threads.h \
|
||||
libc/isystem/time.h \
|
||||
libc/isystem/tmmintrin.h \
|
||||
libc/isystem/tuple \
|
||||
libc/isystem/type_traits \
|
||||
libc/isystem/typeindex \
|
||||
libc/isystem/typeinfo \
|
||||
libc/isystem/uchar.h \
|
||||
libc/isystem/ucontext.h \
|
||||
libc/isystem/uio.h \
|
||||
libc/isystem/unistd.h \
|
||||
libc/isystem/unordered_map \
|
||||
libc/isystem/unordered_set \
|
||||
libc/isystem/unwind.h \
|
||||
libc/isystem/utility \
|
||||
libc/isystem/utime.h \
|
||||
libc/isystem/utmp.h \
|
||||
libc/isystem/utmpx.h \
|
||||
libc/isystem/valarray \
|
||||
libc/isystem/variant \
|
||||
libc/isystem/vector \
|
||||
libc/isystem/version \
|
||||
libc/isystem/wait.h \
|
||||
libc/isystem/wchar.h \
|
||||
libc/isystem/wctype.h \
|
||||
libc/isystem/winternl.h \
|
||||
libc/isystem/wmmintrin.h \
|
||||
libc/isystem/x86intrin.h \
|
||||
libc/isystem/xmmintrin.h
|
||||
libc/isystem/xmmintrin.h \
|
||||
|
||||
LIBC_HDRS = $(filter %.h,$(LIBC_FILES)) $(LIBC_ISYSTEM)
|
||||
LIBC_HDRS_H = $(filter %.h,$(LIBC_HDRS))
|
||||
|
||||
@@ -147,6 +147,13 @@ o/$(MODE)/libc/calls/pledge-linux.o: private \
|
||||
-fPIC \
|
||||
-ffreestanding
|
||||
|
||||
# we want -Os because:
|
||||
# it makes a big difference
|
||||
# it gets called very rarely
|
||||
o/$(MODE)/libc/calls/sigcrashsig.o: private \
|
||||
CFLAGS += \
|
||||
-Os
|
||||
|
||||
# these assembly files are safe to build on aarch64
|
||||
o/$(MODE)/libc/calls/getcontext.o: libc/calls/getcontext.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
|
||||
@@ -10,12 +10,12 @@ void end_cancelation_point(int);
|
||||
#define END_CANCELATION_POINT (void)0
|
||||
#else
|
||||
#define BEGIN_CANCELATION_POINT \
|
||||
do { \
|
||||
int _Cp; \
|
||||
do { \
|
||||
int _Cp; \
|
||||
_Cp = begin_cancelation_point()
|
||||
#define END_CANCELATION_POINT \
|
||||
end_cancelation_point(_Cp); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
#endif
|
||||
|
||||
|
||||
+1
-1
@@ -23,8 +23,8 @@
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Duplicates file descriptor.
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@ int dup2(int oldfd, int newfd) {
|
||||
rc = oldfd;
|
||||
} else
|
||||
#endif
|
||||
if (!IsWindows()) {
|
||||
if (!IsWindows()) {
|
||||
if (__isfdkind(oldfd, kFdZip) || __isfdkind(newfd, kFdZip)) {
|
||||
if (__vforked) {
|
||||
return enotsup();
|
||||
|
||||
+5
-14
@@ -48,20 +48,11 @@ int getcpu(unsigned *out_opt_cpu, unsigned *out_opt_node) {
|
||||
} else {
|
||||
return __winerr();
|
||||
}
|
||||
} else if (IsXnuSilicon()) {
|
||||
if (__syslib->__version >= 9) {
|
||||
size_t cpu64;
|
||||
errno_t err = __syslib->__pthread_cpu_number_np(&cpu64);
|
||||
if (!err) {
|
||||
cpu = cpu64;
|
||||
node = 0;
|
||||
} else {
|
||||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return enosys();
|
||||
}
|
||||
} else if (IsAarch64()) {
|
||||
long tpidr_el0;
|
||||
asm("mrs\t%0,tpidr_el0" : "=r"(tpidr_el0));
|
||||
cpu = tpidr_el0 & 255;
|
||||
node = 0;
|
||||
} else {
|
||||
int rc = sys_getcpu(&cpu, &node, 0);
|
||||
if (rc == -1)
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ static struct HostAdapterInfoNode {
|
||||
struct sockaddr netmask;
|
||||
struct sockaddr broadcast;
|
||||
short flags;
|
||||
} * __hostInfo;
|
||||
} *__hostInfo;
|
||||
|
||||
static int ioctl_default(int fd, unsigned long request, void *arg) {
|
||||
int rc;
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/serialize.h"
|
||||
#include "libc/proc/execve.internal.h"
|
||||
#include "libc/serialize.h"
|
||||
|
||||
/**
|
||||
* Returns true if executable image is supported by APE Loader.
|
||||
|
||||
+1
-1
@@ -24,8 +24,8 @@
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Creates hard filesystem link.
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Creates directory a.k.a. folder.
|
||||
|
||||
+18
-21
@@ -23,6 +23,7 @@
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/proc/ntspawn.h"
|
||||
#include "libc/stdio/sysparam.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/thompike.h"
|
||||
#include "libc/str/utf16.h"
|
||||
@@ -31,16 +32,14 @@
|
||||
|
||||
#define APPEND(c) \
|
||||
do { \
|
||||
if (k == 32766) { \
|
||||
return e2big(); \
|
||||
} \
|
||||
cmdline[k++] = c; \
|
||||
if (k < size) \
|
||||
cmdline[k] = c; \
|
||||
++k; \
|
||||
} while (0)
|
||||
|
||||
static bool NeedsQuotes(const char *s) {
|
||||
if (!*s) {
|
||||
static textwindows bool NeedsQuotes(const char *s) {
|
||||
if (!*s)
|
||||
return true;
|
||||
}
|
||||
do {
|
||||
switch (*s) {
|
||||
case '"':
|
||||
@@ -60,7 +59,7 @@ static inline int IsAlpha(int c) {
|
||||
return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
|
||||
}
|
||||
|
||||
static bool LooksLikeCosmoDrivePath(const char *s) {
|
||||
static textwindows bool LooksLikeCosmoDrivePath(const char *s) {
|
||||
return s[0] == '/' && //
|
||||
IsAlpha(s[1]) && //
|
||||
s[2] == '/';
|
||||
@@ -74,12 +73,13 @@ static bool LooksLikeCosmoDrivePath(const char *s) {
|
||||
//
|
||||
// @param cmdline is output buffer
|
||||
// @param argv is an a NULL-terminated array of UTF-8 strings
|
||||
// @return 0 on success, or -1 w/ errno
|
||||
// @raise E2BIG if everything is too huge
|
||||
// @param size is number of characters in cmdline buffer
|
||||
// @return length on success, which is >=size on truncation
|
||||
// @see "Everyone quotes command line arguments the wrong way" MSDN
|
||||
// @see libc/runtime/getdosargv.c
|
||||
// @asyncsignalsafe
|
||||
textwindows int mkntcmdline(char16_t cmdline[32767], char *const argv[]) {
|
||||
textwindows size_t mkntcmdline(char16_t *cmdline, char *const argv[],
|
||||
size_t size) {
|
||||
char *arg;
|
||||
int slashes, n;
|
||||
bool needsquote;
|
||||
@@ -95,9 +95,8 @@ textwindows int mkntcmdline(char16_t cmdline[32767], char *const argv[]) {
|
||||
} else {
|
||||
arg = argv[i];
|
||||
}
|
||||
if ((needsquote = NeedsQuotes(arg))) {
|
||||
if ((needsquote = NeedsQuotes(arg)))
|
||||
APPEND(u'"');
|
||||
}
|
||||
for (slashes = j = 0;;) {
|
||||
wint_t x = arg[j++] & 255;
|
||||
if (x >= 0300) {
|
||||
@@ -122,9 +121,8 @@ textwindows int mkntcmdline(char16_t cmdline[32767], char *const argv[]) {
|
||||
APPEND(u'"');
|
||||
APPEND(u'"');
|
||||
} else {
|
||||
for (s = 0; s < slashes; ++s) {
|
||||
for (s = 0; s < slashes; ++s)
|
||||
APPEND(u'\\');
|
||||
}
|
||||
slashes = 0;
|
||||
uint32_t w = EncodeUtf16(x);
|
||||
do
|
||||
@@ -132,13 +130,12 @@ textwindows int mkntcmdline(char16_t cmdline[32767], char *const argv[]) {
|
||||
while ((w >>= 16));
|
||||
}
|
||||
}
|
||||
for (s = 0; s < (slashes << needsquote); ++s) {
|
||||
for (s = 0; s < (slashes << needsquote); ++s)
|
||||
APPEND(u'\\');
|
||||
}
|
||||
if (needsquote) {
|
||||
if (needsquote)
|
||||
APPEND(u'"');
|
||||
}
|
||||
}
|
||||
cmdline[k] = 0;
|
||||
return 0;
|
||||
if (size)
|
||||
cmdline[MIN(k, size - 1)] = 0;
|
||||
return k;
|
||||
}
|
||||
+168
-86
@@ -20,9 +20,15 @@
|
||||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/creationdisposition.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/enum/filesharemode.h"
|
||||
#include "libc/nt/enum/processaccess.h"
|
||||
#include "libc/nt/enum/processcreationflags.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/events.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/process.h"
|
||||
@@ -33,6 +39,7 @@
|
||||
#include "libc/nt/struct/startupinfo.h"
|
||||
#include "libc/nt/struct/startupinfoex.h"
|
||||
#include "libc/proc/ntspawn.h"
|
||||
#include "libc/stdalign.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#ifdef __x86_64__
|
||||
@@ -44,14 +51,167 @@ struct SpawnBlock {
|
||||
char envbuf[32767];
|
||||
};
|
||||
|
||||
static void *ntspawn_malloc(size_t size) {
|
||||
static textwindows void *ntspawn_malloc(size_t size) {
|
||||
return HeapAlloc(GetProcessHeap(), 0, size);
|
||||
}
|
||||
|
||||
static void ntspawn_free(void *ptr) {
|
||||
static textwindows void ntspawn_free(void *ptr) {
|
||||
HeapFree(GetProcessHeap(), 0, ptr);
|
||||
}
|
||||
|
||||
static textwindows ssize_t ntspawn_read(intptr_t fh, char *buf, size_t len) {
|
||||
bool ok;
|
||||
uint32_t got;
|
||||
struct NtOverlapped overlap = {.hEvent = CreateEvent(0, 0, 0, 0)};
|
||||
ok = (ReadFile(fh, buf, len, 0, &overlap) ||
|
||||
GetLastError() == kNtErrorIoPending) &&
|
||||
GetOverlappedResult(fh, &overlap, &got, true);
|
||||
CloseHandle(overlap.hEvent);
|
||||
return ok ? got : -1;
|
||||
}
|
||||
|
||||
static textwindows int ntspawn2(struct NtSpawnArgs *a, struct SpawnBlock *sb) {
|
||||
|
||||
// make executable path
|
||||
if (__mkntpathath(a->dirhand, a->prog, 0, sb->path) == -1)
|
||||
return -1;
|
||||
|
||||
// open executable
|
||||
char *p = sb->envbuf;
|
||||
char *pe = p + sizeof(sb->envbuf);
|
||||
intptr_t fh = CreateFile(
|
||||
sb->path, kNtFileGenericRead,
|
||||
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, 0,
|
||||
kNtOpenExisting, kNtFileAttributeNormal | kNtFileFlagBackupSemantics, 0);
|
||||
if (fh == -1)
|
||||
return -1;
|
||||
ssize_t got = ntspawn_read(fh, p, pe - p);
|
||||
CloseHandle(fh);
|
||||
if (got < 3)
|
||||
return enoexec();
|
||||
pe = p + got;
|
||||
|
||||
// handle shebang
|
||||
size_t i = 0; // represents space of sb->cmdline consumed
|
||||
if (p[0] == 'M' && p[1] == 'Z') {
|
||||
// it's a windows executable
|
||||
} else if (p[0] == '#' && p[1] == '!') {
|
||||
p += 2;
|
||||
// make sure we got a complete first line
|
||||
pe = memchr(p, '\n', pe - p);
|
||||
if (!pe)
|
||||
return enoexec();
|
||||
*pe = 0;
|
||||
int argc = 0;
|
||||
char *argv[4];
|
||||
// it's legal to say "#! /bin/sh"
|
||||
while (p < pe && (*p == ' ' || *p == '\t'))
|
||||
++p;
|
||||
if (p == pe)
|
||||
return enoexec();
|
||||
argv[argc++] = p;
|
||||
// find the optional argument
|
||||
while (p < pe && !(*p == ' ' || *p == '\t'))
|
||||
++p;
|
||||
if (p < pe) {
|
||||
*p++ = 0;
|
||||
while (p < pe && (*p == ' ' || *p == '\t'))
|
||||
++p;
|
||||
if (p < pe) {
|
||||
argv[argc++] = p;
|
||||
}
|
||||
}
|
||||
// now add the prog
|
||||
argv[argc++] = (char *)a->prog;
|
||||
argv[argc] = 0;
|
||||
// ignore argv[0]
|
||||
if (*a->argv)
|
||||
++a->argv;
|
||||
// prepend arguments
|
||||
if ((i += mkntcmdline(sb->cmdline + i, argv, 32767 - i)) >= 32767 - 1)
|
||||
return e2big();
|
||||
sb->cmdline[i++] = ' ';
|
||||
sb->cmdline[i] = 0;
|
||||
// setup the true executable path
|
||||
if (__mkntpathath(a->dirhand, argv[0], 0, sb->path) == -1)
|
||||
return -1;
|
||||
} else {
|
||||
// it's something else
|
||||
return enoexec();
|
||||
}
|
||||
|
||||
// setup arguments and environment
|
||||
if ((i += mkntcmdline(sb->cmdline + i, a->argv, 32767 - i)) >= 32767)
|
||||
return e2big();
|
||||
if (mkntenvblock(sb->envblock, a->envp, a->extravars, sb->envbuf) == -1)
|
||||
return -1;
|
||||
|
||||
// create attribute list
|
||||
// this code won't call malloc in practice
|
||||
bool32 ok;
|
||||
void *freeme = 0;
|
||||
alignas(16) char memory[128];
|
||||
size_t size = sizeof(memory);
|
||||
struct NtProcThreadAttributeList *alist = (void *)memory;
|
||||
uint32_t items = !!a->opt_hParentProcess + !!a->opt_lpExplicitHandleList;
|
||||
ok = InitializeProcThreadAttributeList(alist, items, 0, &size);
|
||||
if (!ok && GetLastError() == kNtErrorInsufficientBuffer) {
|
||||
ok = !!(alist = freeme = ntspawn_malloc(size));
|
||||
if (ok) {
|
||||
ok = InitializeProcThreadAttributeList(alist, items, 0, &size);
|
||||
}
|
||||
}
|
||||
if (ok && a->opt_hParentProcess) {
|
||||
ok = UpdateProcThreadAttribute(
|
||||
alist, 0, kNtProcThreadAttributeParentProcess, &a->opt_hParentProcess,
|
||||
sizeof(a->opt_hParentProcess), 0, 0);
|
||||
}
|
||||
if (ok && a->opt_lpExplicitHandleList) {
|
||||
ok = UpdateProcThreadAttribute(
|
||||
alist, 0, kNtProcThreadAttributeHandleList, a->opt_lpExplicitHandleList,
|
||||
a->dwExplicitHandleCount * sizeof(*a->opt_lpExplicitHandleList), 0, 0);
|
||||
}
|
||||
|
||||
// create the process
|
||||
int rc;
|
||||
if (ok) {
|
||||
struct NtStartupInfoEx info = {
|
||||
.StartupInfo = *a->lpStartupInfo,
|
||||
.lpAttributeList = alist,
|
||||
};
|
||||
info.StartupInfo.cb = sizeof(info);
|
||||
if (ok) {
|
||||
if (CreateProcess(sb->path, sb->cmdline, 0, 0, true,
|
||||
a->dwCreationFlags | kNtCreateUnicodeEnvironment |
|
||||
kNtExtendedStartupinfoPresent |
|
||||
kNtInheritParentAffinity |
|
||||
GetPriorityClass(GetCurrentProcess()),
|
||||
sb->envblock, a->opt_lpCurrentDirectory,
|
||||
&info.StartupInfo, a->opt_out_lpProcessInformation)) {
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = -1;
|
||||
STRACE("CreateProcess() failed w/ %d", GetLastError());
|
||||
if (GetLastError() == kNtErrorSharingViolation) {
|
||||
etxtbsy();
|
||||
} else if (GetLastError() == kNtErrorInvalidName) {
|
||||
enoent();
|
||||
}
|
||||
}
|
||||
rc = __fix_enotdir(rc, sb->path);
|
||||
}
|
||||
} else {
|
||||
rc = __winerr();
|
||||
}
|
||||
|
||||
// clean up resources
|
||||
if (alist)
|
||||
DeleteProcThreadAttributeList(alist);
|
||||
if (freeme)
|
||||
ntspawn_free(freeme);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns process on Windows NT.
|
||||
*
|
||||
@@ -72,93 +232,15 @@ static void ntspawn_free(void *ptr) {
|
||||
* @see spawnve() which abstracts this function
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
textwindows int ntspawn(
|
||||
int64_t dirhand, const char *prog, char *const argv[], char *const envp[],
|
||||
char *const extravars[], uint32_t dwCreationFlags,
|
||||
const char16_t *opt_lpCurrentDirectory, int64_t opt_hParentProcess,
|
||||
int64_t *opt_lpExplicitHandleList, uint32_t dwExplicitHandleCount,
|
||||
const struct NtStartupInfo *lpStartupInfo,
|
||||
struct NtProcessInformation *opt_out_lpProcessInformation) {
|
||||
int rc = -1;
|
||||
textwindows int ntspawn(struct NtSpawnArgs *args) {
|
||||
int rc;
|
||||
struct SpawnBlock *sb;
|
||||
BLOCK_SIGNALS;
|
||||
if ((sb = ntspawn_malloc(sizeof(*sb))) &&
|
||||
__mkntpathath(dirhand, prog, 0, sb->path) != -1) {
|
||||
if (!mkntcmdline(sb->cmdline, argv) &&
|
||||
!mkntenvblock(sb->envblock, envp, extravars, sb->envbuf)) {
|
||||
bool32 ok;
|
||||
int64_t dp = GetCurrentProcess();
|
||||
|
||||
// create attribute list
|
||||
// this code won't call malloc in practice
|
||||
void *freeme = 0;
|
||||
_Alignas(16) char memory[128];
|
||||
size_t size = sizeof(memory);
|
||||
struct NtProcThreadAttributeList *alist = (void *)memory;
|
||||
uint32_t items = !!opt_hParentProcess + !!opt_lpExplicitHandleList;
|
||||
ok = InitializeProcThreadAttributeList(alist, items, 0, &size);
|
||||
if (!ok && GetLastError() == kNtErrorInsufficientBuffer) {
|
||||
ok = !!(alist = freeme = ntspawn_malloc(size));
|
||||
if (ok) {
|
||||
ok = InitializeProcThreadAttributeList(alist, items, 0, &size);
|
||||
}
|
||||
}
|
||||
if (ok && opt_hParentProcess) {
|
||||
ok = UpdateProcThreadAttribute(
|
||||
alist, 0, kNtProcThreadAttributeParentProcess, &opt_hParentProcess,
|
||||
sizeof(opt_hParentProcess), 0, 0);
|
||||
}
|
||||
if (ok && opt_lpExplicitHandleList) {
|
||||
ok = UpdateProcThreadAttribute(
|
||||
alist, 0, kNtProcThreadAttributeHandleList,
|
||||
opt_lpExplicitHandleList,
|
||||
dwExplicitHandleCount * sizeof(*opt_lpExplicitHandleList), 0, 0);
|
||||
}
|
||||
|
||||
// create the process
|
||||
if (ok) {
|
||||
struct NtStartupInfoEx info;
|
||||
bzero(&info, sizeof(info));
|
||||
info.StartupInfo = *lpStartupInfo;
|
||||
info.StartupInfo.cb = sizeof(info);
|
||||
info.lpAttributeList = alist;
|
||||
if (ok) {
|
||||
if (CreateProcess(sb->path, sb->cmdline, 0, 0, true,
|
||||
dwCreationFlags | kNtCreateUnicodeEnvironment |
|
||||
kNtExtendedStartupinfoPresent |
|
||||
kNtInheritParentAffinity |
|
||||
GetPriorityClass(GetCurrentProcess()),
|
||||
sb->envblock, opt_lpCurrentDirectory,
|
||||
&info.StartupInfo, opt_out_lpProcessInformation)) {
|
||||
rc = 0;
|
||||
} else {
|
||||
STRACE("CreateProcess() failed w/ %d", GetLastError());
|
||||
if (GetLastError() == kNtErrorSharingViolation) {
|
||||
etxtbsy();
|
||||
} else if (GetLastError() == kNtErrorInvalidName) {
|
||||
enoent();
|
||||
}
|
||||
}
|
||||
rc = __fix_enotdir(rc, sb->path);
|
||||
}
|
||||
} else {
|
||||
rc = __winerr();
|
||||
}
|
||||
|
||||
// clean up resources
|
||||
if (alist) {
|
||||
DeleteProcThreadAttributeList(alist);
|
||||
}
|
||||
if (freeme) {
|
||||
ntspawn_free(freeme);
|
||||
}
|
||||
if (dp && dp != GetCurrentProcess()) {
|
||||
CloseHandle(dp);
|
||||
}
|
||||
}
|
||||
if ((sb = ntspawn_malloc(sizeof(*sb)))) {
|
||||
rc = ntspawn2(args, sb);
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
if (sb)
|
||||
ntspawn_free(sb);
|
||||
ALLOW_SIGNALS;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -27,13 +27,13 @@
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
|
||||
@@ -1641,7 +1641,6 @@ static privileged void AllowMmapExec(struct Filter *f) {
|
||||
//
|
||||
// - MAP_LOCKED (0x02000)
|
||||
// - MAP_NONBLOCK (0x10000)
|
||||
// - MAP_HUGETLB (0x40000)
|
||||
//
|
||||
static privileged void AllowMmapNoexec(struct Filter *f) {
|
||||
static const struct sock_filter fragment[] = {
|
||||
@@ -1650,7 +1649,7 @@ static privileged void AllowMmapNoexec(struct Filter *f) {
|
||||
/*L2*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, ~(PROT_READ | PROT_WRITE)),
|
||||
/*L3*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 8 - 4),
|
||||
/*L4*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[3])), // flags
|
||||
/*L5*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x52000),
|
||||
/*L5*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x12000),
|
||||
/*L6*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 1),
|
||||
/*L7*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
|
||||
/*L8*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)),
|
||||
|
||||
+6
-1
@@ -30,6 +30,7 @@
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/stdio/sysparam.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
@@ -39,7 +40,7 @@
|
||||
*
|
||||
* @param fd is something open()'d earlier, noting pipes might not work
|
||||
* @param buf is copied into, cf. copy_file_range(), sendfile(), etc.
|
||||
* @param size in range [1..0x7ffff000] is reasonable
|
||||
* @param size is always saturated to 0x7ffff000 automatically
|
||||
* @param offset is bytes from start of file at which read begins
|
||||
* @return [1..size] bytes on success, 0 on EOF, or -1 w/ errno; with
|
||||
* exception of size==0, in which case return zero means no error
|
||||
@@ -58,6 +59,10 @@ ssize_t pread(int fd, void *buf, size_t size, int64_t offset) {
|
||||
ssize_t rc;
|
||||
BEGIN_CANCELATION_POINT;
|
||||
|
||||
// XNU and BSDs will EINVAL if requested bytes exceeds INT_MAX
|
||||
// this is inconsistent with Linux which ignores huge requests
|
||||
size = MIN(size, 0x7ffff000);
|
||||
|
||||
if (offset < 0) {
|
||||
rc = einval();
|
||||
} else if (fd < 0) {
|
||||
|
||||
+43
-7
@@ -28,24 +28,55 @@
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/stdckdint.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static size_t SumIovecBytes(const struct iovec *iov, int iovlen) {
|
||||
size_t count = 0;
|
||||
for (int i = 0; i < iovlen; ++i)
|
||||
if (ckd_add(&count, count, iov[i].iov_len))
|
||||
count = SIZE_MAX;
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t Preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
|
||||
int e, i;
|
||||
size_t got;
|
||||
ssize_t rc, toto;
|
||||
|
||||
if (fd < 0) {
|
||||
if (fd < 0)
|
||||
return ebadf();
|
||||
}
|
||||
|
||||
if (iovlen < 0) {
|
||||
if (iovlen < 0)
|
||||
return einval();
|
||||
}
|
||||
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen))
|
||||
return efault();
|
||||
|
||||
// XNU and BSDs will EINVAL if requested bytes exceeds INT_MAX
|
||||
// this is inconsistent with Linux which ignores huge requests
|
||||
if (!IsLinux()) {
|
||||
size_t sum, remain = 0x7ffff000;
|
||||
if ((sum = SumIovecBytes(iov, iovlen)) > remain) {
|
||||
struct iovec *iov2;
|
||||
#pragma GCC push_options
|
||||
#pragma GCC diagnostic ignored "-Walloca-larger-than="
|
||||
iov2 = alloca(iovlen * sizeof(struct iovec));
|
||||
CheckLargeStackAllocation(iov2, iovlen * sizeof(struct iovec));
|
||||
#pragma GCC pop_options
|
||||
for (int i = 0; i < iovlen; ++i) {
|
||||
iov2[i] = iov[i];
|
||||
if (remain >= iov2[i].iov_len) {
|
||||
remain -= iov2[i].iov_len;
|
||||
} else {
|
||||
iov2[i].iov_len = remain;
|
||||
remain = 0;
|
||||
}
|
||||
}
|
||||
iov = iov2;
|
||||
}
|
||||
}
|
||||
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
@@ -112,6 +143,11 @@ static ssize_t Preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
|
||||
/**
|
||||
* Reads with maximum generality.
|
||||
*
|
||||
* It's possible for file write request to be partially completed. For
|
||||
* example, if the sum of `iov` lengths exceeds 0x7ffff000 then bytes
|
||||
* beyond that will be ignored. This is a Linux behavior that Cosmo
|
||||
* polyfills across platforms.
|
||||
*
|
||||
* @return number of bytes actually read, or -1 w/ errno
|
||||
* @cancelationpoint
|
||||
* @asyncsignalsafe
|
||||
|
||||
+6
-1
@@ -28,6 +28,7 @@
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/stdio/sysparam.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
@@ -37,7 +38,7 @@
|
||||
*
|
||||
* @param fd is something open()'d earlier, noting pipes might not work
|
||||
* @param buf is copied from, cf. copy_file_range(), sendfile(), etc.
|
||||
* @param size in range [1..0x7ffff000] is reasonable
|
||||
* @param size is always saturated to 0x7ffff000 automatically
|
||||
* @param offset is bytes from start of file at which write begins,
|
||||
* which can exceed or overlap the end of file, in which case your
|
||||
* file will be extended
|
||||
@@ -53,6 +54,10 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
|
||||
size_t wrote;
|
||||
BEGIN_CANCELATION_POINT;
|
||||
|
||||
// XNU and BSDs will EINVAL if requested bytes exceeds INT_MAX
|
||||
// this is inconsistent with Linux which ignores huge requests
|
||||
size = MIN(size, 0x7ffff000);
|
||||
|
||||
if (offset < 0) {
|
||||
rc = einval();
|
||||
} else if (fd == -1) {
|
||||
|
||||
+44
-10
@@ -28,28 +28,57 @@
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/stdckdint.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static size_t SumIovecBytes(const struct iovec *iov, int iovlen) {
|
||||
size_t count = 0;
|
||||
for (int i = 0; i < iovlen; ++i)
|
||||
if (ckd_add(&count, count, iov[i].iov_len))
|
||||
count = SIZE_MAX;
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t Pwritev(int fd, const struct iovec *iov, int iovlen,
|
||||
int64_t off) {
|
||||
int i, e;
|
||||
size_t sent;
|
||||
ssize_t rc, toto;
|
||||
|
||||
if (fd < 0) {
|
||||
if (fd < 0)
|
||||
return ebadf();
|
||||
}
|
||||
|
||||
if (iovlen < 0) {
|
||||
if (iovlen < 0)
|
||||
return einval();
|
||||
}
|
||||
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen))
|
||||
return efault();
|
||||
}
|
||||
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip)
|
||||
return ebadf();
|
||||
|
||||
// XNU and BSDs will EINVAL if requested bytes exceeds INT_MAX
|
||||
// this is inconsistent with Linux which ignores huge requests
|
||||
if (!IsLinux()) {
|
||||
size_t sum, remain = 0x7ffff000;
|
||||
if ((sum = SumIovecBytes(iov, iovlen)) > remain) {
|
||||
struct iovec *iov2;
|
||||
#pragma GCC push_options
|
||||
#pragma GCC diagnostic ignored "-Walloca-larger-than="
|
||||
iov2 = alloca(iovlen * sizeof(struct iovec));
|
||||
CheckLargeStackAllocation(iov2, iovlen * sizeof(struct iovec));
|
||||
#pragma GCC pop_options
|
||||
for (int i = 0; i < iovlen; ++i) {
|
||||
iov2[i] = iov[i];
|
||||
if (remain >= iov2[i].iov_len) {
|
||||
remain -= iov2[i].iov_len;
|
||||
} else {
|
||||
iov2[i].iov_len = remain;
|
||||
remain = 0;
|
||||
}
|
||||
}
|
||||
iov = iov2;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsWindows()) {
|
||||
@@ -116,6 +145,11 @@ static ssize_t Pwritev(int fd, const struct iovec *iov, int iovlen,
|
||||
* been committed. It can also happen if we need to polyfill this system
|
||||
* call using pwrite().
|
||||
*
|
||||
* It's possible for file write request to be partially completed. For
|
||||
* example, if the sum of `iov` lengths exceeds 0x7ffff000 then bytes
|
||||
* beyond that will be ignored. This is a Linux behavior that Cosmo
|
||||
* polyfills across platforms.
|
||||
*
|
||||
* @return number of bytes actually sent, or -1 w/ errno
|
||||
* @cancelationpoint
|
||||
* @asyncsignalsafe
|
||||
|
||||
+6
-1
@@ -29,6 +29,7 @@
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/stdio/sysparam.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
@@ -41,7 +42,7 @@
|
||||
*
|
||||
* @param fd is something open()'d earlier
|
||||
* @param buf is copied into, cf. copy_file_range(), sendfile(), etc.
|
||||
* @param size in range [1..0x7ffff000] is reasonable
|
||||
* @param size is always saturated to 0x7ffff000 automatically
|
||||
* @return [1..size] bytes on success, 0 on EOF, or -1 w/ errno; with
|
||||
* exception of size==0, in which case return zero means no error
|
||||
* @raise EBADF if `fd` is negative or not an open file descriptor
|
||||
@@ -67,6 +68,10 @@ ssize_t read(int fd, void *buf, size_t size) {
|
||||
ssize_t rc;
|
||||
BEGIN_CANCELATION_POINT;
|
||||
|
||||
// XNU and BSDs will EINVAL if requested bytes exceeds INT_MAX
|
||||
// this is inconsistent with Linux which ignores huge requests
|
||||
size = MIN(size, 0x7ffff000);
|
||||
|
||||
if (fd < 0) {
|
||||
rc = ebadf();
|
||||
} else if ((!buf && size) || (IsAsan() && !__asan_is_valid(buf, size))) {
|
||||
|
||||
+70
-26
@@ -28,10 +28,74 @@
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/stdckdint.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static size_t SumIovecBytes(const struct iovec *iov, int iovlen) {
|
||||
size_t count = 0;
|
||||
for (int i = 0; i < iovlen; ++i)
|
||||
if (ckd_add(&count, count, iov[i].iov_len))
|
||||
count = SIZE_MAX;
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t readv_impl(int fd, const struct iovec *iov, int iovlen) {
|
||||
if (fd < 0)
|
||||
return ebadf();
|
||||
if (iovlen < 0)
|
||||
return einval();
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen))
|
||||
return efault();
|
||||
|
||||
// XNU and BSDs will EINVAL if requested bytes exceeds INT_MAX
|
||||
// this is inconsistent with Linux which ignores huge requests
|
||||
if (!IsLinux()) {
|
||||
size_t sum, remain = 0x7ffff000;
|
||||
if ((sum = SumIovecBytes(iov, iovlen)) > remain) {
|
||||
struct iovec *iov2;
|
||||
#pragma GCC push_options
|
||||
#pragma GCC diagnostic ignored "-Walloca-larger-than="
|
||||
iov2 = alloca(iovlen * sizeof(struct iovec));
|
||||
CheckLargeStackAllocation(iov2, iovlen * sizeof(struct iovec));
|
||||
#pragma GCC pop_options
|
||||
for (int i = 0; i < iovlen; ++i) {
|
||||
iov2[i] = iov[i];
|
||||
if (remain >= iov2[i].iov_len) {
|
||||
remain -= iov2[i].iov_len;
|
||||
} else {
|
||||
iov2[i].iov_len = remain;
|
||||
remain = 0;
|
||||
}
|
||||
}
|
||||
iov = iov2;
|
||||
}
|
||||
}
|
||||
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return _weaken(__zipos_read)(
|
||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
|
||||
} else if (IsLinux() || IsXnu() || IsFreebsd() || IsOpenbsd() || IsNetbsd()) {
|
||||
if (iovlen == 1) {
|
||||
return sys_read(fd, iov[0].iov_base, iov[0].iov_len);
|
||||
} else {
|
||||
return sys_readv(fd, iov, iovlen);
|
||||
}
|
||||
} else if (fd >= g_fds.n) {
|
||||
return ebadf();
|
||||
} else if (IsMetal()) {
|
||||
return sys_readv_metal(fd, iov, iovlen);
|
||||
} else if (IsWindows()) {
|
||||
return sys_readv_nt(fd, iov, iovlen);
|
||||
} else {
|
||||
return enosys();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads data to multiple buffers.
|
||||
*
|
||||
@@ -42,6 +106,11 @@
|
||||
* be passed to the kernel as read() instead. This yields a 100 cycle
|
||||
* performance boost in the case of a single small iovec.
|
||||
*
|
||||
* It's possible for file write request to be partially completed. For
|
||||
* example, if the sum of `iov` lengths exceeds 0x7ffff000 then bytes
|
||||
* beyond that will be ignored. This is a Linux behavior that Cosmo
|
||||
* polyfills across platforms.
|
||||
*
|
||||
* @return number of bytes actually read, or -1 w/ errno
|
||||
* @cancelationpoint
|
||||
* @restartable
|
||||
@@ -49,32 +118,7 @@
|
||||
ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
|
||||
ssize_t rc;
|
||||
BEGIN_CANCELATION_POINT;
|
||||
|
||||
if (fd < 0) {
|
||||
rc = ebadf();
|
||||
} else if (iovlen < 0) {
|
||||
rc = einval();
|
||||
} else if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
|
||||
rc = efault();
|
||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = _weaken(__zipos_read)(
|
||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
|
||||
} else if (IsLinux() || IsXnu() || IsFreebsd() || IsOpenbsd() || IsNetbsd()) {
|
||||
if (iovlen == 1) {
|
||||
rc = sys_read(fd, iov[0].iov_base, iov[0].iov_len);
|
||||
} else {
|
||||
rc = sys_readv(fd, iov, iovlen);
|
||||
}
|
||||
} else if (fd >= g_fds.n) {
|
||||
rc = ebadf();
|
||||
} else if (IsMetal()) {
|
||||
rc = sys_readv_metal(fd, iov, iovlen);
|
||||
} else if (IsWindows()) {
|
||||
rc = sys_readv_nt(fd, iov, iovlen);
|
||||
} else {
|
||||
rc = enosys();
|
||||
}
|
||||
|
||||
rc = readv_impl(fd, iov, iovlen);
|
||||
END_CANCELATION_POINT;
|
||||
STRACE("readv(%d, [%s], %d) → %'ld% m", fd, DescribeIovec(rc, iov, iovlen),
|
||||
iovlen, rc);
|
||||
|
||||
+1
-4
@@ -19,7 +19,6 @@
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/framebuffervirtualscreeninfo.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/enum/version.h"
|
||||
#include "libc/nt/system.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
@@ -72,9 +71,7 @@ int reboot(int howto) {
|
||||
} else {
|
||||
howto |= kNtShutdownForceSelf;
|
||||
howto |= kNtShutdownForceOthers;
|
||||
if (NtGetVersion() >= kNtVersionWindows8) {
|
||||
howto |= kNtShutdownHybrid;
|
||||
}
|
||||
howto |= kNtShutdownHybrid;
|
||||
if (immediately) {
|
||||
ok = !!InitiateShutdown(0, 0, 0, howto | kNtShutdownGraceOverride, 0);
|
||||
} else {
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Renames files relative to directories.
|
||||
|
||||
@@ -17,14 +17,12 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/cpuset.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nexgen32e/rdtscp.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/nt/struct/processornumber.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/runtime/syslib.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int sys_getcpu(unsigned *opt_cpu, unsigned *opt_node, void *tcache);
|
||||
@@ -38,23 +36,14 @@ int sched_getcpu(void) {
|
||||
unsigned tsc_aux;
|
||||
rdtscp(&tsc_aux);
|
||||
return TSC_AUX_CORE(tsc_aux);
|
||||
} else if (IsAarch64()) {
|
||||
long tpidr_el0;
|
||||
asm("mrs\t%0,tpidr_el0" : "=r"(tpidr_el0));
|
||||
return tpidr_el0 & 255;
|
||||
} else if (IsWindows()) {
|
||||
struct NtProcessorNumber pn;
|
||||
GetCurrentProcessorNumberEx(&pn);
|
||||
return 64 * pn.Group + pn.Number;
|
||||
} else if (IsXnuSilicon()) {
|
||||
if (__syslib->__version >= 9) {
|
||||
size_t cpu;
|
||||
errno_t err = __syslib->__pthread_cpu_number_np(&cpu);
|
||||
if (!err) {
|
||||
return cpu;
|
||||
} else {
|
||||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return enosys();
|
||||
}
|
||||
} else {
|
||||
unsigned cpu = 0;
|
||||
int rc = sys_getcpu(&cpu, 0, 0);
|
||||
|
||||
+27
-75
@@ -301,7 +301,7 @@ static textwindows wontreturn void __sig_tramp(struct SignalFrame *sf) {
|
||||
}
|
||||
|
||||
// sends signal to another specific thread which is ref'd
|
||||
static int __sig_killer(struct PosixThread *pt, int sig, int sic) {
|
||||
static textwindows int __sig_killer(struct PosixThread *pt, int sig, int sic) {
|
||||
unsigned rva = __sighandrvas[sig];
|
||||
unsigned flags = __sighandflags[sig];
|
||||
|
||||
@@ -462,66 +462,7 @@ textwindows void __sig_generate(int sig, int sic) {
|
||||
ALLOW_SIGNALS;
|
||||
}
|
||||
|
||||
static int __sig_crash_sig(struct NtExceptionPointers *ep, int *code) {
|
||||
switch (ep->ExceptionRecord->ExceptionCode) {
|
||||
case kNtSignalBreakpoint:
|
||||
*code = TRAP_BRKPT;
|
||||
return SIGTRAP;
|
||||
case kNtSignalIllegalInstruction:
|
||||
*code = ILL_ILLOPC;
|
||||
return SIGILL;
|
||||
case kNtSignalPrivInstruction:
|
||||
*code = ILL_PRVOPC;
|
||||
return SIGILL;
|
||||
case kNtSignalInPageError:
|
||||
case kNtStatusStackOverflow:
|
||||
*code = SEGV_MAPERR;
|
||||
return SIGSEGV;
|
||||
case kNtSignalGuardPage:
|
||||
case kNtSignalAccessViolation:
|
||||
*code = SEGV_ACCERR;
|
||||
return SIGSEGV;
|
||||
case kNtSignalInvalidHandle:
|
||||
case kNtSignalInvalidParameter:
|
||||
case kNtSignalAssertionFailure:
|
||||
*code = SI_USER;
|
||||
return SIGABRT;
|
||||
case kNtStatusIntegerOverflow:
|
||||
*code = FPE_INTOVF;
|
||||
return SIGFPE;
|
||||
case kNtSignalFltDivideByZero:
|
||||
*code = FPE_FLTDIV;
|
||||
return SIGFPE;
|
||||
case kNtSignalFltOverflow:
|
||||
*code = FPE_FLTOVF;
|
||||
return SIGFPE;
|
||||
case kNtSignalFltUnderflow:
|
||||
*code = FPE_FLTUND;
|
||||
return SIGFPE;
|
||||
case kNtSignalFltInexactResult:
|
||||
*code = FPE_FLTRES;
|
||||
return SIGFPE;
|
||||
case kNtSignalFltDenormalOperand:
|
||||
case kNtSignalFltInvalidOperation:
|
||||
case kNtSignalFltStackCheck:
|
||||
case kNtSignalIntegerDivideByZero:
|
||||
case kNtSignalFloatMultipleFaults:
|
||||
case kNtSignalFloatMultipleTraps:
|
||||
*code = FPE_FLTINV;
|
||||
return SIGFPE;
|
||||
case kNtSignalDllNotFound:
|
||||
case kNtSignalOrdinalNotFound:
|
||||
case kNtSignalEntrypointNotFound:
|
||||
case kNtSignalDllInitFailed:
|
||||
*code = SI_KERNEL;
|
||||
return SIGSYS;
|
||||
default:
|
||||
*code = ep->ExceptionRecord->ExceptionCode;
|
||||
return SIGSEGV;
|
||||
}
|
||||
}
|
||||
|
||||
static char *__sig_stpcpy(char *d, const char *s) {
|
||||
static textwindows char *__sig_stpcpy(char *d, const char *s) {
|
||||
size_t i;
|
||||
for (i = 0;; ++i) {
|
||||
if (!(d[i] = s[i])) {
|
||||
@@ -530,8 +471,24 @@ static char *__sig_stpcpy(char *d, const char *s) {
|
||||
}
|
||||
}
|
||||
|
||||
static void __sig_unmaskable(struct NtExceptionPointers *ep, int code, int sig,
|
||||
struct CosmoTib *tib) {
|
||||
static textwindows wontreturn void __sig_death(int sig, const char *thing) {
|
||||
#ifndef TINY
|
||||
intptr_t hStderr;
|
||||
char sigbuf[21], s[128], *p;
|
||||
hStderr = GetStdHandle(kNtStdErrorHandle);
|
||||
p = __sig_stpcpy(s, "Terminating on ");
|
||||
p = __sig_stpcpy(p, thing);
|
||||
p = __sig_stpcpy(p, strsignal_r(sig, sigbuf));
|
||||
p = __sig_stpcpy(p,
|
||||
". Pass --strace and/or ShowCrashReports() for details.\n");
|
||||
WriteFile(hStderr, s, p - s, 0, 0);
|
||||
#endif
|
||||
__sig_terminate(sig);
|
||||
}
|
||||
|
||||
static textwindows void __sig_unmaskable(struct NtExceptionPointers *ep,
|
||||
int code, int sig,
|
||||
struct CosmoTib *tib) {
|
||||
|
||||
// log vital crash information reliably for --strace before doing much
|
||||
// we don't print this without the flag since raw numbers scare people
|
||||
@@ -549,17 +506,7 @@ static void __sig_unmaskable(struct NtExceptionPointers *ep, int code, int sig,
|
||||
// exception, then print a friendly helpful hint message to stderr
|
||||
unsigned rva = __sighandrvas[sig];
|
||||
if (rva == (intptr_t)SIG_DFL || rva == (intptr_t)SIG_IGN) {
|
||||
#ifndef TINY
|
||||
intptr_t hStderr;
|
||||
char sigbuf[21], s[128], *p;
|
||||
hStderr = GetStdHandle(kNtStdErrorHandle);
|
||||
p = __sig_stpcpy(s, "Terminating on uncaught ");
|
||||
p = __sig_stpcpy(p, strsignal_r(sig, sigbuf));
|
||||
p = __sig_stpcpy(
|
||||
p, ". Pass --strace and/or ShowCrashReports() for details.\n");
|
||||
WriteFile(hStderr, s, p - s, 0, 0);
|
||||
#endif
|
||||
__sig_terminate(sig);
|
||||
__sig_death(sig, "uncaught ");
|
||||
}
|
||||
|
||||
// if this signal handler is configured to auto-reset to the default
|
||||
@@ -580,8 +527,9 @@ static void __sig_unmaskable(struct NtExceptionPointers *ep, int code, int sig,
|
||||
}
|
||||
|
||||
// call the user signal handler
|
||||
// with a temporarily replaced signal mask
|
||||
// and a modifiable view of the faulting code's cpu state
|
||||
// temporarily replace signal mask while calling crash handler
|
||||
// abort process if sig is already blocked to avoid crash loop
|
||||
// note ucontext_t is a hefty data structures on top of NtContext
|
||||
ucontext_t ctx = {0};
|
||||
siginfo_t si = {.si_signo = sig, .si_code = code, .si_addr = si_addr};
|
||||
@@ -591,6 +539,10 @@ static void __sig_unmaskable(struct NtExceptionPointers *ep, int code, int sig,
|
||||
blocksigs |= 1ull << (sig - 1);
|
||||
ctx.uc_sigmask = atomic_fetch_or_explicit(&tib->tib_sigmask, blocksigs,
|
||||
memory_order_acquire);
|
||||
if (ctx.uc_sigmask & (1ull << (sig - 1))) {
|
||||
__sig_death(sig, "masked ");
|
||||
__sig_terminate(sig);
|
||||
}
|
||||
__sig_handler(rva)(sig, &si, &ctx);
|
||||
atomic_store_explicit(&tib->tib_sigmask, ctx.uc_sigmask,
|
||||
memory_order_release);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef COSMOPOLITAN_LIBC_CALLS_SIGNALS_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_SIGNALS_INTERNAL_H_
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/nt/struct/ntexceptionpointers.h"
|
||||
#include "libc/thread/posixthread.internal.h"
|
||||
|
||||
#define SIG_HANDLED_NO_RESTART 1
|
||||
@@ -17,11 +18,12 @@ extern struct Signals __sig;
|
||||
|
||||
bool __sig_ignored(int);
|
||||
int __sig_check(void);
|
||||
int __sig_crash_sig(struct NtExceptionPointers *, int *);
|
||||
int __sig_get(sigset_t);
|
||||
int __sig_kill(struct PosixThread *, int, int);
|
||||
int __sig_mask(int, const sigset_t *, sigset_t *);
|
||||
int __sig_relay(int, int, sigset_t);
|
||||
int __sig_raise(int, int);
|
||||
int __sig_get(sigset_t);
|
||||
int __sig_relay(int, int, sigset_t);
|
||||
void __sig_delete(int);
|
||||
void __sig_generate(int, int);
|
||||
void __sig_init(void);
|
||||
|
||||
@@ -252,6 +252,12 @@ static int __sigaction(int sig, const struct sigaction *act,
|
||||
rc = sys_sigaction(sig, ap, oldact, arg4, arg5);
|
||||
} else {
|
||||
rc = _sysret(__syslib->__sigaction(sig, ap, oldact));
|
||||
// xnu silicon claims to support sa_resethand but it does nothing
|
||||
// this can be tested, since it clears the bit from flags as well
|
||||
if (!rc && oldact &&
|
||||
(((struct sigaction_silicon *)oldact)->sa_flags & SA_RESETHAND)) {
|
||||
((struct sigaction_silicon *)oldact)->sa_flags |= SA_RESETHAND;
|
||||
}
|
||||
}
|
||||
if (rc != -1) {
|
||||
sigaction_native2cosmo((union metasigaction *)oldact);
|
||||
@@ -415,7 +421,7 @@ static int __sigaction(int sig, const struct sigaction *act,
|
||||
* ctx->uc_mcontext.rip += xedd.length;
|
||||
* }
|
||||
*
|
||||
* void OnCrash(int sig, struct siginfo *si, void *vctx) {
|
||||
* void OnCrash(int sig, siginfo_t *si, void *vctx) {
|
||||
* struct ucontext *ctx = vctx;
|
||||
* SkipOverFaultingInstruction(ctx);
|
||||
* ContinueOnCrash(); // reinstall here in case *rip faults
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2024 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/calls/sig.internal.h"
|
||||
#include "libc/intrin/pushpop.internal.h"
|
||||
#include "libc/nt/enum/signal.h"
|
||||
#include "libc/nt/enum/status.h"
|
||||
#include "libc/nt/struct/ntexceptionpointers.h"
|
||||
|
||||
// this is all a mandatory dependency of winmain
|
||||
// so, we trade away maintanibility for tininess
|
||||
// see libc/sysv/consts.sh for canonical magnums
|
||||
|
||||
#define SIGILL_ pushpop(4)
|
||||
#define SIGTRAP_ pushpop(5)
|
||||
#define SIGABRT_ pushpop(6)
|
||||
#define SIGFPE_ pushpop(8)
|
||||
#define SIGSEGV_ pushpop(11)
|
||||
#define SIGSYS_ pushpop(31)
|
||||
|
||||
#define TRAP_BRKPT_ pushpop(1)
|
||||
#define ILL_ILLOPC_ pushpop(1)
|
||||
#define ILL_PRVOPC_ pushpop(5)
|
||||
#define SEGV_MAPERR_ pushpop(1)
|
||||
#define SEGV_ACCERR_ pushpop(2)
|
||||
#define SI_USER_ pushpop(0)
|
||||
#define FPE_FLTDIV_ pushpop(3)
|
||||
#define FPE_FLTOVF_ pushpop(4)
|
||||
#define FPE_INTOVF_ pushpop(2)
|
||||
#define FPE_FLTUND_ pushpop(5)
|
||||
#define FPE_FLTRES_ pushpop(6)
|
||||
#define FPE_FLTINV_ pushpop(7)
|
||||
#define SI_KERNEL_ 0x80
|
||||
|
||||
textwindows int __sig_crash_sig(struct NtExceptionPointers *ep, int *code) {
|
||||
switch (ep->ExceptionRecord->ExceptionCode) {
|
||||
case kNtSignalBreakpoint:
|
||||
*code = TRAP_BRKPT_;
|
||||
return SIGTRAP_;
|
||||
case kNtSignalIllegalInstruction:
|
||||
*code = ILL_ILLOPC_;
|
||||
return SIGILL_;
|
||||
case kNtSignalPrivInstruction:
|
||||
*code = ILL_PRVOPC_;
|
||||
return SIGILL_;
|
||||
case kNtSignalInPageError:
|
||||
case kNtStatusStackOverflow:
|
||||
*code = SEGV_MAPERR_;
|
||||
return SIGSEGV_;
|
||||
case kNtSignalGuardPage:
|
||||
case kNtSignalAccessViolation:
|
||||
*code = SEGV_ACCERR_;
|
||||
return SIGSEGV_;
|
||||
case kNtSignalInvalidHandle:
|
||||
case kNtSignalInvalidParameter:
|
||||
case kNtSignalAssertionFailure:
|
||||
*code = SI_USER_;
|
||||
return SIGABRT_;
|
||||
case kNtStatusIntegerOverflow:
|
||||
*code = FPE_INTOVF_;
|
||||
return SIGFPE_;
|
||||
case kNtSignalFltDivideByZero:
|
||||
*code = FPE_FLTDIV_;
|
||||
return SIGFPE_;
|
||||
case kNtSignalFltOverflow:
|
||||
*code = FPE_FLTOVF_;
|
||||
return SIGFPE_;
|
||||
case kNtSignalFltUnderflow:
|
||||
*code = FPE_FLTUND_;
|
||||
return SIGFPE_;
|
||||
case kNtSignalFltInexactResult:
|
||||
*code = FPE_FLTRES_;
|
||||
return SIGFPE_;
|
||||
case kNtSignalFltDenormalOperand:
|
||||
case kNtSignalFltInvalidOperation:
|
||||
case kNtSignalFltStackCheck:
|
||||
case kNtSignalIntegerDivideByZero:
|
||||
case kNtSignalFloatMultipleFaults:
|
||||
case kNtSignalFloatMultipleTraps:
|
||||
*code = FPE_FLTINV_;
|
||||
return SIGFPE_;
|
||||
case kNtSignalDllNotFound:
|
||||
case kNtSignalOrdinalNotFound:
|
||||
case kNtSignalEntrypointNotFound:
|
||||
case kNtSignalDllInitFailed:
|
||||
*code = SI_KERNEL_;
|
||||
return SIGSYS_;
|
||||
default:
|
||||
*code = ep->ExceptionRecord->ExceptionCode;
|
||||
return SIGSEGV_;
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
privileged void __sigenter_wsl(int sig, struct siginfo *info, ucontext_t *ctx) {
|
||||
privileged void __sigenter_wsl(int sig, siginfo_t *info, ucontext_t *ctx) {
|
||||
int rva, flags;
|
||||
rva = __sighandrvas[sig];
|
||||
if (rva >= kSigactionMinRva) {
|
||||
|
||||
@@ -43,7 +43,7 @@ privileged void __sigenter_netbsd(int sig, struct siginfo_netbsd *si,
|
||||
CheckLargeStackAllocation(&uc, sizeof(uc));
|
||||
#pragma GCC pop_options
|
||||
int rva, flags;
|
||||
struct siginfo si2;
|
||||
siginfo_t si2;
|
||||
rva = __sighandrvas[sig];
|
||||
if (rva >= kSigactionMinRva) {
|
||||
flags = __sighandflags[sig];
|
||||
|
||||
@@ -41,7 +41,7 @@ privileged void __sigenter_openbsd(int sig, struct siginfo_openbsd *openbsdinfo,
|
||||
#pragma GCC diagnostic ignored "-Wframe-larger-than="
|
||||
struct Goodies {
|
||||
ucontext_t uc;
|
||||
struct siginfo si;
|
||||
siginfo_t si;
|
||||
} g;
|
||||
CheckLargeStackAllocation(&g, sizeof(g));
|
||||
#pragma GCC pop_options
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/runtime/syslib.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
|
||||
@@ -494,6 +495,8 @@ privileged void __sigenter_xnu(void *fn, int infostyle, int sig,
|
||||
privileged void __sigenter_xnu(int sig, struct siginfo_xnu *xnuinfo,
|
||||
struct __darwin_ucontext *xnuctx) {
|
||||
#endif
|
||||
|
||||
// allocate signal frame on stack
|
||||
#pragma GCC push_options
|
||||
#pragma GCC diagnostic ignored "-Wframe-larger-than="
|
||||
struct Goodies {
|
||||
@@ -502,10 +505,24 @@ privileged void __sigenter_xnu(int sig, struct siginfo_xnu *xnuinfo,
|
||||
} g;
|
||||
CheckLargeStackAllocation(&g, sizeof(g));
|
||||
#pragma GCC pop_options
|
||||
|
||||
// handle signal
|
||||
int rva, flags;
|
||||
rva = __sighandrvas[sig];
|
||||
if (rva >= kSigactionMinRva) {
|
||||
flags = __sighandflags[sig];
|
||||
|
||||
#ifdef __aarch64__
|
||||
// xnu silicon claims to support sa_resethand but it does nothing
|
||||
// this can be tested, since it clears the bit from flags as well
|
||||
if (flags & SA_RESETHAND) {
|
||||
struct sigaction sa = {0};
|
||||
__syslib->__sigaction(sig, &sa, 0);
|
||||
__sighandflags[sig] = 0;
|
||||
__sighandrvas[sig] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (~flags & SA_SIGINFO) {
|
||||
((sigaction_f)(__executable_start + rva))(sig, 0, 0);
|
||||
} else {
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
privileged void __siginfo2cosmo(struct siginfo *si,
|
||||
const union siginfo_meta *m) {
|
||||
privileged void __siginfo2cosmo(siginfo_t *si, const union siginfo_meta *m) {
|
||||
void *si_addr;
|
||||
int32_t si_signo;
|
||||
int32_t si_errno;
|
||||
@@ -93,7 +92,7 @@ privileged void __siginfo2cosmo(struct siginfo *si,
|
||||
}
|
||||
}
|
||||
|
||||
*si = (struct siginfo){0};
|
||||
*si = (siginfo_t){0};
|
||||
si->si_signo = si_signo;
|
||||
si->si_errno = si_errno;
|
||||
si->si_code = si_code;
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "libc/mem/alloca.h"
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
ssize_t __robust_writev(int, struct iovec *, int);
|
||||
int64_t sys_preadv(int, struct iovec *, int, int64_t, int64_t);
|
||||
int64_t sys_pwritev(int, const struct iovec *, int, int64_t, int64_t);
|
||||
int64_t sys_readv(int32_t, const struct iovec *, int32_t);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
typedef void (*sighandler_t)(int);
|
||||
typedef void (*sigaction_f)(int, struct siginfo *, void *);
|
||||
typedef void (*sigaction_f)(int, siginfo_t *, void *);
|
||||
|
||||
struct sigaction {
|
||||
union {
|
||||
|
||||
@@ -60,11 +60,11 @@ union metasigaction {
|
||||
struct sigaction_xnu_out xnu_out;
|
||||
};
|
||||
|
||||
void __sigenter_xnu(int, struct siginfo *, void *);
|
||||
void __sigenter_wsl(int, struct siginfo *, void *);
|
||||
void __sigenter_netbsd(int, struct siginfo *, void *);
|
||||
void __sigenter_freebsd(int, struct siginfo *, void *);
|
||||
void __sigenter_openbsd(int, struct siginfo *, void *);
|
||||
void __sigenter_xnu(int, siginfo_t *, void *);
|
||||
void __sigenter_wsl(int, siginfo_t *, void *);
|
||||
void __sigenter_netbsd(int, siginfo_t *, void *);
|
||||
void __sigenter_freebsd(int, siginfo_t *, void *);
|
||||
void __sigenter_openbsd(int, siginfo_t *, void *);
|
||||
|
||||
const char *DescribeSigaction(char[256], int, const struct sigaction *);
|
||||
#define DescribeSigaction(rc, sa) DescribeSigaction(alloca(256), rc, sa)
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
union siginfo_meta {
|
||||
struct siginfo linux;
|
||||
siginfo_t linux;
|
||||
struct siginfo_xnu xnu;
|
||||
struct siginfo_freebsd freebsd;
|
||||
struct siginfo_openbsd openbsd;
|
||||
struct siginfo_netbsd netbsd;
|
||||
};
|
||||
|
||||
void __siginfo2cosmo(struct siginfo *, const union siginfo_meta *);
|
||||
void __siginfo2cosmo(siginfo_t *, const union siginfo_meta *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_META_INTERNAL_H_ */
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "libc/intrin/nomultics.internal.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/enum/consolemodeflags.h"
|
||||
#include "libc/nt/version.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/baud.internal.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
@@ -96,9 +95,7 @@ textwindows int tcsetattr_nt(int fd, int opt, const struct termios *tio) {
|
||||
if (!(tio->c_oflag & ONLCR)) {
|
||||
outmode |= kNtDisableNewlineAutoReturn;
|
||||
}
|
||||
if (IsAtLeastWindows10()) {
|
||||
outmode |= kNtEnableVirtualTerminalProcessing;
|
||||
}
|
||||
outmode |= kNtEnableVirtualTerminalProcessing;
|
||||
|
||||
// tune the win32 configuration
|
||||
unassert(SetConsoleMode(hInput, inmode));
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/stdio/sysparam.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/paths.h"
|
||||
#include "libc/stdio/sysparam.h"
|
||||
|
||||
/**
|
||||
* Returns name of terminal.
|
||||
|
||||
+6
-28
@@ -30,7 +30,6 @@
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/enum/computernameformat.h"
|
||||
#include "libc/nt/struct/teb.h"
|
||||
#include "libc/nt/systeminfo.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
@@ -81,34 +80,13 @@ static textwindows void GetNtName(char *name, int kind) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline textwindows int GetNtMajorVersion(void) {
|
||||
#ifdef __x86_64__
|
||||
return NtGetPeb()->OSMajorVersion;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline textwindows int GetNtMinorVersion(void) {
|
||||
#ifdef __x86_64__
|
||||
return NtGetPeb()->OSMinorVersion;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline textwindows int GetNtBuildNumber(void) {
|
||||
#ifdef __x86_64__
|
||||
return NtGetPeb()->OSBuildNumber;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static textwindows void GetNtVersion(char *p) {
|
||||
p = FormatUint32(p, GetNtMajorVersion()), *p++ = '.';
|
||||
p = FormatUint32(p, GetNtMinorVersion()), *p++ = '-';
|
||||
p = FormatUint32(p, GetNtBuildNumber());
|
||||
// We could ask GetVersionExW() for this information, but it'll simply
|
||||
// report what we put in the MajorOperatingSystemVersion of the PE ape
|
||||
// header fields. Windows doesn't want us detecting versions it seems.
|
||||
// Chances are they bake all old versions of Windows into Windows, and
|
||||
// run us on the intended one, like some kind of Docker container. Heh
|
||||
strcpy(p, "10.0");
|
||||
}
|
||||
|
||||
static const char *Str(int rc, const char *s) {
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Deletes inode and maybe the file too.
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/stdio/sysparam.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
@@ -39,6 +40,7 @@
|
||||
*
|
||||
* @param fd is open file descriptor
|
||||
* @param buf is copied from, cf. copy_file_range(), sendfile(), etc.
|
||||
* @param size is always saturated to 0x7ffff000 automatically
|
||||
* @return [1..size] bytes on success, or -1 w/ errno; noting zero is
|
||||
* impossible unless size was passed as zero to do an error check
|
||||
* @raise EBADF if `fd` is negative or not an open file descriptor
|
||||
@@ -68,6 +70,10 @@ ssize_t write(int fd, const void *buf, size_t size) {
|
||||
ssize_t rc;
|
||||
BEGIN_CANCELATION_POINT;
|
||||
|
||||
// XNU and BSDs will EINVAL if requested bytes exceeds INT_MAX
|
||||
// this is inconsistent with Linux which ignores huge requests
|
||||
size = MIN(size, 0x7ffff000);
|
||||
|
||||
if (fd < 0) {
|
||||
rc = ebadf();
|
||||
} else if (IsAsan() && !__asan_is_valid(buf, size)) {
|
||||
|
||||
+69
-25
@@ -27,8 +27,71 @@
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/stdckdint.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/vga/vga.internal.h"
|
||||
|
||||
static size_t SumIovecBytes(const struct iovec *iov, int iovlen) {
|
||||
size_t count = 0;
|
||||
for (int i = 0; i < iovlen; ++i)
|
||||
if (ckd_add(&count, count, iov[i].iov_len))
|
||||
count = SIZE_MAX;
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t writev_impl(int fd, const struct iovec *iov, int iovlen) {
|
||||
if (fd < 0)
|
||||
return ebadf();
|
||||
if (iovlen < 0)
|
||||
return einval();
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen))
|
||||
return efault();
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip)
|
||||
return ebadf(); // posix specifies this when not open()'d for writing
|
||||
|
||||
// XNU and BSDs will EINVAL if requested bytes exceeds INT_MAX
|
||||
// this is inconsistent with Linux which ignores huge requests
|
||||
if (!IsLinux()) {
|
||||
size_t sum, remain = 0x7ffff000;
|
||||
if ((sum = SumIovecBytes(iov, iovlen)) > remain) {
|
||||
struct iovec *iov2;
|
||||
#pragma GCC push_options
|
||||
#pragma GCC diagnostic ignored "-Walloca-larger-than="
|
||||
iov2 = alloca(iovlen * sizeof(struct iovec));
|
||||
CheckLargeStackAllocation(iov2, iovlen * sizeof(struct iovec));
|
||||
#pragma GCC pop_options
|
||||
for (int i = 0; i < iovlen; ++i) {
|
||||
iov2[i] = iov[i];
|
||||
if (remain >= iov2[i].iov_len) {
|
||||
remain -= iov2[i].iov_len;
|
||||
} else {
|
||||
iov2[i].iov_len = remain;
|
||||
remain = 0;
|
||||
}
|
||||
}
|
||||
iov = iov2;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsLinux() || IsXnu() || IsFreebsd() || IsOpenbsd() || IsNetbsd()) {
|
||||
if (iovlen == 1) {
|
||||
return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
|
||||
} else {
|
||||
return sys_writev(fd, iov, iovlen);
|
||||
}
|
||||
} else if (fd >= g_fds.n) {
|
||||
return ebadf();
|
||||
} else if (IsMetal()) {
|
||||
return sys_writev_metal(g_fds.p + fd, iov, iovlen);
|
||||
} else if (IsWindows()) {
|
||||
return sys_writev_nt(fd, iov, iovlen);
|
||||
} else {
|
||||
return enosys();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes data from multiple buffers.
|
||||
@@ -45,6 +108,11 @@
|
||||
* been committed. It can also happen if we need to polyfill this system
|
||||
* call using write().
|
||||
*
|
||||
* It's possible for file write request to be partially completed. For
|
||||
* example, if the sum of `iov` lengths exceeds 0x7ffff000 then bytes
|
||||
* beyond that will be ignored. This is a Linux behavior that Cosmo
|
||||
* polyfills across platforms.
|
||||
*
|
||||
* @return number of bytes actually handed off, or -1 w/ errno
|
||||
* @cancelationpoint
|
||||
* @restartable
|
||||
@@ -52,31 +120,7 @@
|
||||
ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
||||
ssize_t rc;
|
||||
BEGIN_CANCELATION_POINT;
|
||||
|
||||
if (fd < 0) {
|
||||
rc = ebadf();
|
||||
} else if (iovlen < 0) {
|
||||
rc = einval();
|
||||
} else if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
|
||||
rc = efault();
|
||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = ebadf(); // posix specifies this when not open()'d for writing
|
||||
} else if (IsLinux() || IsXnu() || IsFreebsd() || IsOpenbsd() || IsNetbsd()) {
|
||||
if (iovlen == 1) {
|
||||
rc = sys_write(fd, iov[0].iov_base, iov[0].iov_len);
|
||||
} else {
|
||||
rc = sys_writev(fd, iov, iovlen);
|
||||
}
|
||||
} else if (fd >= g_fds.n) {
|
||||
rc = ebadf();
|
||||
} else if (IsMetal()) {
|
||||
rc = sys_writev_metal(g_fds.p + fd, iov, iovlen);
|
||||
} else if (IsWindows()) {
|
||||
rc = sys_writev_nt(fd, iov, iovlen);
|
||||
} else {
|
||||
rc = enosys();
|
||||
}
|
||||
|
||||
rc = writev_impl(fd, iov, iovlen);
|
||||
END_CANCELATION_POINT;
|
||||
STRACE("writev(%d, %s, %d) → %'ld% m", fd,
|
||||
DescribeIovec(rc != -1 ? rc : -2, iov, iovlen), iovlen, rc);
|
||||
|
||||
+5
-5
@@ -2,12 +2,12 @@
|
||||
#define COSMOPOLITAN_LIBC_COSMO_H_
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
errno_t cosmo_once(_Atomic(uint32_t) *, void (*)(void));
|
||||
errno_t cosmo_once(_Atomic(unsigned) *, void (*)(void)) libcesque;
|
||||
int systemvpe(const char *, char *const[], char *const[]) libcesque;
|
||||
char *GetProgramExecutableName(void);
|
||||
void unleaf(void);
|
||||
int __demangle(char *, const char *, size_t);
|
||||
int __is_mangled(const char *);
|
||||
char *GetProgramExecutableName(void) libcesque;
|
||||
void unleaf(void) libcesque;
|
||||
int __demangle(char *, const char *, size_t) libcesque;
|
||||
int __is_mangled(const char *) libcesque;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* COSMOPOLITAN_LIBC_COSMO_H_ */
|
||||
@@ -54,6 +54,8 @@ $(LIBC_DLOPEN_A_OBJS): private \
|
||||
o/$(MODE)/libc/dlopen/foreign_tramp.o: libc/dlopen/foreign_tramp.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
|
||||
$(LIBC_DLOPEN_A_OBJS): private COPTS += -fno-sanitize=address
|
||||
|
||||
LIBC_DLOPEN_LIBS = $(foreach x,$(LIBC_DLOPEN_ARTIFACTS),$($(x)))
|
||||
LIBC_DLOPEN_SRCS = $(foreach x,$(LIBC_DLOPEN_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_DLOPEN_HDRS = $(foreach x,$(LIBC_DLOPEN_ARTIFACTS),$($(x)_HDRS))
|
||||
|
||||
+19
-10
@@ -5,9 +5,9 @@
|
||||
#include "libc/elf/struct/phdr.h"
|
||||
#include "libc/elf/struct/shdr.h"
|
||||
#include "libc/elf/struct/sym.h"
|
||||
#include "libc/serialize.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/serialize.h"
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define GetStr(tab, rva) ((char *)(tab) + (rva))
|
||||
@@ -30,7 +30,8 @@ static inline char *GetStrtab(const Elf64_Ehdr *e, size_t *n) {
|
||||
if (shdr->sh_type == SHT_STRTAB) {
|
||||
name = GetSectionName(e, GetShdr(e, i));
|
||||
if (name && READ64LE(name) == READ64LE(".strtab")) {
|
||||
if (n) *n = shdr->sh_size;
|
||||
if (n)
|
||||
*n = shdr->sh_size;
|
||||
return GetSection(e, shdr);
|
||||
}
|
||||
}
|
||||
@@ -44,7 +45,8 @@ static inline Elf64_Sym *GetSymtab(const Elf64_Ehdr *e, Elf64_Xword *n) {
|
||||
for (i = e->e_shnum; i-- > 0;) {
|
||||
shdr = GetShdr(e, i);
|
||||
if (shdr->sh_type == SHT_SYMTAB) {
|
||||
if (n) *n = shdr->sh_size / sizeof(Elf64_Sym);
|
||||
if (n)
|
||||
*n = shdr->sh_size / sizeof(Elf64_Sym);
|
||||
return GetSection(e, shdr);
|
||||
}
|
||||
}
|
||||
@@ -60,14 +62,19 @@ static inline void GetImageRange(const Elf64_Ehdr *elf, intptr_t *x,
|
||||
end = 0;
|
||||
for (i = 0; i < elf->e_phnum; ++i) {
|
||||
phdr = GetPhdr(elf, i);
|
||||
if (phdr->p_type != PT_LOAD) continue;
|
||||
if (phdr->p_type != PT_LOAD)
|
||||
continue;
|
||||
pstart = phdr->p_vaddr;
|
||||
pend = phdr->p_vaddr + phdr->p_memsz;
|
||||
if (pstart < start) start = pstart;
|
||||
if (pend > end) end = pend;
|
||||
if (pstart < start)
|
||||
start = pstart;
|
||||
if (pend > end)
|
||||
end = pend;
|
||||
}
|
||||
if (x) *x = start;
|
||||
if (y) *y = end;
|
||||
if (x)
|
||||
*x = start;
|
||||
if (y)
|
||||
*y = end;
|
||||
}
|
||||
|
||||
static inline bool GetElfSymbolValue(const Elf64_Ehdr *ehdr, const char *name,
|
||||
@@ -75,8 +82,10 @@ static inline bool GetElfSymbolValue(const Elf64_Ehdr *ehdr, const char *name,
|
||||
Elf64_Xword i, n;
|
||||
const char *stab;
|
||||
const Elf64_Sym *st;
|
||||
if (!(stab = GetStrtab(ehdr, 0))) return false;
|
||||
if (!(st = GetSymtab(ehdr, &n))) return false;
|
||||
if (!(stab = GetStrtab(ehdr, 0)))
|
||||
return false;
|
||||
if (!(st = GetSymtab(ehdr, &n)))
|
||||
return false;
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (!__strcmp(GetStr(stab, st[i].st_name), name)) {
|
||||
*res = st[i].st_value;
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ COSMOPOLITAN_C_START_
|
||||
#define errno \
|
||||
(*__extension__({ \
|
||||
errno_t *__ep; \
|
||||
__asm__("sub\t%0,x28,#192-0x3c" : "=r"(__ep)); \
|
||||
__asm__("sub\t%0,x28,#512-0x3c" : "=r"(__ep)); \
|
||||
__ep; \
|
||||
}))
|
||||
#else
|
||||
|
||||
+2
-1
@@ -55,7 +55,8 @@ $(LIBC_FMT_A).pkg: \
|
||||
|
||||
$(LIBC_FMT_A_OBJS): private \
|
||||
CFLAGS += \
|
||||
-fno-jump-tables
|
||||
-fno-jump-tables \
|
||||
-fno-sanitize=address
|
||||
|
||||
o/$(MODE)/libc/fmt/formatint64.o \
|
||||
o/$(MODE)/libc/fmt/formatint64thousands.o \
|
||||
|
||||
+9
-6
@@ -3,13 +3,16 @@
|
||||
#include "libc/errno.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#define CONSUME_SPACES(t, s, c) \
|
||||
if (endptr) *endptr = (t *)(s); \
|
||||
while (c == ' ' || c == '\t') c = *++s
|
||||
#define CONSUME_SPACES(t, s, c) \
|
||||
if (endptr) \
|
||||
*endptr = (t *)(s); \
|
||||
while (c == ' ' || c == '\t') \
|
||||
c = *++s
|
||||
|
||||
#define GET_SIGN(s, c, d) \
|
||||
d = c == '-' ? -1 : 1; \
|
||||
if (c == '-' || c == '+') c = *++s
|
||||
#define GET_SIGN(s, c, d) \
|
||||
d = c == '-' ? -1 : 1; \
|
||||
if (c == '-' || c == '+') \
|
||||
c = *++s
|
||||
|
||||
#define GET_RADIX(s, c, r) \
|
||||
if (!r) { \
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ char *sleb64(char *p, int64_t x) {
|
||||
*p++ = c;
|
||||
return p;
|
||||
} else {
|
||||
*p++ = c | 64;
|
||||
*p++ = c | 128;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
-11
@@ -66,14 +66,15 @@
|
||||
#endif
|
||||
|
||||
#if (!defined(__llvm__) && !__has_builtin(__builtin_assume))
|
||||
#define __builtin_assume(x) \
|
||||
do { \
|
||||
if (!(x)) __builtin_unreachable(); \
|
||||
#define __builtin_assume(x) \
|
||||
do { \
|
||||
if (!(x)) \
|
||||
__builtin_unreachable(); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if __STDC_VERSION__ + 0 < 201112
|
||||
#define _Atomic(TYPE) TYPE volatile
|
||||
#define _Atomic(t) volatile t *
|
||||
#endif
|
||||
|
||||
#ifdef __llvm__
|
||||
@@ -106,8 +107,6 @@ typedef __CHAR32_TYPE__ char32_t;
|
||||
#include "libc/stdbool.h"
|
||||
#endif
|
||||
|
||||
#define _LIBCPP_STDINT_H
|
||||
|
||||
typedef int errno_t;
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef __PTRDIFF_TYPE__ ssize_t;
|
||||
@@ -540,16 +539,13 @@ typedef struct {
|
||||
#ifdef __x86_64__
|
||||
#define notpossible \
|
||||
do { \
|
||||
__asm__("nop\n\t" \
|
||||
"ud2\n\t" \
|
||||
"nop"); \
|
||||
__asm__("ud2"); \
|
||||
__builtin_unreachable(); \
|
||||
} while (0)
|
||||
#elif defined(__aarch64__)
|
||||
#define notpossible \
|
||||
do { \
|
||||
__asm__("udf\t#0\n\t" \
|
||||
"nop"); \
|
||||
__asm__("udf\t#0"); \
|
||||
__builtin_unreachable(); \
|
||||
} while (0)
|
||||
#else
|
||||
@@ -598,10 +594,21 @@ typedef struct {
|
||||
|
||||
#ifdef __x86_64__
|
||||
#define DebugBreak() __asm__("int3")
|
||||
#elif defined(__aarch64__)
|
||||
#define DebugBreak() __asm__("brk\t#0x666")
|
||||
#else
|
||||
#define DebugBreak() __builtin_trap()
|
||||
#endif
|
||||
|
||||
#ifdef __aarch64__
|
||||
/* raise sigill (not sigtrap) like x86 does */
|
||||
#define __builtin_trap() \
|
||||
do { \
|
||||
__asm__("udf\t#0x666"); \
|
||||
__builtin_unreachable(); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif /* _COSMO_SOURCE */
|
||||
|
||||
#define __veil(CONSTRAINT, EXPRESSION) \
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#endif
|
||||
|
||||
#define __COSMOPOLITAN_MAJOR__ 3
|
||||
#define __COSMOPOLITAN_MINOR__ 3
|
||||
#define __COSMOPOLITAN_PATCH__ 5
|
||||
#define __COSMOPOLITAN_MINOR__ 4
|
||||
#define __COSMOPOLITAN_PATCH__ 0
|
||||
#define __COSMOPOLITAN__ \
|
||||
(100000000 * __COSMOPOLITAN_MAJOR__ + 1000000 * __COSMOPOLITAN_MINOR__ + \
|
||||
__COSMOPOLITAN_PATCH__)
|
||||
|
||||
@@ -82,7 +82,9 @@ o//libc/intrin/memcmp.o \
|
||||
o//libc/intrin/memset.o \
|
||||
o//libc/intrin/memmove.o: private \
|
||||
CFLAGS += \
|
||||
-O2 -finline -foptimize-sibling-calls
|
||||
-O2 \
|
||||
-finline \
|
||||
-foptimize-sibling-calls
|
||||
|
||||
o/$(MODE)/libc/intrin/bzero.o \
|
||||
o/$(MODE)/libc/intrin/memcmp.o \
|
||||
|
||||
Loaded 100 of 2529 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user