diff --git a/Makefile b/Makefile index a6ad437b7..9417f639e 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,7 @@ # # TROUBLESHOOTING # -# make -j8 -O SILENT=0 o//examples/hello.com +# make -j8 -O V=1 o//examples/hello.com # make o//examples/life.elf -pn |& less # etc. # diff --git a/README.md b/README.md index 8ea2863a3..5ab71d759 100644 --- a/README.md +++ b/README.md @@ -18,21 +18,20 @@ libc](https://justine.lol/cosmopolitan/index.html) website. We also have ## Getting Started -Here's how to get started with the freestanding hermetically-sealed -monolithic source repository: +Cosmopolitan can be compiled from source on any Linux distro. ```sh -tar xf cosmopolitan-0.1.2.tar.gz # see our releases page -cd cosmo -make -j12 +tar xf cosmopolitan-0.1.2.tar.gz # see releases page +cd cosmopolitan-0.1.2 +make -j16 o//examples/hello.com +find o -name \*.com | xargs ls -rShal | less ``` -Here's how to get started with the amalgamated binaries, which let you -bring your own build system: +Alternatively you can use the release binaries: ```sh -unzip cosmopolitan-amalgamated-0.1.2.zip # see our releases page +unzip cosmopolitan-amalgamated-0.1.2.zip # see releases page echo 'main() { printf("hello world\n"); }' >hello.c gcc -g -O -static -fno-pie -no-pie -mno-red-zone -nostdlib -nostdinc \ -o hello.com.dbg hello.c -Wl,--gc-sections -Wl,-z,max-page-size=0x1000 -fuse-ld=bfd \ diff --git a/build/archive b/build/archive index f7fed1751..b378daadd 100755 --- a/build/archive +++ b/build/archive @@ -28,15 +28,15 @@ set -- o/build/bootstrap/ar.com "$@" OUT=$3 printf "$LOGFMT" "${ACTION:-ARCHIVE.a}" "$OUT" >&2 -# if [ "$SILENT" = "0" ]; then +# if [ "$V" = "0" ]; then +# printf "$LOGFMT" "${ACTION:-ARCHIVE.a}" "$OUT" >&2 +# else # # some of these windows nt archives are quite huge # COLUMNS=${COLUMNS:-80} # COLUMNS=$((COLUMNS - 4)) # printf "%s\n" "$*" | # /usr/bin/fold -s -w $COLUMNS | # sed -e '1bb' -e 's/^/ /' -e ':b' -e '$b' -e 's/$/ \\/' >&2 -# else -# printf "$LOGFMT" "${ACTION:-ARCHIVE.a}" "$OUT" >&2 # fi REASON=failed diff --git a/build/assemble b/build/assemble index 802147ef4..39678be39 100755 --- a/build/assemble +++ b/build/assemble @@ -23,13 +23,12 @@ if [ ! -d o/third_party/gcc ]; then third_party/gcc/unbundle.sh fi -export LC_ALL=C MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit -if [ "$SILENT" = "0" ]; then - printf "%s\n" "$*" >&2 -else +if [ "$V" = "0" ]; then printf "$LOGFMT" "${ACTION:-OBJECTIFY.s}" "$TARGET" >&2 +else + printf "%s\n" "$*" >&2 fi if [ "$TARGET" ]; then diff --git a/build/bootstrap/compile.com b/build/bootstrap/compile.com new file mode 100755 index 000000000..3121db014 Binary files /dev/null and b/build/bootstrap/compile.com differ diff --git a/build/compile b/build/compile index 96b311e32..660cfb499 100755 --- a/build/compile +++ b/build/compile @@ -33,7 +33,6 @@ if [ "$1" = "clang++-10" ]; then fi fi -export LC_ALL=C MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit GZME= @@ -270,10 +269,10 @@ fi set -- "$@" -no-canonical-prefixes $FDIAGNOSTIC_COLOR $ASAN $UBSAN $COUNTERMAND -if [ "$SILENT" = "0" ]; then - printf "%s\n" "$*" >&2 -else +if [ "$V" = "0" ]; then printf "$LOGFMT" "${ACTION:-COMPILE}" "${TARGET:-$OUT}" >&2 +else + printf "%s\n" "$*" >&2 fi OUTDIR="${OUT%/*}" diff --git a/build/definitions.mk b/build/definitions.mk index c135e0bdc..528cd6f24 100644 --- a/build/definitions.mk +++ b/build/definitions.mk @@ -13,8 +13,8 @@ # # When tuning the variables below, please note they're interpreted in # the strictest sense. For example, we don't pass CFLAGS to gcc if we -# know it's compiling a .S file. This allows our `make SILENT=0` logs -# to be succinct and informative, at the cost of being less forgiving. +# know it's compiling a .S file. This enables our `make V=0` logging +# to be succinct and informative at the cost of being less forgiving. # # Further note that link order is equally unforgiving in repositories # of this scale. We approach that by over-specifying dependencies, in @@ -42,6 +42,10 @@ # ASFLAGS assembler flags (don't use -Wa, frontend prefix) # TARGET_ARCH microarchitecture flags (e.g. -march=native) +V ?= 1 +LC_ALL = C.UTF-8 +SOURCE_DATE_EPOCH = 0 + DD ?= /bin/dd CP ?= /bin/cp -f RM ?= /bin/rm -f @@ -49,7 +53,6 @@ SED ?= /bin/sed MKDIR ?= /bin/mkdir -p TAGS ?= /usr/bin/ctags # emacs source builds or something breaks it ARFLAGS = rcsD -SILENT ?= 0 ZFLAGS ?= XARGS ?= xargs -P4 -rs8000 NICE ?= build/actuallynice @@ -77,36 +80,51 @@ PWD := $(shell pwd) IMAGE_BASE_VIRTUAL ?= 0x400000 TMPDIR := $(shell build/findtmp) LOGFMT := $(shell build/getlogfmt) +COMPILE := $(shell build/getcompile) CCNAME := $(shell build/getccname $(CC)) CCVERSION := $(shell build/getccversion $(CC)) BLAH1 := $(shell build/zipobj 2>/dev/null) BLAH2 := $(shell build/package 2>/dev/null) export ADDR2LINE -export OBJDUMP export CCNAME export CCVERSION export CP export DD export GZ export IMAGE_BASE_VIRTUAL +export LC_ALL export LOGFMT export MKDIR export MODE +export OBJDUMP export RM export SED -export SILENT +export SOURCE_DATE_EPOCH export TMPDIR +export V export ZFLAGS +unexport COMPILER_PATH +unexport CPATH +unexport CPLUS_INCLUDE_PATH +unexport C_INCLUDE_PATH +unexport DEPENDENCIES_OUTPUT +unexport GCC_COMPARE_DEBUG +unexport GCC_EXEC_PREFIX +unexport LANG +unexport LC_CTYPE +unexport LC_MESSAGES +unexport LIBRARY_PATH +unexport OBJC_INCLUDE_PATH +unexport SUNPRO_DEPENDENCIES + FTRACE = \ -pg SANITIZER = \ -fsanitize=leak \ - -fsanitize=address \ - -fsanitize=implicit-signed-integer-truncation \ - -fsanitize=implicit-integer-sign-change + -fsanitize=address NO_MAGIC = \ -mno-fentry \ @@ -154,8 +172,7 @@ MATHEMATICAL = \ DEFAULT_CPPFLAGS = \ -DIMAGE_BASE_VIRTUAL=$(IMAGE_BASE_VIRTUAL) \ -nostdinc \ - -iquote - \ - -iquote . + -iquote. DEFAULT_CFLAGS = \ -std=gnu2x diff --git a/build/do b/build/do index e6b39f29f..932a17f03 100755 --- a/build/do +++ b/build/do @@ -46,10 +46,10 @@ if [ "$OUT" ]; then fi # Log command. -if [ "$SILENT" = "0" ]; then - printf "%s\n" "$*" >&2 -else +if [ "$V" = "0" ]; then printf "$LOGFMT" "${ACTION:-BUILD}" "$TARGET" >&2 +else + printf "%s\n" "$*" >&2 fi exec "$@" diff --git a/build/findtmp b/build/findtmp index 602183263..b49c312bf 100755 --- a/build/findtmp +++ b/build/findtmp @@ -13,7 +13,5 @@ # environment variable. Many programs use it under the hood, e.g. gcc, # so it grants many small performance improvements. -MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit - -$MKDIR o/tmp +mkdir -p o/tmp echo o/tmp diff --git a/build/getcompile b/build/getcompile new file mode 100755 index 000000000..3d330924a --- /dev/null +++ b/build/getcompile @@ -0,0 +1,12 @@ +#!/bin/sh +#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐ +#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘ + +if ! [ o/build/bootstrap/compile.com -nt build/bootstrap/compile.com ]; then + mkdir -p o/build/bootstrap/ + cp -f build/bootstrap/compile.com o/build/bootstrap/compile.$$.com + o/build/bootstrap/compile.$$.com --do-nothing + mv -f o/build/bootstrap/compile.$$.com o/build/bootstrap/compile.com +fi + +echo o/build/bootstrap/compile.com diff --git a/build/getlogfmt b/build/getlogfmt index 87a828adb..10003eb65 100755 --- a/build/getlogfmt +++ b/build/getlogfmt @@ -11,23 +11,19 @@ # This program is invoked once by build/definitions.mk to choose the # most appropriate format string when logging command invocations. -if [ "$SILENT" = "0" ]; then - printf "''" -else - W1=15 - if [ "$TERM" = "dumb" ]; then # e.g. emacs' dismal tty - if [ "$COLUMNS" = "" ]; then - if TPUT=$(command -v tput); then - COLUMNS=$("$TPUT" cols) - else - COLUMNS=80 - fi +W1=15 +if [ "$TERM" = "dumb" ]; then + if [ "$COLUMNS" = "" ]; then + if TPUT=$(command -v tput); then + COLUMNS=$("$TPUT" cols) + else + COLUMNS=80 fi - COLUMNS=$((COLUMNS - 1)) - W2=$((COLUMNS - W1)) - printf '%%-%ds%%-%ds\\r' "$W1" "$W2" - else - echo ♥cosmo >&2 - printf '\\033[F\\033[K%%-%ds%%s\\r\\n' "$W1" fi + COLUMNS=$((COLUMNS - 1)) + W2=$((COLUMNS - W1)) + printf '%%-%ds%%-%ds\\r' "$W1" "$W2" +else + echo ♥cosmo >&2 + printf '\\033[F\\033[K%%-%ds%%s\\r\\n' "$W1" fi diff --git a/build/link b/build/link index 7439197ca..6f0fc503d 100755 --- a/build/link +++ b/build/link @@ -19,7 +19,6 @@ if [ ! -d o/third_party/gcc ]; then third_party/gcc/unbundle.sh fi -export LC_ALL=C # very important for ld MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit OUT= @@ -41,10 +40,10 @@ for x; do set -- "$@" "$x" done -if [ "$SILENT" = "0" ]; then - printf "%s\n" "$*" >&2 -else +if [ "$V" = "0" ]; then printf "$LOGFMT" "${ACTION:-LINK.elf}" "$OUT" >&2 +else + printf "%s\n" "$*" >&2 fi OUTDIR="${OUT%/*}" diff --git a/build/mkdeps b/build/mkdeps index b6919ca4b..a4cbc0da2 100755 --- a/build/mkdeps +++ b/build/mkdeps @@ -13,10 +13,10 @@ else set -- o/build/bootstrap/mkdeps.com "$@" fi -if [ "$SILENT" = "0" ]; then - printf "%s\n" "$*" >&2 -else +if [ "$V" = "0" ]; then printf "$LOGFMT" "${ACTION:-MKDEPS}" "$3" >&2 +else + printf "%s\n" "$*" >&2 fi exec "$@" diff --git a/build/package b/build/package index 6dbcf31e2..63ca44aaa 100755 --- a/build/package +++ b/build/package @@ -20,14 +20,14 @@ else fi printf "$LOGFMT" "${ACTION:-PACKAGE}" "$3" >&2 -# if [ "$SILENT" = "0" ]; then +# if [ "$V" = "0" ]; then +# printf "$LOGFMT" "${ACTION:-PACKAGE}" "$3" >&2 +# else # COLUMNS=${COLUMNS:-80} # COLUMNS=$((COLUMNS - 4)) # printf "%s\n" "$*" | # /usr/bin/fold -s -w $COLUMNS | # sed -e '1bb' -e 's/^/ /' -e ':b' -e '$b' -e 's/$/ \\/' >&2 -# else -# printf "$LOGFMT" "${ACTION:-PACKAGE}" "$3" >&2 # fi exec "$@" diff --git a/build/rules.mk b/build/rules.mk index 991e95721..0edb2153e 100644 --- a/build/rules.mk +++ b/build/rules.mk @@ -17,72 +17,72 @@ MAKEFLAGS += --no-builtin-rules o/%.a:; @$(ARCHIVE) $@ $^ -o/%.o: %.s; @TARGET=$@ build/assemble $(OBJECTIFY.s) $(OUTPUT_OPTION) $< -o/%.o: o/%.s; @TARGET=$@ build/assemble $(OBJECTIFY.s) $(OUTPUT_OPTION) $< -o/%.s: %.S; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) $< -o/%.s: o/%.S; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) $< -o/%.i: %.S; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) $< -o/%.o: %.S; @ACTION=OBJECTIFY.S build/compile $(OBJECTIFY.S) $(OUTPUT_OPTION) $< -o/%.o: o/%.S; @ACTION=OBJECTIFY.S build/compile $(OBJECTIFY.S) $(OUTPUT_OPTION) $< -o/%.s: %.i; @ACTION=COMPILE.i build/compile $(COMPILE.i) $(OUTPUT_OPTION) $< -o/%.s: o/%.i; @ACTION=COMPILE.i build/compile $(COMPILE.i) $(OUTPUT_OPTION) $< -o/%.o: %.cc; @ACTION=OBJECTIFY.cxx build/compile $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $< -o/%.o: o/%.cc; @ACTION=OBJECTIFY.cxx build/compile $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $< -o/%.lds: %.lds; @ACTION=PREPROCESS build/compile $(PREPROCESS.lds) $(OUTPUT_OPTION) $< -o/%.inc: %.h; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) -D__ASSEMBLER__ -P $< +o/%.o: %.s; @TARGET=$@ $(COMPILE) $(OBJECTIFY.s) $(OUTPUT_OPTION) $< +o/%.o: o/%.s; @TARGET=$@ $(COMPILE) $(OBJECTIFY.s) $(OUTPUT_OPTION) $< +o/%.s: %.S; @ACTION=PREPROCESS $(COMPILE) $(PREPROCESS) $(OUTPUT_OPTION) $< +o/%.s: o/%.S; @ACTION=PREPROCESS $(COMPILE) $(PREPROCESS) $(OUTPUT_OPTION) $< +o/%.i: %.S; @ACTION=PREPROCESS $(COMPILE) $(PREPROCESS) $(OUTPUT_OPTION) $< +o/%.o: %.S; @ACTION=OBJECTIFY.S $(COMPILE) $(OBJECTIFY.S) $(OUTPUT_OPTION) $< +o/%.o: o/%.S; @ACTION=OBJECTIFY.S $(COMPILE) $(OBJECTIFY.S) $(OUTPUT_OPTION) $< +o/%.s: %.i; @ACTION=COMPILE.i $(COMPILE) $(COMPILE.i) $(OUTPUT_OPTION) $< +o/%.s: o/%.i; @ACTION=COMPILE.i $(COMPILE) $(COMPILE.i) $(OUTPUT_OPTION) $< +o/%.o: %.cc; @ACTION=OBJECTIFY.cxx $(COMPILE) $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $< +o/%.o: o/%.cc; @ACTION=OBJECTIFY.cxx $(COMPILE) $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $< +o/%.lds: %.lds; @ACTION=PREPROCESS $(COMPILE) $(PREPROCESS.lds) $(OUTPUT_OPTION) $< +o/%.inc: %.h; @ACTION=PREPROCESS $(COMPILE) $(PREPROCESS) $(OUTPUT_OPTION) -D__ASSEMBLER__ -P $< o/%.pkg:; @build/package $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) $(filter %.o,$^) -o/%.h.ok: %.h; @ACTION=CHECK.h build/compile $(COMPILE.c) -x c -g0 -o $@ $< -o/%.h.okk: %.h; @ACTION=CHECK.h build/compile $(COMPILE.cxx) -x c++ -g0 -o $@ $< -o/%.greg.o: %.greg.c; @ACTION=OBJECTIFY.greg build/compile $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $< +o/%.h.ok: %.h; @ACTION=CHECK.h $(COMPILE) $(COMPILE.c) -x c -g0 -o $@ $< +o/%.h.okk: %.h; @ACTION=CHECK.h $(COMPILE) $(COMPILE.cxx) -x c++ -g0 -o $@ $< +o/%.greg.o: %.greg.c; @ACTION=OBJECTIFY.greg $(COMPILE) $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $< o/%.zip.o: o/%; @build/zipobj $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $< o/$(MODE)/%.a:; @$(ARCHIVE) $@ $^ -o/$(MODE)/%: o/$(MODE)/%.dbg; @ACTION=OBJCOPY TARGET=$@ build/do $(OBJCOPY) -SO binary $< $@ -o/$(MODE)/%.o: %.s; @TARGET=$@ build/assemble $(OBJECTIFY.s) $(OUTPUT_OPTION) $< -o/$(MODE)/%.o: o/$(MODE)/%.s; @TARGET=$@ build/assemble $(OBJECTIFY.s) $(OUTPUT_OPTION) $< -o/$(MODE)/%.s: %.S; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) $< -o/$(MODE)/%.s: o/$(MODE)/%.S; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) $< -o/$(MODE)/%.o: %.c; @ACTION=OBJECTIFY.c build/compile $(OBJECTIFY.c) $(OUTPUT_OPTION) $< -o/$(MODE)/%.o: %.f; @ACTION=OBJECTIFY.f build/compile $(OBJECTIFY.f) $(OUTPUT_OPTION) $< -o/$(MODE)/%.o: %.F; @ACTION=OBJECTIFY.F build/compile $(OBJECTIFY.F) $(OUTPUT_OPTION) $< -o/$(MODE)/%.o: o/$(MODE)/%.c; @ACTION=OBJECTIFY.c build/compile $(OBJECTIFY.c) $(OUTPUT_OPTION) $< -o/$(MODE)/%.ss: %.c; @ACTION=COMPILE.c build/compile $(COMPILE.c) $(OUTPUT_OPTION) $< -o/$(MODE)/%.ss: o/$(MODE)/%.c; @ACTION=OBJECTIFY.s build/compile $(COMPILE.c) $(OUTPUT_OPTION) $< -o/$(MODE)/%.i: %.S; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) $< -o/$(MODE)/%.i: %.c; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) $< -o/$(MODE)/%.i: %.cc; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) $< -o/$(MODE)/%.i: o/$(MODE)/%.c; @ACTION=PREPROCESS build/compile $(PREPROCESS) $(OUTPUT_OPTION) $< -o/$(MODE)/%.h: %.c; @ACTION=AMALGAMATE build/compile $(PREPROCESS) $(OUTPUT_OPTION) -fdirectives-only -P $< -o/$(MODE)/%.h: o/$(MODE)/%.c; @ACTION=AMALGAMATE build/compile $(PREPROCESS) $(OUTPUT_OPTION) -fdirectives-only -P $< -o/$(MODE)/%.o: %.S; @ACTION=OBJECTIFY.S build/compile $(OBJECTIFY.S) $(OUTPUT_OPTION) $< -o/$(MODE)/%.o: o/$(MODE)/%.S; @ACTION=OBJECTIFY.S build/compile $(OBJECTIFY.S) $(OUTPUT_OPTION) $< -o/$(MODE)/%.s: %.i; @ACTION=COMPILE.i build/compile $(COMPILE.i) $(OUTPUT_OPTION) $< -o/$(MODE)/%.s: o/$(MODE)/%.i; @ACTION=COMPILE.i build/compile $(COMPILE.i) $(OUTPUT_OPTION) $< -o/$(MODE)/%.o: %.cc; @ACTION=OBJECTIFY.cxx build/compile $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $< -o/$(MODE)/%.o: o/$(MODE)/%.cc; @ACTION=OBJECTIFY.cxx build/compile $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $< -o/$(MODE)/%.lds: %.lds; @ACTION=PREPROCESS build/compile $(PREPROCESS.lds) $(OUTPUT_OPTION) $< -o/$(MODE)/%.h.ok: %.h; @ACTION=CHECK.h build/compile $(COMPILE.c) -x c -g0 -o $@ $< -o/$(MODE)/%.h.okk: %.h; @ACTION=CHECK.h build/compile $(COMPILE.cxx) -x c++ -g0 -o $@ $< -o/$(MODE)/%.o: %.greg.c; @ACTION=OBJECTIFY.greg build/compile $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $< -o/$(MODE)/%.greg.o: %.greg.c; @ACTION=OBJECTIFY.greg build/compile $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $< -o/$(MODE)/%.ansi.o: %.ansi.c; @ACTION=OBJECTIFY.ansi build/compile $(OBJECTIFY.ansi.c) $(OUTPUT_OPTION) $< -o/$(MODE)/%.ansi.o: %.c; @ACTION=OBJECTIFY.ansi build/compile $(OBJECTIFY.ansi.c) $(OUTPUT_OPTION) $< -o/$(MODE)/%.c99.o: %.c99.c; @ACTION=OBJECTIFY.c99 build/compile $(OBJECTIFY.c99.c) $(OUTPUT_OPTION) $< -o/$(MODE)/%.c11.o: %.c11.c; @ACTION=OBJECTIFY.c11 build/compile $(OBJECTIFY.c11.c) $(OUTPUT_OPTION) $< -o/$(MODE)/%.c2x.o: %.c2x.c; @ACTION=OBJECTIFY.c2x build/compile $(OBJECTIFY.c2x.c) $(OUTPUT_OPTION) $< -o/$(MODE)/%.initabi.o: %.initabi.c; @ACTION=OBJECTIFY.init build/compile $(OBJECTIFY.initabi.c) $(OUTPUT_OPTION) $< -o/$(MODE)/%.ncabi.o: %.ncabi.c; @ACTION=OBJECTIFY.nc build/compile $(OBJECTIFY.ncabi.c) $(OUTPUT_OPTION) $< -o/$(MODE)/%.real.o: %.c; @ACTION=OBJECTIFY.real build/compile $(OBJECTIFY.real.c) $(OUTPUT_OPTION) $< +o/$(MODE)/%: o/$(MODE)/%.dbg; @ACTION=OBJCOPY TARGET=$@ $(COMPILE) $(OBJCOPY) -SO binary $< $@ +o/$(MODE)/%.o: %.s; @TARGET=$@ $(COMPILE) $(OBJECTIFY.s) $(OUTPUT_OPTION) $< +o/$(MODE)/%.o: o/$(MODE)/%.s; @TARGET=$@ $(COMPILE) $(OBJECTIFY.s) $(OUTPUT_OPTION) $< +o/$(MODE)/%.s: %.S; @ACTION=PREPROCESS $(COMPILE) $(PREPROCESS) $(OUTPUT_OPTION) $< +o/$(MODE)/%.s: o/$(MODE)/%.S; @ACTION=PREPROCESS $(COMPILE) $(PREPROCESS) $(OUTPUT_OPTION) $< +o/$(MODE)/%.o: %.c; @ACTION=OBJECTIFY.c $(COMPILE) $(OBJECTIFY.c) $(OUTPUT_OPTION) $< +o/$(MODE)/%.o: %.f; @ACTION=OBJECTIFY.f $(COMPILE) $(OBJECTIFY.f) $(OUTPUT_OPTION) $< +o/$(MODE)/%.o: %.F; @ACTION=OBJECTIFY.F $(COMPILE) $(OBJECTIFY.F) $(OUTPUT_OPTION) $< +o/$(MODE)/%.o: o/$(MODE)/%.c; @ACTION=OBJECTIFY.c $(COMPILE) $(OBJECTIFY.c) $(OUTPUT_OPTION) $< +o/$(MODE)/%.ss: %.c; @ACTION=COMPILE.c $(COMPILE) $(COMPILE.c) $(OUTPUT_OPTION) $< +o/$(MODE)/%.ss: o/$(MODE)/%.c; @ACTION=OBJECTIFY.s $(COMPILE) $(COMPILE.c) $(OUTPUT_OPTION) $< +o/$(MODE)/%.i: %.S; @ACTION=PREPROCESS $(COMPILE) $(PREPROCESS) $(OUTPUT_OPTION) $< +o/$(MODE)/%.i: %.c; @ACTION=PREPROCESS $(COMPILE) $(PREPROCESS) $(OUTPUT_OPTION) $< +o/$(MODE)/%.i: %.cc; @ACTION=PREPROCESS $(COMPILE) $(PREPROCESS) $(OUTPUT_OPTION) $< +o/$(MODE)/%.i: o/$(MODE)/%.c; @ACTION=PREPROCESS $(COMPILE) $(PREPROCESS) $(OUTPUT_OPTION) $< +o/$(MODE)/%.h: %.c; @ACTION=AMALGAMATE $(COMPILE) $(PREPROCESS) $(OUTPUT_OPTION) -fdirectives-only -P $< +o/$(MODE)/%.h: o/$(MODE)/%.c; @ACTION=AMALGAMATE $(COMPILE) $(PREPROCESS) $(OUTPUT_OPTION) -fdirectives-only -P $< +o/$(MODE)/%.o: %.S; @ACTION=OBJECTIFY.S $(COMPILE) $(OBJECTIFY.S) $(OUTPUT_OPTION) $< +o/$(MODE)/%.o: o/$(MODE)/%.S; @ACTION=OBJECTIFY.S $(COMPILE) $(OBJECTIFY.S) $(OUTPUT_OPTION) $< +o/$(MODE)/%.s: %.i; @ACTION=COMPILE.i $(COMPILE) $(COMPILE.i) $(OUTPUT_OPTION) $< +o/$(MODE)/%.s: o/$(MODE)/%.i; @ACTION=COMPILE.i $(COMPILE) $(COMPILE.i) $(OUTPUT_OPTION) $< +o/$(MODE)/%.o: %.cc; @ACTION=OBJECTIFY.cxx $(COMPILE) $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $< +o/$(MODE)/%.o: o/$(MODE)/%.cc; @ACTION=OBJECTIFY.cxx $(COMPILE) $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $< +o/$(MODE)/%.lds: %.lds; @ACTION=PREPROCESS $(COMPILE) $(PREPROCESS.lds) $(OUTPUT_OPTION) $< +o/$(MODE)/%.h.ok: %.h; @ACTION=CHECK.h $(COMPILE) $(COMPILE.c) -x c -g0 -o $@ $< +o/$(MODE)/%.h.okk: %.h; @ACTION=CHECK.h $(COMPILE) $(COMPILE.cxx) -x c++ -g0 -o $@ $< +o/$(MODE)/%.o: %.greg.c; @ACTION=OBJECTIFY.greg $(COMPILE) $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $< +o/$(MODE)/%.greg.o: %.greg.c; @ACTION=OBJECTIFY.greg $(COMPILE) $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $< +o/$(MODE)/%.ansi.o: %.ansi.c; @ACTION=OBJECTIFY.ansi $(COMPILE) $(OBJECTIFY.ansi.c) $(OUTPUT_OPTION) $< +o/$(MODE)/%.ansi.o: %.c; @ACTION=OBJECTIFY.ansi $(COMPILE) $(OBJECTIFY.ansi.c) $(OUTPUT_OPTION) $< +o/$(MODE)/%.c99.o: %.c99.c; @ACTION=OBJECTIFY.c99 $(COMPILE) $(OBJECTIFY.c99.c) $(OUTPUT_OPTION) $< +o/$(MODE)/%.c11.o: %.c11.c; @ACTION=OBJECTIFY.c11 $(COMPILE) $(OBJECTIFY.c11.c) $(OUTPUT_OPTION) $< +o/$(MODE)/%.c2x.o: %.c2x.c; @ACTION=OBJECTIFY.c2x $(COMPILE) $(OBJECTIFY.c2x.c) $(OUTPUT_OPTION) $< +o/$(MODE)/%.initabi.o: %.initabi.c; @ACTION=OBJECTIFY.init $(COMPILE) $(OBJECTIFY.initabi.c) $(OUTPUT_OPTION) $< +o/$(MODE)/%.ncabi.o: %.ncabi.c; @ACTION=OBJECTIFY.nc $(COMPILE) $(OBJECTIFY.ncabi.c) $(OUTPUT_OPTION) $< +o/$(MODE)/%.real.o: %.c; @ACTION=OBJECTIFY.real $(COMPILE) $(OBJECTIFY.real.c) $(OUTPUT_OPTION) $< o/$(MODE)/%.runs: o/$(MODE)/%; @ACTION=CHECK.runs TARGET=$< build/runcom $< $(TESTARGS) && touch $@ o/$(MODE)/%.pkg:; @build/package $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) $(filter %.o,$^) o/$(MODE)/%.zip.o: %; @build/zipobj $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $< -o/$(MODE)/%-gcc.asm: %.c; @ACTION=OBJECTIFY.c build/compile $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $< +o/$(MODE)/%-gcc.asm: %.c; @ACTION=OBJECTIFY.c $(COMPILE) $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $< o/$(MODE)/%-clang.asm: CC = $(CLANG) -o/$(MODE)/%-clang.asm: %.c; @ACTION=OBJECTIFY.c build/compile $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $< || echo / need $(CLANG) >$@ -o/$(MODE)/%-gcc.asm: %.f; @ACTION=OBJECTIFY.f build/compile $(OBJECTIFY.f) -S -g0 $(OUTPUT_OPTION) $< +o/$(MODE)/%-clang.asm: %.c; @ACTION=OBJECTIFY.c $(COMPILE) $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $< || echo / need $(CLANG) >$@ +o/$(MODE)/%-gcc.asm: %.f; @ACTION=OBJECTIFY.f $(COMPILE) $(OBJECTIFY.f) -S -g0 $(OUTPUT_OPTION) $< o/$(MODE)/%-clang.asm: CC = $(CLANG) -o/$(MODE)/%-clang.asm: %.f; @ACTION=OBJECTIFY.f build/compile $(OBJECTIFY.f) -S -g0 $(OUTPUT_OPTION) $< || echo / need $(CLANG) >$@ -o/$(MODE)/%-gcc.asm: %.F; @ACTION=OBJECTIFY.F build/compile $(OBJECTIFY.F) -S -g0 $(OUTPUT_OPTION) $< +o/$(MODE)/%-clang.asm: %.f; @ACTION=OBJECTIFY.f $(COMPILE) $(OBJECTIFY.f) -S -g0 $(OUTPUT_OPTION) $< || echo / need $(CLANG) >$@ +o/$(MODE)/%-gcc.asm: %.F; @ACTION=OBJECTIFY.F $(COMPILE) $(OBJECTIFY.F) -S -g0 $(OUTPUT_OPTION) $< o/$(MODE)/%-clang.asm: CC = $(CLANG) -o/$(MODE)/%-clang.asm: %.F; @ACTION=OBJECTIFY.F build/compile $(OBJECTIFY.F) -S -g0 $(OUTPUT_OPTION) $< || echo / need $(CLANG) >$@ +o/$(MODE)/%-clang.asm: %.F; @ACTION=OBJECTIFY.F $(COMPILE) $(OBJECTIFY.F) -S -g0 $(OUTPUT_OPTION) $< || echo / need $(CLANG) >$@ diff --git a/build/zipobj b/build/zipobj index dfa1a89aa..02a9097d9 100755 --- a/build/zipobj +++ b/build/zipobj @@ -42,10 +42,10 @@ else set -- o/build/bootstrap/zipobj.com "$@" fi -if [ "$SILENT" = "0" ]; then - printf "%s\n" "$*" >&2 -else +if [ "$V" = "0" ]; then printf "$LOGFMT" "${ACTION:-ZIPOBJ}" "$3" >&2 +else + printf "%s\n" "$*" >&2 fi exec "$@" diff --git a/libc/calls/calls.h b/libc/calls/calls.h index 0198a637b..100254d39 100644 --- a/libc/calls/calls.h +++ b/libc/calls/calls.h @@ -1,7 +1,14 @@ #ifndef COSMOPOLITAN_LIBC_CALLS_SYSCALLS_H_ #define COSMOPOLITAN_LIBC_CALLS_SYSCALLS_H_ +#include "libc/calls/struct/iovec.h" +#include "libc/calls/struct/rlimit.h" +#include "libc/calls/struct/rusage.h" #include "libc/calls/struct/sigaction.h" +#include "libc/calls/struct/stat.h" +#include "libc/calls/struct/sysinfo.h" #include "libc/calls/struct/timespec.h" +#include "libc/calls/struct/tms.h" +#include "libc/calls/struct/utsname.h" #include "libc/calls/typedef/sighandler_t.h" #include "libc/dce.h" #include "libc/fmt/pflink.h" @@ -54,17 +61,6 @@ COSMOPOLITAN_C_START_ │ cosmopolitan § system calls ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ -struct dirstream; -struct iovec; -struct rlimit; -struct rusage; -struct sigaction; -struct sigset; -struct stat; -struct sysinfo; -struct tms; -struct utsname; - typedef int sig_atomic_t; typedef struct dirstream DIR; @@ -196,12 +192,12 @@ int wait(int *); int wait3(int *, int, struct rusage *); int wait4(int, int *, int, struct rusage *); int waitpid(int, int *, int); -int64_t lseek(int, int64_t, int); -int64_t pread(int, void *, size_t, int64_t); -int64_t preadv(int, struct iovec *, int, int64_t); -int64_t pwrite(int, const void *, size_t, int64_t); -int64_t pwritev(int, const struct iovec *, int, int64_t); -int64_t syscall(); +ssize_t lseek(int, int64_t, unsigned); +ssize_t pread(int, void *, size_t, int64_t); +ssize_t preadv(int, struct iovec *, int, int64_t); +ssize_t pwrite(int, const void *, size_t, int64_t); +ssize_t pwritev(int, const struct iovec *, int, int64_t); +intptr_t syscall(int, ...); void sync(void); long telldir(DIR *); int getpid(void); diff --git a/libc/calls/calls.mk b/libc/calls/calls.mk index ae2afe0e1..38227c8b2 100644 --- a/libc/calls/calls.mk +++ b/libc/calls/calls.mk @@ -17,7 +17,6 @@ LIBC_CALLS = $(LIBC_CALLS_A_DEPS) $(LIBC_CALLS_A) LIBC_CALLS_A = o/$(MODE)/libc/calls/syscalls.a LIBC_CALLS_A_FILES := \ $(wildcard libc/calls/typedef/*) \ - $(wildcard libc/calls/thunks/*) \ $(wildcard libc/calls/struct/*) \ $(wildcard libc/calls/*) LIBC_CALLS_A_HDRS = $(filter %.h,$(LIBC_CALLS_A_FILES)) diff --git a/libc/calls/chmod.c b/libc/calls/chmod.c index 7dba99b96..3404c5f41 100644 --- a/libc/calls/chmod.c +++ b/libc/calls/chmod.c @@ -44,6 +44,5 @@ * @see fchmod() */ int chmod(const char *pathname, uint32_t mode) { - if (!pathname) return efault(); return sys_fchmodat(AT_FDCWD, pathname, mode, 0); } diff --git a/libc/calls/clock_gettime.c b/libc/calls/clock_gettime.c index 9d64dab2e..336fe2f13 100644 --- a/libc/calls/clock_gettime.c +++ b/libc/calls/clock_gettime.c @@ -16,22 +16,12 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/bits/bits.h" -#include "libc/bits/safemacros.h" -#include "libc/calls/calls.h" +#include "libc/assert.h" #include "libc/calls/internal.h" -#include "libc/calls/struct/timespec.h" #include "libc/calls/struct/timeval.h" -#include "libc/dce.h" #include "libc/fmt/conv.h" -#include "libc/mach.h" -#include "libc/nt/struct/filetime.h" -#include "libc/nt/struct/systemtime.h" #include "libc/nt/synchronization.h" -#include "libc/sysv/consts/clock.h" -#include "libc/sysv/consts/fileno.h" #include "libc/sysv/errfuns.h" -#include "libc/time/time.h" /** * Returns nanosecond time. @@ -43,40 +33,34 @@ * @param clockid can be CLOCK_REALTIME, CLOCK_MONOTONIC, etc. noting * that on Linux CLOCK_MONOTONIC is redefined to use the monotonic * clock that's actually monotonic lool - * @param out_ts is where the nanoseconds are stored if non-NULL - * @return 0 on success or -1 w/ errno on error + * @param ts is where the result is stored + * @return 0 on success, or -1 w/ errno * @error ENOSYS if clockid isn't available; in which case this function - * guarantees an ordinary timestamp is still stored to out_ts; and + * guarantees an ordinary timestamp is still stored to ts; and * errno isn't restored to its original value, to detect prec. loss * @see strftime(), gettimeofday() * @asyncsignalsafe */ -int clock_gettime(int clockid, struct timespec *out_ts) { - /* TODO(jart): Just ignore O/S for MONOTONIC and measure RDTSC on start */ +int clock_gettime(int clockid, struct timespec *ts) { + int rc; + axdx_t ad; + struct NtFileTime ft; + if (!ts) return efault(); if (!IsWindows()) { - if (!IsXnu()) { - if (out_ts) { - out_ts->tv_sec = 0; - out_ts->tv_nsec = 0; + if ((rc = sys_clock_gettime(clockid, ts)) == -1 && errno == ENOSYS) { + ad = sys_gettimeofday((struct timeval *)ts, NULL, NULL); + assert(ad.ax != -1); + if (SupportsXnu() && ad.ax) { + ts->tv_sec = ad.ax; + ts->tv_nsec = ad.dx; } - return sys_clock_gettime(clockid, out_ts); - } else { - int rc; - _Static_assert(sizeof(struct timeval) == sizeof(struct timespec)); - if (out_ts) { - out_ts->tv_sec = 0; - out_ts->tv_nsec = 0; - } - rc = sys_gettimeofday((struct timeval *)out_ts, NULL); - if (out_ts) { - out_ts->tv_nsec *= 1000; - } - return rc; + ts->tv_nsec *= 1000; + rc = 0; } + return rc; } else { - struct NtFileTime ft; GetSystemTimeAsFileTime(&ft); - *out_ts = FileTimeToTimeSpec(ft); + *ts = FileTimeToTimeSpec(ft); return 0; } } diff --git a/libc/calls/execve-sysv.c b/libc/calls/execve-sysv.c index c7357be64..2c77471a5 100644 --- a/libc/calls/execve-sysv.c +++ b/libc/calls/execve-sysv.c @@ -27,7 +27,7 @@ int sys_execve(const char *prog, char *const argv[], char *const envp[]) { size_t i; char **shargs; - if (__sys_execve(prog, argv, envp) != -1) return 0; + __sys_execve(prog, argv, envp); if (errno != ENOEXEC) return -1; for (i = 0; argv[i];) ++i; shargs = alloca((i + 2) * sizeof(char *)); diff --git a/libc/calls/faccessat.c b/libc/calls/faccessat.c index 651500676..d599f14d2 100644 --- a/libc/calls/faccessat.c +++ b/libc/calls/faccessat.c @@ -34,7 +34,6 @@ * @asyncsignalsafe */ int faccessat(int dirfd, const char *path, int mode, uint32_t flags) { - if (!path) return efault(); if (!IsWindows()) { return sys_faccessat(dirfd, path, mode, flags); } else { diff --git a/libc/calls/ftruncate.c b/libc/calls/ftruncate.c index 0fe03ff90..2a0b75473 100644 --- a/libc/calls/ftruncate.c +++ b/libc/calls/ftruncate.c @@ -33,7 +33,7 @@ */ int ftruncate(int fd, int64_t length) { if (!IsWindows()) { - return sys_ftruncate(fd, length); + return sys_ftruncate(fd, length, length); } else { return sys_ftruncate_nt(fd, length); } diff --git a/libc/calls/getcwd-nt.c b/libc/calls/getcwd-nt.c index 4c4a8550d..db109370e 100644 --- a/libc/calls/getcwd-nt.c +++ b/libc/calls/getcwd-nt.c @@ -23,7 +23,7 @@ #include "libc/sysv/errfuns.h" textwindows char *sys_getcwd_nt(char *buf, size_t size) { - uint16_t name16[PATH_MAX]; + char16_t name16[PATH_MAX]; if (GetCurrentDirectory(ARRAYLEN(name16), name16)) { tprecode16to8(buf, size, name16); return buf; diff --git a/libc/calls/getcwd-xnu.c b/libc/calls/getcwd-xnu.c index 7e404bc83..4da7837f0 100644 --- a/libc/calls/getcwd-xnu.c +++ b/libc/calls/getcwd-xnu.c @@ -24,9 +24,8 @@ #include "libc/sysv/consts/o.h" #include "libc/sysv/errfuns.h" -#define NETBSD_F_GETPATH 15 -#define XNU_F_GETPATH 50 -#define XNU_MAXPATHLEN 1024 +#define XNU_F_GETPATH 50 +#define XNU_MAXPATHLEN 1024 char *sys_getcwd_xnu(char *res, size_t size) { int fd; diff --git a/libc/calls/getenv.c b/libc/calls/getenv.c index cff58f1e9..a85c9f6b6 100644 --- a/libc/calls/getenv.c +++ b/libc/calls/getenv.c @@ -20,6 +20,8 @@ /** * Returns value of environment variable, or NULL if not found. + * + * Environment variables can store empty string on Unix but not Windows. */ char *getenv(const char *s) { char **p; @@ -29,7 +31,7 @@ char *getenv(const char *s) { for (j = 0;; ++j) { if (!s[j]) { if (p[i][j] == '=') { - return &p[i][j + 1]; + return p[i] + j + 1; } break; } diff --git a/libc/calls/thunks/fork-sysv.S b/libc/calls/gethostname-bsd.c similarity index 71% rename from libc/calls/thunks/fork-sysv.S rename to libc/calls/gethostname-bsd.c index 55f2cb11d..23d5317c8 100644 --- a/libc/calls/thunks/fork-sysv.S +++ b/libc/calls/gethostname-bsd.c @@ -1,5 +1,5 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2021 Justine Alexandra Roberts Tunney │ │ │ @@ -16,26 +16,27 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/dce.h" -#include "libc/macros.h" +#include "libc/calls/calls.h" +#include "libc/errno.h" +#include "libc/str/str.h" -/ Makes fork() kernel ABI consistent across UNIX systems. -/ -/ @return 0 if parent, pid if child, or -1 on error -sys_fork: - push %rbp - mov %rsp,%rbp - .profilable - call __sys_fork -#if SupportsXnu() - testb IsXnu() - jz 1f - cmp $-1,%rax - je 1f - neg %edx # edx is 0 for parent and 1 for child - not %edx # eax always returned with childs pid - and %edx,%eax -#endif -1: pop %rbp - ret - .endfn sys_fork,globl,hidden +#define CTL_KERN 1 +#define KERN_HOSTNAME 10 + +int gethostname_bsd(char *name, size_t len) { + char *p; + int cmd[2]; + char buf[254]; + size_t buflen; + cmd[0] = CTL_KERN; + cmd[1] = KERN_HOSTNAME; + buflen = sizeof(buf); + if (sysctl(cmd, 2, buf, &buflen, NULL, 0) == -1) { + if (errno == ENOMEM) errno = ENAMETOOLONG; + return -1; + } + strncpy(name, buf, len); + name[len - 1] = '\0'; + if ((p = strchr(name, '.'))) *p = '\0'; + return 0; +} diff --git a/libc/calls/thunks/pread-sysv.S b/libc/calls/gethostname-linux.c similarity index 77% rename from libc/calls/thunks/pread-sysv.S rename to libc/calls/gethostname-linux.c index c046cc598..fac5b9b9c 100644 --- a/libc/calls/thunks/pread-sysv.S +++ b/libc/calls/gethostname-linux.c @@ -1,5 +1,5 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2020 Justine Alexandra Roberts Tunney │ │ │ @@ -16,11 +16,16 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/macros.h" -.source __FILE__ +#include "libc/calls/calls.h" +#include "libc/calls/internal.h" +#include "libc/calls/struct/utsname.h" +#include "libc/str/str.h" +#include "libc/sysv/errfuns.h" -/ Directly calls pread() impl on host o/s if available. -sys_pread: - mov %rcx,%r8 # netbsd+openbsd:pad - jmp __sys_pread - .endfn sys_pread,globl,hidden +int gethostname_linux(char *name, size_t len) { + struct utsname u; + if (uname(&u) == -1) return -1; + memccpy(name, u.nodename, '\0', len); + name[len - 1] = '\0'; + return 0; +} diff --git a/libc/calls/thunks/lseek-sysv.S b/libc/calls/gethostname-nt.c similarity index 73% rename from libc/calls/thunks/lseek-sysv.S rename to libc/calls/gethostname-nt.c index f97982135..9d5a513be 100644 --- a/libc/calls/thunks/lseek-sysv.S +++ b/libc/calls/gethostname-nt.c @@ -1,5 +1,5 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2020 Justine Alexandra Roberts Tunney │ │ │ @@ -16,22 +16,20 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/dce.h" -#include "libc/macros.h" -.source __FILE__ +#include "libc/calls/calls.h" +#include "libc/calls/internal.h" +#include "libc/nt/enum/computernameformat.h" +#include "libc/nt/systeminfo.h" +#include "libc/str/str.h" -/ Directly calls lseek() impl on host o/s if available. -sys_lseek: -#if SupportsOpenbsd() || SupportsNetbsd() - testb $OPENBSD|NETBSD,__hostos(%rip) - cmovnz %rdx,%rcx # openbsd:evilpad - cmovnz %rsi,%rdx - cmovnz .Lzero(%rip),%rsi -#endif - jmp __sys_lseek - .endfn sys_lseek,globl,hidden - - .rodata.cst8 -.Lzero: .quad 0 - .endobj .Lzero - .previous +textwindows int gethostname_nt(char *name, size_t len) { + uint32_t nSize; + char16_t name16[256]; + nSize = ARRAYLEN(name16); + if (GetComputerNameEx(kNtComputerNameDnsHostname, name16, &nSize)) { + tprecode16to8(name, len, name16); + return 0; + } else { + return __winerr(); + } +} diff --git a/libc/calls/gethostname.c b/libc/calls/gethostname.c index 006c6dd3c..5e4337331 100644 --- a/libc/calls/gethostname.c +++ b/libc/calls/gethostname.c @@ -18,20 +18,9 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/struct/utsname.h" #include "libc/dce.h" -#include "libc/errno.h" -#include "libc/macros.h" -#include "libc/nt/enum/computernameformat.h" -#include "libc/nt/errors.h" -#include "libc/nt/runtime.h" -#include "libc/nt/systeminfo.h" -#include "libc/str/str.h" #include "libc/sysv/errfuns.h" -#define CTL_KERN 1 -#define KERN_HOSTNAME 10 - /** * Returns name of host system, e.g. * @@ -42,38 +31,12 @@ int gethostname(char *name, size_t len) { if (len < 1) return einval(); if (!name) return efault(); if (!IsWindows()) { - if (IsBsd()) { - char *p; - int cmd[2]; - char buf[254]; - size_t buflen; - cmd[0] = CTL_KERN; - cmd[1] = KERN_HOSTNAME; - buflen = sizeof(buf); - if (sysctl(cmd, 2, buf, &buflen, NULL, 0) == -1) { - if (errno == ENOMEM) errno = ENAMETOOLONG; - return -1; - } - strncpy(name, buf, len); - name[len - 1] = '\0'; - if ((p = strchr(name, '.'))) *p = '\0'; - return 0; + if (!IsBsd()) { + return gethostname_linux(name, len); } else { - struct utsname u; - if (uname(&u) == -1) return -1; - memccpy(name, u.nodename, '\0', len); - name[len - 1] = '\0'; - return 0; + return gethostname_bsd(name, len); } } else { - uint32_t nSize; - char16_t name16[256]; - nSize = ARRAYLEN(name16); - if (GetComputerNameEx(kNtComputerNameDnsHostname, name16, &nSize)) { - tprecode16to8(name, len, name16); - return 0; - } else { - return __winerr(); - } + return gethostname_nt(name, len); } } diff --git a/libc/calls/getrusage-nt.c b/libc/calls/getrusage-nt.c index fe8d22df9..12715daf4 100644 --- a/libc/calls/getrusage-nt.c +++ b/libc/calls/getrusage-nt.c @@ -25,12 +25,15 @@ #include "libc/nt/thread.h" #include "libc/str/str.h" #include "libc/sysv/consts/rusage.h" +#include "libc/sysv/errfuns.h" textwindows int sys_getrusage_nt(int who, struct rusage *usage) { struct NtFileTime CreationFileTime; struct NtFileTime ExitFileTime; struct NtFileTime KernelFileTime; struct NtFileTime UserFileTime; + if (!usage) return efault(); + if (who == 99) return enosys(); /* @see libc/sysv/consts.sh */ memset(usage, 0, sizeof(*usage)); if ((who == RUSAGE_SELF ? GetProcessTimes : GetThreadTimes)( (who == RUSAGE_SELF ? GetCurrentProcess : GetCurrentThread)(), diff --git a/libc/calls/getrusage.c b/libc/calls/getrusage.c index aa9b63915..285c8a32a 100644 --- a/libc/calls/getrusage.c +++ b/libc/calls/getrusage.c @@ -27,8 +27,6 @@ * @return 0 on success, or -1 w/ errno */ int getrusage(int who, struct rusage *usage) { - if (who == 99) return enosys(); /* @see libc/sysv/consts.sh */ - if (!usage) return efault(); if (!IsWindows()) { return sys_getrusage(who, usage); } else { diff --git a/libc/calls/thunks/gettemppatha-flunk.S b/libc/calls/gettemppatha-flunk.S similarity index 97% rename from libc/calls/thunks/gettemppatha-flunk.S rename to libc/calls/gettemppatha-flunk.S index c1ee50493..f83cc661b 100644 --- a/libc/calls/thunks/gettemppatha-flunk.S +++ b/libc/calls/gettemppatha-flunk.S @@ -22,7 +22,7 @@ / Calls GetTempPathA() w/ different API. / / @see GetSystemDirectoryA(), GetWindowsDirectoryA() -GetTempPathA$flunk: +GetTempPathA_flunk: xchg %rcx,%rdx jmp *__imp_GetTempPathA(%rip) - .endfn GetTempPathA$flunk,globl,hidden + .endfn GetTempPathA_flunk,globl,hidden diff --git a/libc/calls/gettimeofday-sysv.S b/libc/calls/gettimeofday-sysv.S deleted file mode 100644 index f713c38f5..000000000 --- a/libc/calls/gettimeofday-sysv.S +++ /dev/null @@ -1,53 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/dce.h" -#include "libc/macros.h" - -/ Returns system wall time in microseconds. -/ -/ @param rdi points to timeval that receives result -/ @param rsi receives UTC timezone if non-NULL -/ @return always zero -/ @see clock_gettime() for nanosecond precision -/ @see strftime() for string formatting -sys_gettimeofday: - push %rbp - mov %rsp,%rbp - .profilable - test %rsi,%rsi - jz 1f - push $0 - pop (%rsi) -1: xor %esi,%esi # no one zones this way. - xor %edx,%edx # i64*mach_absolute_time - call __sys_gettimeofday -#if SupportsXnu() - testb IsXnu() # XNU might do %rax:%rdx - jz 1f - test %rdi,%rdi - jz 1f - test %rax,%rax - jz 1f - mov %rax,(%rdi) - mov %rdx,8(%rdi) -#endif -1: xor %eax,%eax # nevar fail - pop %rbp - ret - .endfn sys_gettimeofday,globl,hidden diff --git a/libc/calls/gettimeofday.c b/libc/calls/gettimeofday.c index 457581d83..81531d728 100644 --- a/libc/calls/gettimeofday.c +++ b/libc/calls/gettimeofday.c @@ -16,9 +16,11 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" #include "libc/calls/internal.h" #include "libc/calls/struct/timeval.h" #include "libc/dce.h" +#include "libc/sysv/errfuns.h" #include "libc/time/struct/timezone.h" #include "libc/time/time.h" @@ -32,8 +34,15 @@ * @see strftime() for string formatting */ int gettimeofday(struct timeval *tv, struct timezone *tz) { + axdx_t ad; if (!IsWindows()) { - return sys_gettimeofday(tv, tz); + ad = sys_gettimeofday(tv, tz, NULL); + assert(ad.ax != -1); + if (SupportsXnu() && ad.ax && tv) { + tv->tv_sec = ad.ax; + tv->tv_usec = ad.dx; + } + return 0; } else { return sys_gettimeofday_nt(tv, tz); } diff --git a/libc/calls/internal.h b/libc/calls/internal.h index 0a6593570..c4ab6ad5a 100644 --- a/libc/calls/internal.h +++ b/libc/calls/internal.h @@ -100,6 +100,10 @@ forceinline size_t clampio(size_t size) { │ cosmopolitan § syscalls » system five » synthetic jump slots ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ +axdx_t __sys_pipe(i32[hasatleast 2], i32) hidden; +axdx_t sys_fork(void) hidden; +axdx_t sys_getpid(void) hidden; +axdx_t sys_gettimeofday(struct timeval *, struct timezone *, void *) hidden; char *sys_getcwd(char *, u64) hidden; char *sys_getcwd_xnu(char *, u64) hidden; i32 __sys_dup3(i32, i32, i32) hidden; @@ -127,11 +131,10 @@ i32 sys_fchownat(i32, const char *, u32, u32, u32) hidden; i32 sys_fcntl(i32, i32, ...) hidden; i32 sys_fdatasync(i32) hidden; i32 sys_flock(i32, i32) hidden; -i32 sys_fork(void) hidden; i32 sys_fstat(i32, struct stat *) hidden; i32 sys_fstatat(i32, const char *, struct stat *, i32) hidden; i32 sys_fsync(i32) hidden; -i32 sys_ftruncate(i32, i64) hidden; +i32 sys_ftruncate(i32, i64, i64) hidden; i32 sys_futimes(i32, const struct timeval *) hidden; i32 sys_futimesat(i32, const char *, const struct timeval *) hidden; i32 sys_getitimer(i32, struct itimerval *) hidden; @@ -139,11 +142,10 @@ i32 sys_getppid(void) hidden; i32 sys_getpriority(i32, u32) hidden; i32 sys_getrlimit(i32, struct rlimit *) hidden; i32 sys_getrusage(i32, struct rusage *) hidden; -i32 sys_gettimeofday(struct timeval *, struct timezone *) hidden; i32 sys_ioctl(i32, u64, void *) hidden; i32 sys_kill(i32, i32, i32) hidden; i32 sys_linkat(i32, const char *, i32, const char *, i32) hidden; -i32 sys_lseek(i32, i64, i32) hidden; +i32 sys_lseek(i32, i64, i64, i64) hidden; i32 sys_lutimes(const char *, const struct timeval *) hidden; i32 sys_madvise(void *, size_t, i32) hidden; i32 sys_memfd_create(const char *, u32) hidden; @@ -176,7 +178,7 @@ i32 sys_symlinkat(const char *, i32, const char *) hidden; i32 sys_sync(void) hidden; i32 sys_sync_file_range(i32, i64, i64, u32) hidden; i32 sys_sysinfo(struct sysinfo *) hidden; -i32 sys_truncate(const char *, u64) hidden; +i32 sys_truncate(const char *, u64, u64) hidden; i32 sys_uname(char *) hidden; i32 sys_unlinkat(i32, const char *, i32) hidden; i32 sys_utime(const char *, const struct utimbuf *) hidden; @@ -185,22 +187,21 @@ i32 sys_utimes(const char *, const struct timeval *) hidden; i32 sys_wait4(i32, i32 *, i32, struct rusage *) hidden; i64 sys_copy_file_range(i32, long *, i32, long *, u64, u32) hidden; i64 sys_getrandom(void *, u64, u32) hidden; -i64 sys_pread(i32, void *, u64, i64) hidden; -i64 sys_preadv(i32, struct iovec *, i32, i64) hidden; +i64 sys_pread(i32, void *, u64, i64, i64) hidden; +i64 sys_preadv(i32, struct iovec *, i32, i64, i64) hidden; i64 sys_ptrace(int, i32, void *, void *) hidden; -i64 sys_pwrite(i32, const void *, u64, i64) hidden; -i64 sys_pwritev(i32, const struct iovec *, i32, i64) hidden; +i64 sys_pwrite(i32, const void *, u64, i64, i64) hidden; +i64 sys_pwritev(i32, const struct iovec *, i32, i64, i64) hidden; i64 sys_read(i32, void *, u64) hidden; i64 sys_sendfile(i32, i32, i64 *, u64) hidden; i64 sys_splice(i32, i64 *, i32, i64 *, u64, u32) hidden; i64 sys_vmsplice(i32, const struct iovec *, i64, u32) hidden; i64 sys_write(i32, const void *, u64) hidden; u32 sys_getgid(void) hidden; -axdx_t sys_getpid(void) hidden; u32 sys_getsid(int) hidden; u32 sys_gettid(void) hidden; u32 sys_getuid(void) hidden; -void *sys_mmap(void *, u64, u32, u32, i64, i64) hidden; +void *sys_mmap(void *, u64, u32, u32, i64, i64, i64) hidden; void *sys_mremap(void *, u64, u64, i32, void *) hidden; /*───────────────────────────────────────────────────────────────────────────│─╗ @@ -219,6 +220,9 @@ void __stat2linux(void *) hidden; void __restore_rt_netbsd(void) hidden; void __xnutrampoline(void *, i32, i32, const struct __darwin_siginfo *, const struct __darwin_ucontext *) hidden wontreturn; +int gethostname_linux(char *, size_t) hidden; +int gethostname_bsd(char *, size_t) hidden; +int gethostname_nt(char *, size_t) hidden; /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § syscalls » windows nt » veneers ─╬─│┼ diff --git a/libc/calls/ioctl-tcgets.c b/libc/calls/ioctl-tcgets.c index 262e93e6e..2ad11362c 100644 --- a/libc/calls/ioctl-tcgets.c +++ b/libc/calls/ioctl-tcgets.c @@ -27,7 +27,7 @@ static int ioctl_tcgets_sysv(int fd, struct termios *tio) { int rc; union metatermios t; if ((rc = sys_ioctl(fd, TCGETS, &t)) != -1) { - termios2linux(tio, &t); + __termios2linux(tio, &t); } return rc; } diff --git a/libc/calls/ioctl-tcsets.c b/libc/calls/ioctl-tcsets.c index 141b3b85f..867a90783 100644 --- a/libc/calls/ioctl-tcsets.c +++ b/libc/calls/ioctl-tcsets.c @@ -21,13 +21,14 @@ #include "libc/calls/termios.internal.h" #include "libc/dce.h" #include "libc/sysv/consts/termios.h" +#include "libc/sysv/errfuns.h" int ioctl_tcsets_nt(int, uint64_t, const struct termios *); static int ioctl_tcsets_sysv(int fd, uint64_t request, const struct termios *tio) { union metatermios t; - return sys_ioctl(fd, request, termios2host(&t, tio)); + return sys_ioctl(fd, request, __termios2host(&t, tio)); } /** @@ -38,6 +39,7 @@ static int ioctl_tcsets_sysv(int fd, uint64_t request, * @see ioctl(fd, TIOCGETA{,W,F}, tio) dispatches here */ int ioctl_tcsets(int fd, uint64_t request, const struct termios *tio) { + if (!tio) return efault(); if (!IsWindows()) { return ioctl_tcsets_sysv(fd, request, tio); } else { diff --git a/libc/calls/ktmppath.S b/libc/calls/ktmppath.S index e8041acbc..a0158b81c 100644 --- a/libc/calls/ktmppath.S +++ b/libc/calls/ktmppath.S @@ -35,7 +35,7 @@ kTmpPath: movl $'/|'t<<010|'m<<020|'p<<030,(%rdi) movw $'/,4(%rdi) pushpop kTmpPathMax,%rdx - ezlea GetTempPathA$flunk,ax + ezlea GetTempPathA_flunk,ax call __getntsyspath .init.end 300,_init_kTmpPath .source __FILE__ diff --git a/libc/calls/link.c b/libc/calls/link.c index 69a975c12..36362510c 100644 --- a/libc/calls/link.c +++ b/libc/calls/link.c @@ -16,11 +16,11 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/dce.h" -#include "libc/calls/internal.h" #include "libc/calls/calls.h" -#include "libc/sysv/errfuns.h" +#include "libc/calls/internal.h" +#include "libc/dce.h" #include "libc/sysv/consts/at.h" +#include "libc/sysv/errfuns.h" /** * Creates hard filesystem link. @@ -32,7 +32,6 @@ * @asyncsignalsafe */ int link(const char *existingpath, const char *newpath) { - if (!existingpath || !newpath) return efault(); if (!IsWindows()) { return sys_linkat(AT_FDCWD, existingpath, AT_FDCWD, newpath, 0); } else { diff --git a/libc/calls/lseek.c b/libc/calls/lseek.c index d63daec35..2cc889dd0 100644 --- a/libc/calls/lseek.c +++ b/libc/calls/lseek.c @@ -29,9 +29,11 @@ * @return new position relative to beginning, or -1 on error * @asyncsignalsafe */ -int64_t lseek(int fd, int64_t offset, int whence) { - if (!IsWindows()) { - return sys_lseek(fd, offset, whence); +int64_t lseek(int fd, int64_t offset, unsigned whence) { + if (!IsWindows() && !IsOpenbsd() && !IsNetbsd()) { + return sys_lseek(fd, offset, whence, 0); + } else if (IsOpenbsd() || IsNetbsd()) { + return sys_lseek(fd, offset, offset, whence); } else { return sys_lseek_nt(fd, offset, whence); } diff --git a/libc/calls/mkntpath.c b/libc/calls/mkntpath.c index e997433a8..1c53b3a7f 100644 --- a/libc/calls/mkntpath.c +++ b/libc/calls/mkntpath.c @@ -71,6 +71,7 @@ textwindows int __mkntpath2(const char *path, * 5. Reserve ≥13 for mkdir() i.e. 1+8+3+1, e.g. "\\ffffffff.xxx\0" */ size_t i, n; + if (!path) return efault(); path = FixNtMagicPath(path, flags); n = tprecode8to16(path16, PATH_MAX - 16, path).ax; if (n == PATH_MAX - 16 - 1) return enametoolong(); diff --git a/libc/calls/nanosleep.c b/libc/calls/nanosleep.c index 58581590f..da817ad73 100644 --- a/libc/calls/nanosleep.c +++ b/libc/calls/nanosleep.c @@ -26,16 +26,12 @@ */ int nanosleep(const struct timespec *req, struct timespec *rem) { if (!req) return efault(); - if (!IsWindows()) { - if (!IsMetal()) { - if (!IsXnu()) { - return sys_nanosleep(req, rem); - } else { - return sys_nanosleep_xnu(req, rem); - } - } else { - return enosys(); /* TODO: Sleep on Metal */ - } + if (!IsWindows() && !IsMetal() && !IsXnu()) { + return sys_nanosleep(req, rem); + } else if (IsXnu()) { + return sys_nanosleep_xnu(req, rem); + } else if (IsMetal()) { + return enosys(); /* TODO: Sleep on Metal */ } else { return sys_nanosleep_nt(req, rem); } diff --git a/libc/calls/onntconsoleevent_init.S b/libc/calls/onntconsoleevent_init.S index deb6a748d..b493e4861 100644 --- a/libc/calls/onntconsoleevent_init.S +++ b/libc/calls/onntconsoleevent_init.S @@ -17,8 +17,14 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/macros.h" +.text.windows .source __FILE__ +__onntconsoleevent_nt: + ezlea __onntconsoleevent,ax + jmp __nt2sysv + .endfn __onntconsoleevent_nt,globl,hidden + .init.start 300,_init_onntconsoleevent ezlea __onntconsoleevent_nt,cx pushpop 1,%rdx diff --git a/libc/calls/thunks/onwincrash.S b/libc/calls/onwincrash.S similarity index 100% rename from libc/calls/thunks/onwincrash.S rename to libc/calls/onwincrash.S diff --git a/libc/calls/openat.c b/libc/calls/openat.c index 79820ae97..6816371a8 100644 --- a/libc/calls/openat.c +++ b/libc/calls/openat.c @@ -39,7 +39,7 @@ * @asyncsignalsafe * @vforksafe */ -nodiscard int openat(int dirfd, const char *file, int flags, ...) { +int openat(int dirfd, const char *file, int flags, ...) { va_list va; unsigned mode; struct ZiposUri zipname; diff --git a/libc/calls/pipe-nt.c b/libc/calls/pipe-nt.c index 79782dedd..b86c959da 100644 --- a/libc/calls/pipe-nt.c +++ b/libc/calls/pipe-nt.c @@ -78,9 +78,13 @@ textwindows int sys_pipe_nt(int pipefd[2], unsigned flags) { pipefd[1] = writer; return 0; } else { + __winerr(); CloseHandle(hin); } + } else { + __winerr(); } + __releasefd(writer); __releasefd(reader); - return __winerr(); + return -1; } diff --git a/libc/calls/pipe-sysv.S b/libc/calls/pipe-sysv.S deleted file mode 100644 index 2a436a98b..000000000 --- a/libc/calls/pipe-sysv.S +++ /dev/null @@ -1,48 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/dce.h" -#include "libc/macros.h" -.source __FILE__ - -/ Creates file descriptors for IPC. -/ -/ @param rdi points to int3[2] that gets (reader, writer) -/ @return 0 on success or -1 w/ errno -/ @asyncsignalsafe -/ @see libc/sysv/syscalls.sh -/ @see pipe2() -sys_pipe: - push %rbp - mov %rsp,%rbp -#if SupportsFreebsd() - xor %esi,%esi -#endif - call __sys_pipe -#if SupportsXnu() || SupportsNetbsd() - testb $XNU|NETBSD,__hostos(%rip) - jz 1f - cmp $-1,%rax - je 1f - mov %eax,(%rdi) - mov %edx,4(%rdi) - xor %eax,%eax -#endif -1: pop %rbp - ret - .endfn sys_pipe,globl,hidden diff --git a/libc/calls/thunks/sigsuspend-sysv.S b/libc/calls/pipe-sysv.c similarity index 80% rename from libc/calls/thunks/sigsuspend-sysv.S rename to libc/calls/pipe-sysv.c index 55b5f9064..575337099 100644 --- a/libc/calls/thunks/sigsuspend-sysv.S +++ b/libc/calls/pipe-sysv.c @@ -1,5 +1,5 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2021 Justine Alexandra Roberts Tunney │ │ │ @@ -16,19 +16,19 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/internal.h" #include "libc/dce.h" -#include "libc/macros.h" -/ Pauses process w/ standard ABI. -sys_sigsuspend: - push %rbp - mov %rsp,%rbp -#if SupportsOpenbsd() - testb IsOpenbsd() - jz 1f - mov (%rdi),%edi # openbsd:byvalue -#endif -1: call __sys_sigsuspend - pop %rbp - ret - .endfn sys_sigsuspend,globl +int sys_pipe(int fds[2]) { + axdx_t ad; + int ax, dx; + ad = __sys_pipe(fds, 0); + ax = ad.ax; + dx = ad.dx; + if ((IsXnu() || IsNetbsd()) && ax != -1) { + fds[0] = ax; + fds[1] = dx; + ax = 0; + } + return ax; +} diff --git a/libc/calls/pipe2.c b/libc/calls/pipe2.c index 638ffa85e..1056f8edd 100644 --- a/libc/calls/pipe2.c +++ b/libc/calls/pipe2.c @@ -16,9 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/dce.h" #include "libc/sysv/errfuns.h" /** diff --git a/libc/calls/pread.c b/libc/calls/pread.c index 68c2406a0..ac769ed9f 100644 --- a/libc/calls/pread.c +++ b/libc/calls/pread.c @@ -47,7 +47,7 @@ ssize_t pread(int fd, void *buf, size_t size, int64_t offset) { rc = weaken(__zipos_read)( (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, buf, size, offset); } else if (!IsWindows()) { - rc = sys_pread(fd, buf, size, offset); + rc = sys_pread(fd, buf, size, offset, offset); } else if (__isfdkind(fd, kFdFile)) { rc = sys_read_nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, offset); } else { diff --git a/libc/calls/preadv.c b/libc/calls/preadv.c index 076dfe516..f1813fc5d 100644 --- a/libc/calls/preadv.c +++ b/libc/calls/preadv.c @@ -17,12 +17,12 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/bits.h" -#include "libc/bits/safemacros.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/calls/struct/iovec.h" #include "libc/dce.h" #include "libc/errno.h" +#include "libc/macros.h" #include "libc/sysv/consts/iov.h" #include "libc/sysv/errfuns.h" @@ -42,7 +42,7 @@ ssize_t preadv(int fd, struct iovec *iovec, int count, int64_t off) { int olderr; ssize_t rc; if (!count) return 0; - if ((count = min(count, IOV_MAX)) < 0) return einval(); + if ((count = MIN(count, IOV_MAX)) < 0) return einval(); /* * NT, XNU, and 2007-era Linux don't support this system call. @@ -58,7 +58,7 @@ ssize_t preadv(int fd, struct iovec *iovec, int count, int64_t off) { demodernize = true; } else { olderr = errno; - rc = sys_preadv(fd, iovec, count, off); + rc = sys_preadv(fd, iovec, count, off, off); if (rc == -1 && errno == ENOSYS) { errno = olderr; demodernize = true; @@ -71,7 +71,7 @@ ssize_t preadv(int fd, struct iovec *iovec, int count, int64_t off) { } if (!demodernize) { - return sys_preadv(fd, iovec, count, off); + return sys_preadv(fd, iovec, count, off, off); } else { return pread(fd, iovec[0].iov_base, iovec[0].iov_len, off); } diff --git a/libc/calls/pwrite.c b/libc/calls/pwrite.c index 8c78108cc..d13be02e2 100644 --- a/libc/calls/pwrite.c +++ b/libc/calls/pwrite.c @@ -43,7 +43,7 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) { if (fd == -1 || offset < 0) return einval(); size = MIN(size, 0x7ffff000); if (!IsWindows()) { - rc = sys_pwrite(fd, buf, size, offset); + rc = sys_pwrite(fd, buf, size, offset, offset); } else if (__isfdkind(fd, kFdFile)) { rc = sys_write_nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, offset); } else { diff --git a/libc/calls/pwritev.c b/libc/calls/pwritev.c index e3f1e9b72..9125cb075 100644 --- a/libc/calls/pwritev.c +++ b/libc/calls/pwritev.c @@ -16,12 +16,12 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/bits/safemacros.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/calls/struct/iovec.h" #include "libc/dce.h" #include "libc/errno.h" +#include "libc/macros.h" #include "libc/sysv/consts/iov.h" #include "libc/sysv/errfuns.h" @@ -45,9 +45,8 @@ ssize_t pwritev(int fd, const struct iovec *iovec, int count, int64_t off) { static bool once, demodernize; int olderr; ssize_t rc; - if (!count) return 0; - if ((count = min(count, IOV_MAX)) < 0) return einval(); + if ((count = MIN(count, IOV_MAX)) < 0) return einval(); /* * NT, XNU, and 2007-era Linux don't support this system call. @@ -63,7 +62,7 @@ ssize_t pwritev(int fd, const struct iovec *iovec, int count, int64_t off) { demodernize = true; } else { olderr = errno; - rc = sys_pwritev(fd, iovec, count, off); + rc = sys_pwritev(fd, iovec, count, off, off); if (rc == -1 && errno == ENOSYS) { errno = olderr; demodernize = true; @@ -77,7 +76,7 @@ ssize_t pwritev(int fd, const struct iovec *iovec, int count, int64_t off) { } if (!demodernize) { - return sys_pwritev(fd, iovec, count, off); + return sys_pwritev(fd, iovec, count, off, off); } else { return pwrite(fd, iovec[0].iov_base, iovec[0].iov_len, off); } diff --git a/libc/calls/read-nt.c b/libc/calls/read-nt.c index e9b92f138..e1c86084e 100644 --- a/libc/calls/read-nt.c +++ b/libc/calls/read-nt.c @@ -24,21 +24,37 @@ #include "libc/nt/errors.h" #include "libc/nt/runtime.h" #include "libc/nt/struct/overlapped.h" -#include "libc/nt/struct/teb.h" #include "libc/sysv/errfuns.h" textwindows ssize_t sys_read_nt(struct Fd *fd, const struct iovec *iov, - size_t iovlen, ssize_t opt_offset) { - uint32_t got; + size_t iovlen, ssize_t opt_offset) { + size_t i, total; + uint32_t got, size; struct NtOverlapped overlap; while (iovlen && !iov[0].iov_len) iov++, iovlen--; - if (ReadFile(fd->handle, iovlen ? iov[0].iov_base : NULL, - iovlen ? clampio(iov[0].iov_len) : 0, &got, - offset2overlap(opt_offset, &overlap))) { - return got; - } else if (NtGetErr() == kNtErrorBrokenPipe) { - return 0; /* read() doesn't EPIPE lool */ + if (iovlen) { + for (total = i = 0; i < iovlen; ++i) { + size = clampio(iov[i].iov_len); + if (ReadFile(fd->handle, iov[i].iov_base, size, &got, + offset2overlap(opt_offset, &overlap))) { + total += got; + if (opt_offset != -1) opt_offset += got; + if (got < iov[i].iov_len) break; + } else if (GetLastError() == kNtErrorBrokenPipe) { + break; /* read() doesn't EPIPE lool */ + } else { + return __winerr(); + } + } + return total; } else { - return __winerr(); + if (ReadFile(fd->handle, NULL, 0, &got, + offset2overlap(opt_offset, &overlap))) { + return got; + } else if (GetLastError() == kNtErrorBrokenPipe) { + return 0; + } else { + return __winerr(); + } } } diff --git a/libc/calls/renameat.c b/libc/calls/renameat.c index ad4ff00a4..16ce76709 100644 --- a/libc/calls/renameat.c +++ b/libc/calls/renameat.c @@ -32,7 +32,6 @@ */ int renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) { - if (!oldpath || !newpath) return efault(); if (!IsWindows()) { return sys_renameat(olddirfd, oldpath, newdirfd, newpath); } else { diff --git a/libc/calls/sigprocmask.c b/libc/calls/sigprocmask.c index 94cb7c188..7df83de75 100644 --- a/libc/calls/sigprocmask.c +++ b/libc/calls/sigprocmask.c @@ -20,6 +20,7 @@ #include "libc/calls/internal.h" #include "libc/calls/struct/sigset.h" #include "libc/dce.h" +#include "libc/str/str.h" #include "libc/sysv/errfuns.h" /** @@ -37,8 +38,18 @@ * @vforksafe */ int sigprocmask(int how, const sigset_t *opt_set, sigset_t *opt_out_oldset) { - if (!IsWindows()) { + int32_t x; + if (!IsWindows() && !IsOpenbsd()) { return sys_sigprocmask(how, opt_set, opt_out_oldset, 8); + } else if (IsOpenbsd()) { + if (!opt_set) how = 1; + if (opt_set) opt_set = (sigset_t *)(uintptr_t)(*(uint32_t *)opt_set); + if ((x = sys_sigprocmask(how, opt_set, 0, 0)) != -1) { + if (opt_out_oldset) memcpy(opt_out_oldset, &x, sizeof(x)); + return 0; + } else { + return -1; + } } else { return 0; /* TODO(jart): Implement me! */ } diff --git a/libc/calls/sigsuspend.c b/libc/calls/sigsuspend.c index 6f91a49d3..60dae7287 100644 --- a/libc/calls/sigsuspend.c +++ b/libc/calls/sigsuspend.c @@ -30,8 +30,9 @@ * @asyncsignalsafe */ int sigsuspend(const sigset_t *ignore) { - if (!ignore) return efault(); + unsigned x; if (!IsWindows()) { + if (IsOpenbsd()) ignore = (sigset_t *)(uintptr_t)(*(uint32_t *)ignore); return sys_sigsuspend(ignore, 8); } else { return enosys(); /* TODO(jart): Implement me! */ diff --git a/libc/calls/stat2linux.c b/libc/calls/stat2linux.c index 0f9306b3e..9970d8535 100644 --- a/libc/calls/stat2linux.c +++ b/libc/calls/stat2linux.c @@ -82,13 +82,13 @@ static textstartup void __stat2linux_netbsd(union metastat *ms) { */ textstartup void __stat2linux(void *ms) { if (ms) { - if (SupportsXnu() && IsXnu()) { + if (IsXnu()) { __stat2linux_xnu((union metastat *)ms); - } else if (SupportsFreebsd() && IsFreebsd()) { + } else if (IsFreebsd()) { __stat2linux_freebsd((union metastat *)ms); - } else if (SupportsOpenbsd() && IsOpenbsd()) { + } else if (IsOpenbsd()) { __stat2linux_openbsd((union metastat *)ms); - } else if (SupportsNetbsd() && IsNetbsd()) { + } else if (IsNetbsd()) { __stat2linux_netbsd((union metastat *)ms); } } diff --git a/libc/calls/struct/metatermios.internal.h b/libc/calls/struct/metatermios.internal.h index 02b31cd0e..fa2653281 100644 --- a/libc/calls/struct/metatermios.internal.h +++ b/libc/calls/struct/metatermios.internal.h @@ -1,6 +1,5 @@ #ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_METATERMIOS_H_ #define COSMOPOLITAN_LIBC_CALLS_STRUCT_METATERMIOS_H_ -#ifndef __STRICT_ANSI__ #include "libc/calls/struct/termios.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ @@ -33,5 +32,4 @@ union metatermios { COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* !ANSI */ #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_METATERMIOS_H_ */ diff --git a/libc/calls/sync.c b/libc/calls/sync.c index c6f80f994..231ae339f 100644 --- a/libc/calls/sync.c +++ b/libc/calls/sync.c @@ -21,7 +21,7 @@ #include "libc/dce.h" /** - * Flushes file system changes to disk to the greatest extent possible. + * Flushes file system changes to disk by any means necessary. */ void sync(void) { if (!IsWindows()) { diff --git a/libc/calls/termios.internal.h b/libc/calls/termios.internal.h index c8e044d02..c76a3467c 100644 --- a/libc/calls/termios.internal.h +++ b/libc/calls/termios.internal.h @@ -21,8 +21,8 @@ COSMOPOLITAN_C_START_ (TO)->c_ospeed = (FROM)->c_ospeed; \ } while (0) -void *termios2host(union metatermios *, const struct termios *); -void termios2linux(struct termios *, const union metatermios *); +void *__termios2host(union metatermios *, const struct termios *) hidden; +void __termios2linux(struct termios *, const union metatermios *) hidden; COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/calls/termios2host.c b/libc/calls/termios2host.c index 121410364..a08507757 100644 --- a/libc/calls/termios2host.c +++ b/libc/calls/termios2host.c @@ -22,14 +22,14 @@ #include "libc/calls/termios.internal.h" #include "libc/dce.h" -void *termios2host(union metatermios *t, const struct termios *lt) { - if (IsXnu()) { +void *__termios2host(union metatermios *t, const struct termios *lt) { + if (!IsXnu() && !IsFreebsd() && !IsOpenbsd() && !IsNetbsd()) { + return lt; + } else if (IsXnu()) { COPY_TERMIOS(&t->xnu, lt); return &t->xnu; - } else if (IsFreebsd() || IsOpenbsd()) { + } else { COPY_TERMIOS(&t->bsd, lt); return &t->bsd; - } else { - return lt; } } diff --git a/libc/calls/termios2linux.c b/libc/calls/termios2linux.c index e5fee21c2..ab775d69c 100644 --- a/libc/calls/termios2linux.c +++ b/libc/calls/termios2linux.c @@ -22,10 +22,10 @@ #include "libc/calls/termios.internal.h" #include "libc/dce.h" -void termios2linux(struct termios *lt, const union metatermios *t) { +void __termios2linux(struct termios *lt, const union metatermios *t) { if (IsXnu()) { COPY_TERMIOS(lt, &t->xnu); - } else if (IsFreebsd() || IsOpenbsd()) { + } else if (IsFreebsd() || IsOpenbsd() || IsNetbsd()) { COPY_TERMIOS(lt, &t->bsd); } else { memcpy(lt, &t->linux, sizeof(*lt)); diff --git a/libc/calls/thunks/ftruncate-sysv.S b/libc/calls/thunks/ftruncate-sysv.S deleted file mode 100644 index dc1875c62..000000000 --- a/libc/calls/thunks/ftruncate-sysv.S +++ /dev/null @@ -1,26 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/macros.h" -.source __FILE__ - -/ Directly calls ftruncate() impl on host o/s if available. -sys_ftruncate: - mov %rsi,%rdx # netbsd+openbsd:pad - jmp __sys_ftruncate - .endfn sys_ftruncate,globl,hidden diff --git a/libc/calls/thunks/onntconsoleevent.S b/libc/calls/thunks/onntconsoleevent.S deleted file mode 100644 index 264158940..000000000 --- a/libc/calls/thunks/onntconsoleevent.S +++ /dev/null @@ -1,26 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/macros.h" -.text.windows -.source __FILE__ - -__onntconsoleevent_nt: - ezlea __onntconsoleevent,ax - jmp __nt2sysv - .endfn __onntconsoleevent_nt,globl,hidden diff --git a/libc/calls/thunks/preadv-sysv.S b/libc/calls/thunks/preadv-sysv.S deleted file mode 100644 index 6ee8ecc5a..000000000 --- a/libc/calls/thunks/preadv-sysv.S +++ /dev/null @@ -1,26 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/macros.h" -.source __FILE__ - -/ Directly calls preadv() impl on host o/s if available. -sys_preadv: - mov %rcx,%r8 # netbsd+openbsd:pad - jmp __sys_preadv - .endfn sys_preadv,globl,hidden diff --git a/libc/calls/thunks/pwrite-sysv.S b/libc/calls/thunks/pwrite-sysv.S deleted file mode 100644 index b13ecebf3..000000000 --- a/libc/calls/thunks/pwrite-sysv.S +++ /dev/null @@ -1,26 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/macros.h" -.source __FILE__ - -/ Directly calls pwrite() impl on host o/s if available. -sys_pwrite: - mov %rcx,%r8 # netbsd+openbsd:pad - jmp __sys_pwrite - .endfn sys_pwrite,globl,hidden diff --git a/libc/calls/thunks/pwritev-sysv.S b/libc/calls/thunks/pwritev-sysv.S deleted file mode 100644 index 0a34eaf41..000000000 --- a/libc/calls/thunks/pwritev-sysv.S +++ /dev/null @@ -1,26 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/macros.h" -.source __FILE__ - -/ Directly calls pwritev() impl on host o/s if available. -sys_pwritev: - mov %rcx,%r8 # netbsd+openbsd:pad - jmp __sys_pwritev - .endfn sys_pwritev,globl,hidden diff --git a/libc/calls/thunks/sigprocmask-sysv.S b/libc/calls/thunks/sigprocmask-sysv.S deleted file mode 100644 index a2c54ab70..000000000 --- a/libc/calls/thunks/sigprocmask-sysv.S +++ /dev/null @@ -1,46 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2021 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/dce.h" -#include "libc/macros.h" - -/ Sets System Five process signal mask w/ standard ABI. -sys_sigprocmask: - push %rbp - mov %rsp,%rbp -#if SupportsOpenbsd() - testb IsOpenbsd() - jz 4f - test %rsi,%rsi - jnz 1f - mov $1,%edi # SIG_BLOCK on BSDs - jmp 2f -1: mov (%rsi),%esi # openbsd:byvalue -2: call __sys_sigprocmask - cmp $-1,%eax - je 5f - test %rdx,%rdx # original param not a result - jz 3f - mov %eax,(%rdx) # openbsd:byvalue -3: xor %eax,%eax - jmp 5f -#endif -4: call __sys_sigprocmask -5: pop %rbp - ret - .endfn sys_sigprocmask,globl diff --git a/libc/calls/thunks/truncate-sysv.S b/libc/calls/thunks/truncate-sysv.S deleted file mode 100644 index bc6453ad9..000000000 --- a/libc/calls/thunks/truncate-sysv.S +++ /dev/null @@ -1,26 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/macros.h" -.source __FILE__ - -/ Directly calls truncate() impl on host o/s if available. -sys_truncate: - mov %rsi,%rdx # netbsd+openbsd:pad - jmp __sys_truncate - .endfn sys_truncate,globl,hidden diff --git a/libc/calls/truncate.c b/libc/calls/truncate.c index bc4f8c295..a8c3f75f1 100644 --- a/libc/calls/truncate.c +++ b/libc/calls/truncate.c @@ -32,9 +32,8 @@ * @error ENOENT */ int truncate(const char *path, uint64_t length) { - if (!path) return efault(); if (!IsWindows()) { - return sys_truncate(path, length); + return sys_truncate(path, length, length); } else { return sys_truncate_nt(path, length); } diff --git a/libc/runtime/unsetenv.c b/libc/calls/unsetenv.c similarity index 80% rename from libc/runtime/unsetenv.c rename to libc/calls/unsetenv.c index a69d81098..b38abc406 100644 --- a/libc/runtime/unsetenv.c +++ b/libc/calls/unsetenv.c @@ -16,27 +16,32 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/bits/safemacros.h" #include "libc/runtime/runtime.h" -#include "libc/str/str.h" -#include "libc/sysv/errfuns.h" /** * Removes environment variable. */ -int unsetenv(const char *name) { - if (isempty(name) || strchr(name, '=')) return einval(); - if (environ) { - char **ep = environ; - size_t removed = 0; - size_t namelen = strlen(name); - do { - if (*ep && strncmp(*ep, name, namelen) == 0 && (*ep)[namelen] == '=') { - --removed; - } else if (removed) { - ep[removed] = *ep; +int unsetenv(const char *s) { + char **p; + size_t i, j, k; + if (s && (p = environ)) { + for (i = 0; p[i]; ++i) { + for (j = 0;; ++j) { + if (!s[j]) { + if (p[i][j] == '=') { + k = i + 1; + do { + p[k - 1] = p[k]; + } while (p[k++]); + return 0; + } + break; + } + if (s[j] != p[i][j]) { + break; + } } - } while (*ep++); + } } return 0; } diff --git a/libc/calls/thunks/winalarm.S b/libc/calls/winalarm.S similarity index 100% rename from libc/calls/thunks/winalarm.S rename to libc/calls/winalarm.S diff --git a/libc/calls/write-nt.c b/libc/calls/write-nt.c index c508a5725..3a3655aed 100644 --- a/libc/calls/write-nt.c +++ b/libc/calls/write-nt.c @@ -25,7 +25,7 @@ #include "libc/nt/struct/overlapped.h" #include "libc/sysv/errfuns.h" -static size_t SumIovecLen(const struct iovec *v, size_t n) { +static textwindows size_t SumIovecLen(const struct iovec *v, size_t n) { size_t i, sum; for (sum = i = 0; i < n; ++i) { sum += v[i].iov_len; @@ -34,16 +34,32 @@ static size_t SumIovecLen(const struct iovec *v, size_t n) { } textwindows ssize_t sys_write_nt(struct Fd *fd, const struct iovec *iov, - size_t iovlen, ssize_t opt_offset) { - uint32_t wrote; + size_t iovlen, ssize_t opt_offset) { + size_t i, total; + uint32_t size, wrote; struct NtOverlapped overlap; while (iovlen && !iov[0].iov_len) iov++, iovlen--; - if (WriteFile(fd->handle, iovlen ? iov[0].iov_base : NULL, - iovlen ? clampio(iov[0].iov_len) : 0, &wrote, - offset2overlap(opt_offset, &overlap))) { - if (!wrote) assert(!SumIovecLen(iov, iovlen)); - return wrote; + if (iovlen) { + for (total = i = 0; i < iovlen; ++i) { + if (!iov[i].iov_len) continue; + size = clampio(iov[0].iov_len); + if (WriteFile(fd->handle, iov[i].iov_base, size, &wrote, + offset2overlap(opt_offset, &overlap))) { + total += wrote; + if (opt_offset != -1) opt_offset += wrote; + if (wrote < iov[i].iov_len) break; + } else { + return __winerr(); + } + } + if (!total) assert(!SumIovecLen(iov, iovlen)); + return total; } else { - return __winerr(); + if (WriteFile(fd->handle, NULL, 0, &wrote, + offset2overlap(opt_offset, &overlap))) { + return 0; + } else { + return __winerr(); + } } } diff --git a/libc/dce.h b/libc/dce.h index b58bbec89..831a94bb1 100644 --- a/libc/dce.h +++ b/libc/dce.h @@ -51,12 +51,6 @@ #define UseSecurityBlankets() 0 #endif -#ifdef __MGENERAL_REGS_ONLY__ -#define UseGeneralRegsOnly() 1 -#else -#define UseGeneralRegsOnly() 0 -#endif - #ifdef TINY #define IsTiny() 1 #else @@ -87,15 +81,14 @@ ((SUPPORT_VECTOR & (LINUX | METAL | XNU | OPENBSD | FREEBSD | NETBSD)) != 0) #ifndef __ASSEMBLER__ -#define __HOSTOS (__hostos & SUPPORT_VECTOR) -#define IsLinux() ((__HOSTOS & LINUX) == LINUX) -#define IsMetal() ((__HOSTOS & METAL) == METAL) -#define IsWindows() ((__HOSTOS & WINDOWS) == WINDOWS) -#define IsBsd() ((__HOSTOS & (XNU | FREEBSD | OPENBSD | NETBSD)) != 0) -#define IsXnu() ((__HOSTOS & XNU) == XNU) -#define IsFreebsd() ((__HOSTOS & FREEBSD) == FREEBSD) -#define IsOpenbsd() ((__HOSTOS & OPENBSD) == OPENBSD) -#define IsNetbsd() ((__HOSTOS & NETBSD) == NETBSD) +#define IsLinux() (SupportsLinux() && (__hostos & LINUX)) +#define IsMetal() (SupportsMetal() && (__hostos & METAL)) +#define IsWindows() (SupportsWindows() && (__hostos & WINDOWS)) +#define IsXnu() (SupportsXnu() && (__hostos & XNU)) +#define IsFreebsd() (SupportsFreebsd() && (__hostos & FREEBSD)) +#define IsOpenbsd() (SupportsOpenbsd() && (__hostos & OPENBSD)) +#define IsNetbsd() (SupportsNetbsd() && (__hostos & NETBSD)) +#define IsBsd() (IsXnu() || IsFreebsd() || IsOpenbsd() || IsNetbsd()) #else /* clang-format off */ #define IsLinux() $LINUX,__hostos(%rip) diff --git a/libc/fmt/dirname.c b/libc/fmt/dirname.c index 0490c2faf..4101daec8 100644 --- a/libc/fmt/dirname.c +++ b/libc/fmt/dirname.c @@ -19,7 +19,8 @@ #include "libc/fmt/conv.h" #include "libc/str/str.h" -#define ISDELIM(c) (c == '/' || c == '\\' || c == '.') +#define ISSLASH(c) (c == '/' || c == '\\') +#define ISDELIM(c) (ISSLASH(c) || c == '.') /** * Returns directory portion of path. @@ -30,7 +31,7 @@ char *dirname(char *s) { if (!(n = strlen(s))) return s; while (n && ISDELIM(s[n - 1])) --n; if (n) { - while (n && !ISDELIM(s[n - 1])) --n; + while (n && !ISSLASH(s[n - 1])) --n; if (n) { while (n && ISDELIM(s[n - 1])) --n; if (!n) ++n; diff --git a/libc/fmt/palandftoa.c b/libc/fmt/palandftoa.c index 7d109f98d..fa3bbff91 100644 --- a/libc/fmt/palandftoa.c +++ b/libc/fmt/palandftoa.c @@ -31,7 +31,7 @@ │ be thread safe). │ └─────────────────────────────────────────────────────────────────────────────*/ #include "libc/fmt/paland.inc" -#include "libc/fmt/palandprintf.internal.h" +#include "libc/fmt/palandprintf.h" #include "libc/math.h" /** diff --git a/libc/fmt/palandntoa.c b/libc/fmt/palandntoa.c index ee4c8fee0..3404d7f5c 100644 --- a/libc/fmt/palandntoa.c +++ b/libc/fmt/palandntoa.c @@ -27,7 +27,7 @@ #include "libc/assert.h" #include "libc/fmt/conv.h" #include "libc/fmt/paland.inc" -#include "libc/fmt/palandprintf.internal.h" +#include "libc/fmt/palandprintf.h" uintmax_t __udivmodti4(uintmax_t, uintmax_t, uintmax_t *); diff --git a/libc/fmt/palandprintf.c b/libc/fmt/palandprintf.c index 5531641f0..2a5383a0d 100644 --- a/libc/fmt/palandprintf.c +++ b/libc/fmt/palandprintf.c @@ -41,7 +41,7 @@ #include "libc/fmt/conv.h" #include "libc/fmt/fmt.h" #include "libc/fmt/paland.inc" -#include "libc/fmt/palandprintf.internal.h" +#include "libc/fmt/palandprintf.h" #include "libc/mem/mem.h" #include "libc/runtime/internal.h" #include "libc/str/str.h" diff --git a/libc/fmt/palandprintf.internal.h b/libc/fmt/palandprintf.h similarity index 100% rename from libc/fmt/palandprintf.internal.h rename to libc/fmt/palandprintf.h diff --git a/libc/fmt/pflink.h b/libc/fmt/pflink.h index 434289042..24bf35216 100644 --- a/libc/fmt/pflink.h +++ b/libc/fmt/pflink.h @@ -1,6 +1,10 @@ #ifndef COSMOPOLITAN_LIBC_FMT_PFLINK_H_ #define COSMOPOLITAN_LIBC_FMT_PFLINK_H_ #include "libc/dce.h" +#include "libc/mem/mem.h" +#include "libc/runtime/runtime.h" +#include "libc/str/str.h" +#include "libc/unicode/unicode.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) #ifndef __STRICT_ANSI__ @@ -79,11 +83,6 @@ __asm__(".section .yoink\n\t" "nopl\t__grow(%rip)\n\t" ".previous"); #else -#include "libc/fmt/palandprintf.internal.h" -#include "libc/mem/mem.h" -#include "libc/runtime/runtime.h" -#include "libc/str/str.h" -#include "libc/unicode/unicode.h" static long __pflink(long x) { x |= kCp437[0]; x |= ntoa(0, 0, 0, 0, 0, 0, 0, 0, 0); diff --git a/libc/fmt/spacepad.c b/libc/fmt/spacepad.c index 7cab0bdf0..61c5dcb85 100644 --- a/libc/fmt/spacepad.c +++ b/libc/fmt/spacepad.c @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/fmt/palandprintf.internal.h" +#include "libc/fmt/palandprintf.h" int spacepad(int out(long, void *), void *arg, unsigned long n) { int i, rc; diff --git a/libc/fmt/stoa.c b/libc/fmt/stoa.c index 423cd447d..cdbc3b59c 100644 --- a/libc/fmt/stoa.c +++ b/libc/fmt/stoa.c @@ -18,7 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/weaken.h" #include "libc/fmt/paland.inc" -#include "libc/fmt/palandprintf.internal.h" +#include "libc/fmt/palandprintf.h" #include "libc/nexgen32e/tinystrlen.internal.h" #include "libc/str/str.h" #include "libc/str/thompike.h" diff --git a/libc/mem/putenv.c b/libc/mem/putenv.c index 8f6d5a2a3..53e7a9612 100644 --- a/libc/mem/putenv.c +++ b/libc/mem/putenv.c @@ -32,7 +32,7 @@ int PutEnvImpl(char *s, bool overwrite) { if (!p) goto fail; namelen = p + 1 - s; for (i = 0; environ[i]; ++i) { - if (strncmp(environ[i], s, namelen) == 0) { + if (!strncmp(environ[i], s, namelen)) { if (!overwrite) { free(s); return 0; diff --git a/libc/runtime/directmap.c b/libc/runtime/directmap.c index 53be7795c..bc521e05a 100644 --- a/libc/runtime/directmap.c +++ b/libc/runtime/directmap.c @@ -31,7 +31,7 @@ noasan struct DirectMap __mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) { if (!IsWindows()) { - return (struct DirectMap){sys_mmap(addr, size, prot, flags, fd, off), + return (struct DirectMap){sys_mmap(addr, size, prot, flags, fd, off, off), kNtInvalidHandleValue}; } else { return sys_mmap_nt(addr, size, prot, flags, diff --git a/libc/runtime/fork.c b/libc/runtime/fork.c index 3199c8469..8f274f015 100644 --- a/libc/runtime/fork.c +++ b/libc/runtime/fork.c @@ -28,14 +28,22 @@ * @asyncsignalsafe */ int fork(void) { - int rc; + axdx_t ad; + int ax, dx; if (!IsWindows()) { - rc = sys_fork(); + ad = sys_fork(); + ax = ad.ax; + dx = ad.dx; + if (IsXnu() && ax != -1) { + /* eax always returned with childs pid */ + /* edx is 0 for parent and 1 for child */ + ax &= dx - 1; + } } else { - rc = sys_fork_nt(); + ax = sys_fork_nt(); } - if (rc == 0) { + if (!ax) { __onfork(); } - return rc; + return ax; } diff --git a/libc/runtime/runtime.mk b/libc/runtime/runtime.mk index fa208100e..4b04a50a3 100644 --- a/libc/runtime/runtime.mk +++ b/libc/runtime/runtime.mk @@ -76,6 +76,10 @@ o/$(MODE)/libc/runtime/winmain.greg.o: \ OVERRIDE_CFLAGS += \ $(NO_MAGIC) +o/$(MODE)/libc/runtime/ftrace.greg.o: \ + OVERRIDE_CFLAGS += \ + -mgeneral-regs-only + LIBC_RUNTIME_LIBS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x))) LIBC_RUNTIME_SRCS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)_SRCS)) LIBC_RUNTIME_HDRS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)_HDRS)) diff --git a/libc/sock/sendfile.c b/libc/sock/sendfile.c index 8bdb3ab3a..fde33bad3 100644 --- a/libc/sock/sendfile.c +++ b/libc/sock/sendfile.c @@ -59,7 +59,7 @@ static ssize_t sendfile_linux2netflix(int outfd, int infd, int64_t offset, sbytes; if (inout_opt_inoffset) { offset = *inout_opt_inoffset; - } else if ((offset = sys_lseek(infd, 0, SEEK_CUR)) == -1) { + } else if ((offset = lseek(infd, 0, SEEK_CUR)) == -1) { return -1; } if ((rc = sys_sendfile_netflix(infd, outfd, offset, uptobytes, NULL, &sbytes, diff --git a/libc/str/memmem.c b/libc/str/memmem.c index c20622e4c..fd307ab21 100644 --- a/libc/str/memmem.c +++ b/libc/str/memmem.c @@ -16,42 +16,8 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/macros.h" -#include "libc/mem/alloca.h" #include "libc/str/str.h" -static void KnuthMorrisPrattInit(ssize_t m, ssize_t *T, const char *W) { - ssize_t i = 2; - ssize_t j = 0; - T[0] = -1; - T[1] = 0; - while (i < m) { - if (W[i - 1] == W[j]) { - T[i++] = j++ + 1; - } else if (j > 0) { - j = T[j]; - } else { - T[i++] = 0; - } - } - T[m] = 0; -} - -static size_t KnuthMorrisPratt(long m, const long *T, const char *W, long n, - const char *S) { - long i = 0, j = 0; - while (i + j < n) { - if (W[i] == S[i + j]) { - i++; - if (i == m) break; - } else { - j = j + i - T[i]; - if (i > 0) i = T[i]; - } - } - return j; -} - /** * Searches for fixed-length substring in memory region. * @@ -61,24 +27,16 @@ static size_t KnuthMorrisPratt(long m, const long *T, const char *W, long n, * @param needlelen is its character count * @return pointer to first result or NULL if not found */ -void *memmem(const void *haystackp, size_t haystacklen, const void *needlep, +void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) { - long *T; - size_t i; - const char *haystack, *needle, *h; - needle = needlep; - haystack = haystackp; - if (needlelen > haystacklen) return NULL; + size_t i, j; if (!needlelen) return haystack; - h = memchr(haystack, *needle, haystacklen); - if (!h || needlelen == 1) return h; - haystacklen -= h - haystack; - if (needlelen < haystacklen && memcmp(h, needle, needlelen) == 0) { - return h; - } else { - T = alloca((needlelen + 1) * sizeof(long)); - KnuthMorrisPrattInit(needlelen, T, needle); - i = KnuthMorrisPratt(needlelen, T, needle, haystacklen, h); - return i < haystacklen ? h + i : NULL; + for (i = 0; i < haystacklen; ++i) { + for (j = 0;; ++j) { + if (j == needlelen) return (/*unconst*/ char *)haystack + i; + if (i + j == haystacklen) break; + if (((char *)needle)[j] != ((char *)haystack)[i + j]) break; + } } + return NULL; } diff --git a/libc/str/strstr.c b/libc/str/strstr.c index cef3d9374..70129c56a 100644 --- a/libc/str/strstr.c +++ b/libc/str/strstr.c @@ -28,5 +28,15 @@ * @see memmem() */ char *strstr(const char *haystack, const char *needle) { - return memmem(haystack, strlen(haystack), needle, strlen(needle)); + size_t i; + for (;;) { + for (i = 0;;) { + if (!needle[i]) return (/*unconst*/ char *)haystack; + if (!haystack[i]) break; + if (needle[i] != haystack[i]) break; + ++i; + } + if (!*haystack++) break; + } + return NULL; } diff --git a/libc/sysv/calls/__sys_fork.s b/libc/sysv/calls/__sys_fork.s deleted file mode 100644 index e9519041f..000000000 --- a/libc/sysv/calls/__sys_fork.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall __sys_fork 0x0020020022002039 globl hidden diff --git a/libc/sysv/calls/__sys_ftruncate.s b/libc/sysv/calls/__sys_ftruncate.s deleted file mode 100644 index 97c57b914..000000000 --- a/libc/sysv/calls/__sys_ftruncate.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall __sys_ftruncate 0x0c90c91e020c904d globl hidden diff --git a/libc/sysv/calls/__sys_gettimeofday.s b/libc/sysv/calls/__sys_gettimeofday.s deleted file mode 100644 index e8dac45c1..000000000 --- a/libc/sysv/calls/__sys_gettimeofday.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall __sys_gettimeofday 0x1a20430742074060 globl hidden diff --git a/libc/sysv/calls/__sys_lseek.s b/libc/sysv/calls/__sys_lseek.s deleted file mode 100644 index e7798e7a1..000000000 --- a/libc/sysv/calls/__sys_lseek.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall __sys_lseek 0x0c70c71de20c7008 globl hidden diff --git a/libc/sysv/calls/__sys_mmap.s b/libc/sysv/calls/__sys_mmap.s deleted file mode 100644 index c331e2e0b..000000000 --- a/libc/sysv/calls/__sys_mmap.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall __sys_mmap 0x0c50c51dd20c5009 globl hidden diff --git a/libc/sysv/calls/__sys_pread.s b/libc/sysv/calls/__sys_pread.s deleted file mode 100644 index 3b5b5d277..000000000 --- a/libc/sysv/calls/__sys_pread.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall __sys_pread 0x0ad0ad1db2099011 globl hidden diff --git a/libc/sysv/calls/__sys_preadv.s b/libc/sysv/calls/__sys_preadv.s deleted file mode 100644 index caeef7a1f..000000000 --- a/libc/sysv/calls/__sys_preadv.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall __sys_preadv 0x12110b121ffff127 globl hidden diff --git a/libc/sysv/calls/__sys_pwrite.s b/libc/sysv/calls/__sys_pwrite.s deleted file mode 100644 index 20ce64e75..000000000 --- a/libc/sysv/calls/__sys_pwrite.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall __sys_pwrite 0x0ae0ae1dc209a012 globl hidden diff --git a/libc/sysv/calls/__sys_pwritev.s b/libc/sysv/calls/__sys_pwritev.s deleted file mode 100644 index dd1d551f5..000000000 --- a/libc/sysv/calls/__sys_pwritev.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall __sys_pwritev 0x12210c122ffff128 globl hidden diff --git a/libc/sysv/calls/__sys_sigprocmask.s b/libc/sysv/calls/__sys_sigprocmask.s deleted file mode 100644 index ac952a20b..000000000 --- a/libc/sysv/calls/__sys_sigprocmask.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall __sys_sigprocmask 0x125030154203000e globl hidden diff --git a/libc/sysv/calls/__sys_sigsuspend.s b/libc/sysv/calls/__sys_sigsuspend.s deleted file mode 100644 index 8ff36b816..000000000 --- a/libc/sysv/calls/__sys_sigsuspend.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall __sys_sigsuspend 0x12606f155206f082 globl hidden diff --git a/libc/sysv/calls/__sys_truncate.s b/libc/sysv/calls/__sys_truncate.s deleted file mode 100644 index 56699c92a..000000000 --- a/libc/sysv/calls/__sys_truncate.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall __sys_truncate 0x0c80c81df20c804c globl hidden diff --git a/libc/sysv/calls/sys_fork.s b/libc/sysv/calls/sys_fork.s new file mode 100644 index 000000000..009440fc7 --- /dev/null +++ b/libc/sysv/calls/sys_fork.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_fork 0x0020020022002039 globl hidden diff --git a/libc/sysv/calls/sys_ftruncate.s b/libc/sysv/calls/sys_ftruncate.s new file mode 100644 index 000000000..952b434c9 --- /dev/null +++ b/libc/sysv/calls/sys_ftruncate.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_ftruncate 0x0c90c91e020c904d globl hidden diff --git a/libc/sysv/calls/sys_gettimeofday.s b/libc/sysv/calls/sys_gettimeofday.s new file mode 100644 index 000000000..d52cbf2fd --- /dev/null +++ b/libc/sysv/calls/sys_gettimeofday.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_gettimeofday 0x1a20430742074060 globl hidden diff --git a/libc/sysv/calls/sys_lseek.s b/libc/sysv/calls/sys_lseek.s new file mode 100644 index 000000000..bcaba4800 --- /dev/null +++ b/libc/sysv/calls/sys_lseek.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_lseek 0x0c70c71de20c7008 globl hidden diff --git a/libc/sysv/calls/sys_mmap.s b/libc/sysv/calls/sys_mmap.s new file mode 100644 index 000000000..c0eea39ac --- /dev/null +++ b/libc/sysv/calls/sys_mmap.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_mmap 0x0c50c51dd20c5009 globl hidden diff --git a/libc/sysv/calls/sys_pread.s b/libc/sysv/calls/sys_pread.s new file mode 100644 index 000000000..597ff1351 --- /dev/null +++ b/libc/sysv/calls/sys_pread.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_pread 0x0ad0ad1db2099011 globl hidden diff --git a/libc/sysv/calls/sys_preadv.s b/libc/sysv/calls/sys_preadv.s new file mode 100644 index 000000000..3a5d2aedd --- /dev/null +++ b/libc/sysv/calls/sys_preadv.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_preadv 0x12110b121ffff127 globl hidden diff --git a/libc/sysv/calls/sys_pwrite.s b/libc/sysv/calls/sys_pwrite.s new file mode 100644 index 000000000..f0dacf330 --- /dev/null +++ b/libc/sysv/calls/sys_pwrite.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_pwrite 0x0ae0ae1dc209a012 globl hidden diff --git a/libc/sysv/calls/sys_pwritev.s b/libc/sysv/calls/sys_pwritev.s new file mode 100644 index 000000000..4092be6ef --- /dev/null +++ b/libc/sysv/calls/sys_pwritev.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_pwritev 0x12210c122ffff128 globl hidden diff --git a/libc/sysv/calls/sys_sigprocmask.s b/libc/sysv/calls/sys_sigprocmask.s new file mode 100644 index 000000000..4603afba1 --- /dev/null +++ b/libc/sysv/calls/sys_sigprocmask.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_sigprocmask 0x125030154203000e globl hidden diff --git a/libc/sysv/calls/sys_sigsuspend.s b/libc/sysv/calls/sys_sigsuspend.s new file mode 100644 index 000000000..a0750958f --- /dev/null +++ b/libc/sysv/calls/sys_sigsuspend.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_sigsuspend 0x12606f155206f082 globl hidden diff --git a/libc/sysv/calls/sys_truncate.s b/libc/sysv/calls/sys_truncate.s new file mode 100644 index 000000000..2822db5bc --- /dev/null +++ b/libc/sysv/calls/sys_truncate.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_truncate 0x0c80c81df20c804c globl hidden diff --git a/libc/sysv/syscalls.sh b/libc/sysv/syscalls.sh index b0421c40e..ef04ee575 100755 --- a/libc/sysv/syscalls.sh +++ b/libc/sysv/syscalls.sh @@ -43,16 +43,16 @@ scall __sys_fstat 0x1b80352272153005 globl hidden # needs __stat2linux() scall __sys_lstat 0x1b90280282154006 globl hidden # needs __stat2linux(); blocked on Android scall sys_poll 0x0d10fc0d120e6007 globl hidden scall sys_ppoll 0xfff06d221ffff10f globl hidden # consider INTON/INTOFF tutorial in examples/unbourne.c -scall __sys_lseek 0x0c70c71de20c7008 globl hidden # netbsd+openbsd:evilpad -scall __sys_mmap 0x0c50c51dd20c5009 globl hidden # netbsd+openbsd:pad +scall sys_lseek 0x0c70c71de20c7008 globl hidden # netbsd+openbsd:evilpad +scall sys_mmap 0x0c50c51dd20c5009 globl hidden # netbsd+openbsd:pad scall sys_msync 0x115100041204101a globl hidden scall sys_mprotect 0x04a04a04a204a00a globl hidden scall sys_munmap 0x049049049204900b globl hidden scall sys_sigaction 0x15402e1a0202e00d globl hidden # rt_sigaction on Lunix; it's complicated on NetBSD -scall __sys_sigprocmask 0x125030154203000e globl hidden # a.k.a. rt_sigprocmask, openbsd:byvalue +scall sys_sigprocmask 0x125030154203000e globl hidden # a.k.a. rt_sigprocmask, openbsd:byvalue scall sys_ioctl 0x0360360362036010 globl hidden -scall __sys_pread 0x0ad0ad1db2099011 globl hidden # a.k.a. pread64; netbsd+openbsd:pad -scall __sys_pwrite 0x0ae0ae1dc209a012 globl hidden # a.k.a. pwrite64; netbsd+openbsd:pad +scall sys_pread 0x0ad0ad1db2099011 globl hidden # a.k.a. pread64; netbsd+openbsd:pad +scall sys_pwrite 0x0ae0ae1dc209a012 globl hidden # a.k.a. pwrite64; netbsd+openbsd:pad scall sys_readv 0x0780780782078013 globl hidden scall sys_writev 0x0790790792079014 globl hidden scall sys_access 0x0210210212021015 globl hidden @@ -91,7 +91,7 @@ scall __sys_getpeername 0x01f01f08d201f034 globl hidden scall sys_socketpair 0x0870870872087035 globl hidden scall sys_setsockopt 0x0690690692069036 globl hidden scall sys_getsockopt 0x0760760762076037 globl hidden -scall __sys_fork 0x0020020022002039 globl hidden # xnu needs eax=~-edx b/c eax always holds pid and edx is 0 for parent and 1 for child +scall sys_fork 0x0020020022002039 globl hidden # xnu needs eax&=~-edx bc eax always holds pid and edx is 0 for parent and 1 for child #scall vfork 0x042042042204203a globl # this syscall is from the moon so we implement it by hand in libc/calls/hefty/vfork.S scall sys_posix_spawn 0xfffffffff20f4fff globl hidden # good luck figuring out how xnu defines this scall __sys_execve 0x03b03b03b203b03b globl hidden @@ -116,8 +116,8 @@ scall sys_fcntl 0x05c05c05c205c048 globl hidden scall sys_flock 0x0830830832083049 globl hidden scall sys_fsync 0x05f05f05f205f04a globl hidden scall sys_fdatasync 0x0f105f22620bb04b globl hidden # fsync() on openbsd -scall __sys_truncate 0x0c80c81df20c804c globl hidden # netbsd+openbsd:pad -scall __sys_ftruncate 0x0c90c91e020c904d globl hidden # netbsd+openbsd:pad +scall sys_truncate 0x0c80c81df20c804c globl hidden # netbsd+openbsd:pad +scall sys_ftruncate 0x0c90c91e020c904d globl hidden # netbsd+openbsd:pad scall sys_getcwd 0x128130146ffff04f globl hidden scall sys_chdir 0x00c00c00c200c050 globl hidden scall sys_fchdir 0x00d00d00d200d051 globl hidden @@ -135,7 +135,7 @@ scall sys_chown 0x010010010201005c globl hidden # impl. w/ fchownat() @asyncsig scall sys_fchown 0x07b07b07b207b05d globl hidden # @asyncsignalsafe scall sys_lchown 0x1130fe0fe216c05e globl hidden # impl. w/ fchownat() scall umask 0x03c03c03c203c05f globl -scall __sys_gettimeofday 0x1a20430742074060 globl hidden # xnu esi/edx=0 +scall sys_gettimeofday 0x1a20430742074060 globl hidden # xnu esi/edx=0 scall sys_getrlimit 0x0c20c20c220c2061 globl hidden scall sys_getrusage 0x1bd0130752075062 globl hidden scall sys_sysinfo 0xfffffffffffff063 globl hidden @@ -163,7 +163,7 @@ scall sys_setresgid 0xfff11c138ffff077 globl hidden # polyfilled for xnu scall getresuid 0xfff119168ffff076 globl # semantics aren't well-defined scall getresgid 0xfff11b169ffff078 globl # semantics aren't well-defined scall sigpending 0x124034034203407f globl -scall __sys_sigsuspend 0x12606f155206f082 globl hidden # openbsd:byvalue +scall sys_sigsuspend 0x12606f155206f082 globl hidden # openbsd:byvalue scall sigaltstack 0x1191200352035083 globl scall sys_mknod 0x1c200e00e200e085 globl hidden scall mknodat 0x1cc14022fffff103 globl # FreeBSD 12+ @@ -302,8 +302,8 @@ scall sys_vmsplice 0xfffffffffffff116 globl hidden scall migrate_pages 0xfffffffffffff100 globl # numa numa yay scall move_pages 0xfffffffffffff117 globl # NOTE: We view Red Hat versions as "epochs" for all distros. #──────────────────────RHEL 5.0 LIMIT──────────────────────── # ←┬─ last distro with gplv2 licensed compiler c. 2007 -scall __sys_preadv 0x12110b121ffff127 globl hidden # ├─ last distro with system v shell script init -scall __sys_pwritev 0x12210c122ffff128 globl hidden # ├─ rob landley unleashes busybox gpl lawsuits +scall sys_preadv 0x12110b121ffff127 globl hidden # ├─ last distro with system v shell script init +scall sys_pwritev 0x12210c122ffff128 globl hidden # ├─ rob landley unleashes busybox gpl lawsuits scall __sys_utimensat 0x1d3054223ffff118 globl hidden # ├─ python modules need this due to pep513 scall sys_fallocate 0xfffffffffffff11d globl hidden # ├─ end of life 2020-11-30 (extended) scall sys_posix_fallocate 0xffffff212fffffff globl hidden # └─ cosmopolitan supports rhel5+ diff --git a/libc/testlib/ezbench.h b/libc/testlib/ezbench.h index 0ec61010f..428b5b746 100644 --- a/libc/testlib/ezbench.h +++ b/libc/testlib/ezbench.h @@ -6,6 +6,8 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) #define EZBENCH(INIT, EXPR) EZBENCH2(#EXPR, INIT, EXPR) + +#ifndef __STRICT_ANSI__ #define EZBENCH2(NAME, INIT, EXPR) \ do { \ uint64_t Control, Speculative, MemoryStrict; \ @@ -22,6 +24,11 @@ __testlib_ezbenchreport(NAME, Speculative - Control, \ MemoryStrict - Control); \ } while (0) +#else +#define EZBENCH2(NAME, INIT, EXPR) \ + do { \ + } while (0) +#endif void __testlib_ezbenchreport(const char *, uint64_t, uint64_t); uint64_t __testlib_ezbenchcontrol(void); diff --git a/libc/testlib/formatint.c b/libc/testlib/formatint.c index ae9350e3a..8967de565 100644 --- a/libc/testlib/formatint.c +++ b/libc/testlib/formatint.c @@ -25,10 +25,10 @@ static size_t sbufi_; static char sbufs_[2][256]; -nodiscard testonly char *testlib_formatint(intmax_t x) { +nodiscard testonly char *testlib_formatint(intptr_t x) { char *str = sbufi_ < ARRAYLEN(sbufs_) ? sbufs_[sbufi_++] : malloc(256); char *p = str; - p += sprintf(p, "%jd\t(or %#jx", x, x); + p += sprintf(p, "%ld\t(or %#lx", x, x); if (0 <= x && x < 256) { p += sprintf(p, " or %#`c", (unsigned char)x); } diff --git a/libc/testlib/formatrange.c b/libc/testlib/formatrange.c index 852db058f..479bfa170 100644 --- a/libc/testlib/formatrange.c +++ b/libc/testlib/formatrange.c @@ -19,6 +19,6 @@ #include "libc/testlib/testlib.h" #include "libc/x/x.h" -nodiscard testonly char *testlib_formatrange(intmax_t beg, intmax_t end) { - return xasprintf("[%#jx,%#jx]", beg, end); +nodiscard testonly char *testlib_formatrange(intptr_t beg, intptr_t end) { + return xasprintf("[%#ld,%#ld]", beg, end); } diff --git a/libc/testlib/testlib.h b/libc/testlib/testlib.h index 6aa48e22f..48ef24e64 100644 --- a/libc/testlib/testlib.h +++ b/libc/testlib/testlib.h @@ -15,7 +15,9 @@ COSMOPOLITAN_C_START_ * Test cases are guaranteed by the linker to be run in order, sorted by * the (SUITE, NAME) tuple passed here. */ -#define TEST(SUITE, NAME) __TEST_PROTOTYPE(SUITE, NAME, __TEST_ARRAY, ) +#define TEST(SUITE, NAME) \ + STATIC_YOINK("__testcase_start"); \ + __TEST_PROTOTYPE(SUITE, NAME, __TEST_ARRAY, ) /** * Declares function that globally modifies program state. @@ -26,7 +28,9 @@ COSMOPOLITAN_C_START_ * temorarilly by the runtime while calling fixture functions. Fixtures * are also guaranteed by the linker to be run in sorted order. */ -#define FIXTURE(SUITE, NAME) __FIXTURE("fixture", SUITE, NAME) +#define FIXTURE(SUITE, NAME) \ + STATIC_YOINK("__fixture_start"); \ + __FIXTURE("fixture", SUITE, NAME) /** * Registers explosive fixture with linker. @@ -35,7 +39,9 @@ COSMOPOLITAN_C_START_ * Cartesian product of groups. That makes this similar to fixture, but * more appropriate for testing pure code (i.e. no syscalls) like math. */ -#define COMBO(GROUP, ENTRY) __FIXTURE("combo", GROUP, ENTRY) +#define COMBO(GROUP, ENTRY) \ + STATIC_YOINK("__combo_start"); \ + __FIXTURE("combo", GROUP, ENTRY) /** * Declares benchmark function. @@ -109,9 +115,8 @@ void TearDown(void); __TEST_NE(expect, __FILE__, __LINE__, __FUNCTION__, #WANT, #GOT, WANT, GOT, \ __VA_ARGS__) -#define ASSERT_BETWEEN(BEG, END, GOT) \ - assertBetween(FILIFU _I(BEG), _I(END), _I(GOT), \ - #BEG " <= " #GOT " <= " #END, true) +#define ASSERT_BETWEEN(BEG, END, GOT) \ + assertBetween(FILIFU BEG, END, GOT, #BEG " <= " #GOT " <= " #END, true) #define ASSERT_STREQ(WANT, GOT) \ assertStringEquals(FILIFU sizeof(*(WANT)), WANT, GOT, #GOT, true) #define ASSERT_STRNE(NOPE, GOT) \ @@ -167,9 +172,8 @@ void TearDown(void); │ cosmopolitan § testing library » assert or log ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ -#define EXPECT_BETWEEN(BEG, END, GOT) \ - assertBetween(FILIFU _I(BEG), _I(END), _I(GOT), \ - #BEG " <= " #GOT " <= " #END, false) +#define EXPECT_BETWEEN(BEG, END, GOT) \ + assertBetween(FILIFU BEG, END, GOT, #BEG " <= " #GOT " <= " #END, false) #define EXPECT_STREQ(WANT, GOT) \ assertStringEquals(FILIFU sizeof(*(WANT)), WANT, GOT, #GOT, false) #define EXPECT_STRNE(NOPE, GOT) \ @@ -233,46 +237,43 @@ void TearDown(void); const char *file; \ int line -#define TESTLIB_ONFAIL(FILE, FUNC) \ - if (g_testlib_shoulddebugbreak) DebugBreak(); \ - testlib_showerror_file = FILE; \ - testlib_showerror_func = FUNC - -#define TESTLIB_SHOWERROR(THUNK, ...) \ - (((typeof(&testlib_showerror_))strongaddr(#THUNK)))(__VA_ARGS__) - #define __TEST_EQ(KIND, FILE, LINE, FUNC, WANTCODE, GOTCODE, WANT, GOT, ...) \ - ({ \ - autotype(GOT) Got = _I(GOT); \ - typeof(Got) Want = _I(WANT); \ - testlib_ontest(); \ + do { \ + intptr_t Got, Want; \ + ++g_testlib_ran; \ + Got = (intptr_t)(GOT); \ + Want = (intptr_t)(WANT); \ if (Want != Got) { \ - TESTLIB_ONFAIL(FILE, FUNC); \ - TESTLIB_SHOWERROR(testlib_showerror_##KIND##_eq, LINE, WANTCODE, \ - GOTCODE, testlib_formatint(_I(Want)), \ - testlib_formatint(_I(Got)), "" __VA_ARGS__); \ + if (g_testlib_shoulddebugbreak) DebugBreak(); \ + testlib_showerror_file = FILE; \ + testlib_showerror_func = FUNC; \ + testlib_showerror_##KIND##_eq(LINE, WANTCODE, GOTCODE, \ + testlib_formatint(Want), \ + testlib_formatint(Got), "" __VA_ARGS__); \ } \ (void)0; \ - }) + } while (0) #define __TEST_NE(KIND, FILE, LINE, FUNC, WANTCODE, GOTCODE, WANT, GOT, ...) \ - ({ \ - autotype(GOT) Got = (GOT); \ - typeof(Got) Want = (WANT); \ - testlib_ontest(); \ + do { \ + intptr_t Got, Want; \ + ++g_testlib_ran; \ + Got = (intptr_t)(GOT); \ + Want = (intptr_t)(WANT); \ if (Want == Got) { \ - TESTLIB_ONFAIL(FILE, FUNC); \ - TESTLIB_SHOWERROR(testlib_showerror_##KIND##_ne, LINE, WANTCODE, \ - GOTCODE, testlib_formatint(_I(Want)), \ - testlib_formatint(_I(Got)), "" __VA_ARGS__); \ + if (g_testlib_shoulddebugbreak) DebugBreak(); \ + testlib_showerror_file = FILE; \ + testlib_showerror_func = FUNC; \ + testlib_showerror_##KIND##_ne(LINE, WANTCODE, GOTCODE, \ + testlib_formatint(Want), \ + testlib_formatint(Got), "" __VA_ARGS__); \ } \ - (void)0; \ - }) + } while (0) #define _TEST2(NAME, WANT, OP, GOT, WANTCODE, OPSTR, GOTCODE, ISFATAL) \ do { \ - autotype(WANT) Want = (WANT); \ - autotype(GOT) Got = (GOT); \ + intptr_t Want = (intptr_t)(WANT); \ + intptr_t Got = (intptr_t)(GOT); \ if (!(Want OP Got)) { \ testlib_showerror(FILIFU NAME, OPSTR, WANTCODE OPSTR GOTCODE, \ testlib_formatint(Want), testlib_formatint(Got)); \ @@ -300,13 +301,25 @@ extern const testfn_t __testcase_start[], __testcase_end[]; extern const struct TestFixture __fixture_start[], __fixture_end[]; extern const struct TestFixture __combo_start[], __combo_end[]; -void testlib_showerror_(int line, const char *wantcode, const char *gotcode, - char *FREED_want, char *FREED_got, const char *fmt, - ...) relegated; +void testlib_showerror_assert_eq(int, const char *, const char *, char *, + char *, const char *, ...) wontreturn; +void testlib_showerror_assert_false(int, const char *, const char *, char *, + char *, const char *, ...) wontreturn; +void testlib_showerror_assert_ne(int, const char *, const char *, char *, + char *, const char *, ...) wontreturn; +void testlib_showerror_assert_true(int, const char *, const char *, char *, + char *, const char *, ...) wontreturn; +void testlib_showerror_expect_eq(int, const char *, const char *, char *, + char *, const char *, ...); +void testlib_showerror_expect_false(int, const char *, const char *, char *, + char *, const char *, ...); +void testlib_showerror_expect_ne(int, const char *, const char *, char *, + char *, const char *, ...); +void testlib_showerror_expect_true(int, const char *, const char *, char *, + char *, const char *, ...); -void testlib_showerror(const char *file, int line, const char *func, - const char *method, const char *symbol, const char *code, - char *v1, char *v2); +void testlib_showerror(const char *, int, const char *, const char *, + const char *, const char *, char *, char *); void thrashcodecache(void); @@ -333,9 +346,9 @@ bool testlib_hexequals(const char *, const void *, size_t) nosideeffect; bool testlib_startswith(size_t, const void *, const void *) nosideeffect; bool testlib_endswith(size_t, const void *, const void *) nosideeffect; bool testlib_contains(size_t, const void *, const void *) nosideeffect; -char *testlib_formatrange(intmax_t, intmax_t) mallocesque; +char *testlib_formatrange(intptr_t, intptr_t) mallocesque; char *testlib_formatstr(size_t, const void *, int) mallocesque; -char *testlib_formatint(intmax_t) mallocesque; +char *testlib_formatint(intptr_t) mallocesque; char *testlib_formatbool(bool); char *testlib_formatfloat(long double) mallocesque; void testlib_formatbinaryashex(const char *, const void *, size_t, char **, @@ -347,9 +360,6 @@ void testlib_incrementfailed(void); void testlib_clearxmmregisters(void); forceinline void testlib_ontest() { - YOINK(__testcase_start); - YOINK(__fixture_start); - YOINK(__combo_start); ++g_testlib_ran; } @@ -358,7 +368,7 @@ forceinline void testlib_onfail2(bool isfatal) { if (isfatal) testlib_abort(); } -forceinline void assertNotEquals(FILIFU_ARGS intmax_t donotwant, intmax_t got, +forceinline void assertNotEquals(FILIFU_ARGS intptr_t donotwant, intptr_t got, const char *gotcode, bool isfatal) { ++g_testlib_ran; if (got != donotwant) return; @@ -369,7 +379,7 @@ forceinline void assertNotEquals(FILIFU_ARGS intmax_t donotwant, intmax_t got, } #define assertLongDoubleGreaterThan(a, b, code, isfatal) \ - ({ \ + do { \ autotype(a) a_ = (a); \ autotype(b) b_ = (b); \ if (a_ <= b_) { \ @@ -378,10 +388,10 @@ forceinline void assertNotEquals(FILIFU_ARGS intmax_t donotwant, intmax_t got, testlib_onfail2(isfatal); \ } \ (void)0; \ - }) + } while (0) #define assertLongDoubleLessThan(a, b, code, isfatal) \ - ({ \ + do { \ autotype(a) a_ = (a); \ autotype(b) b_ = (b); \ if (a_ >= b_) { \ @@ -390,10 +400,10 @@ forceinline void assertNotEquals(FILIFU_ARGS intmax_t donotwant, intmax_t got, testlib_onfail2(isfatal); \ } \ (void)0; \ - }) + } while (0) -forceinline void assertBetween(FILIFU_ARGS intmax_t beg, intmax_t end, - intmax_t got, const char *gotcode, +forceinline void assertBetween(FILIFU_ARGS intptr_t beg, intptr_t end, + intptr_t got, const char *gotcode, bool isfatal) { ++g_testlib_ran; if (beg <= got && got <= end) return; diff --git a/libc/testlib/ugly.h b/libc/testlib/ugly.h index 1f7ed9f08..2a2511bd0 100644 --- a/libc/testlib/ugly.h +++ b/libc/testlib/ugly.h @@ -3,20 +3,15 @@ #include "libc/macros.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) -#if defined(__GNUC__) || defined(__llvm__) -#pragma GCC diagnostic ignored "-Wpointer-to-int-cast" /* j.f.c. */ -#endif -#define _I(x) (TYPE_SIGNED(typeof(x)) ? (intmax_t)(x) : (uintmax_t)(x)) - #define __TEST_ARRAY(S) \ _Section(".piro.relo.sort.testcase.2." #S ",\"aw\",@init_array #") #define __BENCH_ARRAY(S) \ _Section(".piro.relo.sort.bench.2." #S ",\"aw\",@init_array #") -#define __TEST_PROTOTYPE(S, N, A, K) \ - testonly void S##_##N(void); \ - _Alignas(long) const void *const S##_##N##_ptr[] A(S) = {S##_##N}; \ +#define __TEST_PROTOTYPE(S, N, A, K) \ + void S##_##N(void); \ + const void *const S##_##N##_ptr[] A(S) = {S##_##N}; \ testonly K void S##_##N(void) #define __TEST_SECTION(NAME, CONTENT) \ diff --git a/test/libc/calls/fork_test.c b/test/libc/calls/fork_test.c index 5d737c93b..470e5b31b 100644 --- a/test/libc/calls/fork_test.c +++ b/test/libc/calls/fork_test.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" +#include "libc/macros.h" #include "libc/runtime/runtime.h" #include "libc/sysv/consts/map.h" #include "libc/sysv/consts/msync.h" diff --git a/libc/calls/thunks/mmap-sysv.S b/test/libc/calls/getenv_test.c similarity index 79% rename from libc/calls/thunks/mmap-sysv.S rename to test/libc/calls/getenv_test.c index a739c766c..d7cf3abca 100644 --- a/libc/calls/thunks/mmap-sysv.S +++ b/test/libc/calls/getenv_test.c @@ -1,7 +1,7 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ │ │ │ Permission to use, copy, modify, and/or distribute this software for │ │ any purpose with or without fee is hereby granted, provided that the │ @@ -16,15 +16,13 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/macros.h" -.source __FILE__ +#include "libc/calls/calls.h" +#include "libc/runtime/runtime.h" +#include "libc/testlib/testlib.h" -/ Directly calls mmap() on system five host o/s. -sys_mmap: - push %rbp - mov %rsp,%rbp - push %r9 # netbsd+openbsd:pad - call __sys_mmap - leave - ret - .endfn sys_mmap,globl,hidden +TEST(getenv, test) { + putenv("x=y"); + EXPECT_STREQ("y", getenv("x")); + unsetenv("x"); + EXPECT_EQ(NULL, getenv("x")); +} diff --git a/test/libc/fmt/dirname_test.c b/test/libc/fmt/dirname_test.c index 8e39bd175..6128a4cea 100644 --- a/test/libc/fmt/dirname_test.c +++ b/test/libc/fmt/dirname_test.c @@ -23,6 +23,8 @@ #include "libc/testlib/testlib.h" TEST(dirname, test) { + EXPECT_STREQ("/usr/lib", dirname(gc(strdup("/usr/lib/foo.bar")))); + EXPECT_STREQ("/usr", dirname(gc(strdup("/usr/lib")))); EXPECT_STREQ("/usr", dirname(gc(strdup("/usr/lib")))); EXPECT_STREQ("usr", dirname(gc(strdup("usr/lib")))); EXPECT_STREQ("/", dirname(gc(strdup("/usr/")))); diff --git a/test/libc/release/smoke.c b/test/libc/release/smoke.c index 20ce3a98c..d1e1fa5f0 100644 --- a/test/libc/release/smoke.c +++ b/test/libc/release/smoke.c @@ -1,11 +1,14 @@ int main(int argc, char *argv[]) { int rc; + char *s; FILE *f; + s = strdup(argv[0]); f = fopen("/dev/null", "w"); - fprintf(f, "hello world %d\n", argc); + fprintf(f, "hello world %d %s\n", argc, s); fclose(f); rc = system("exit 42"); CHECK_NE(-1, rc); CHECK_EQ(42, WEXITSTATUS(rc)); + free(s); return 0; } diff --git a/test/libc/release/test.mk b/test/libc/release/test.mk index 3a27dcdca..6631b2160 100644 --- a/test/libc/release/test.mk +++ b/test/libc/release/test.mk @@ -20,7 +20,7 @@ o/$(MODE)/test/libc/release/smoke.com.dbg: \ o/$(MODE)/libc/crt/crt.o \ o/$(MODE)/ape/ape.o \ o/$(MODE)/cosmopolitan.a - @ACTION=CC build/compile $(CC) \ + @ACTION=CC $(COMPILE) $(CC) \ -o $@ \ -Os \ -static \ @@ -49,7 +49,7 @@ o/$(MODE)/test/libc/release/smokecxx.com.dbg: \ o/$(MODE)/libc/crt/crt.o \ o/$(MODE)/ape/ape.o \ o/$(MODE)/cosmopolitan.a - @ACTION=CXX build/compile $(CXX) \ + @ACTION=CXX $(COMPILE) $(CXX) \ -o $@ \ -Os \ -static \ @@ -74,7 +74,7 @@ o/$(MODE)/test/libc/release/smokeansi.com.dbg: \ o/$(MODE)/libc/crt/crt.o \ o/$(MODE)/ape/ape.o \ o/$(MODE)/cosmopolitan.a - @ACTION=ANSI build/compile $(CC) \ + @ACTION=ANSI $(COMPILE) $(CC) \ -o $@ \ -Os \ -ansi \ @@ -100,7 +100,7 @@ o/$(MODE)/test/libc/release/smokeclang.com.dbg: \ o/$(MODE)/libc/crt/crt.o \ o/$(MODE)/ape/ape.o \ o/$(MODE)/cosmopolitan.a - @ACTION=CLANG build/compile clang \ + @ACTION=CLANG $(COMPILE) clang \ -o $@ \ -Os \ -static \ @@ -125,4 +125,6 @@ o/$(MODE)/test/libc/release: \ o/$(MODE)/test/libc/release/smokecxx.com \ o/$(MODE)/test/libc/release/smokecxx.com.runs \ o/$(MODE)/test/libc/release/smokeansi.com \ - o/$(MODE)/test/libc/release/smokeansi.com.runs + o/$(MODE)/test/libc/release/smokeansi.com.runs \ + o/$(MODE)/test/libc/release/smokeclang.com \ + o/$(MODE)/test/libc/release/smokeclang.com.runs diff --git a/test/libc/sock/inet_pton_test.c b/test/libc/sock/inet_pton_test.c index b3d0f2a2d..8229b5fde 100644 --- a/test/libc/sock/inet_pton_test.c +++ b/test/libc/sock/inet_pton_test.c @@ -16,7 +16,6 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/bits/progn.internal.h" #include "libc/bits/safemacros.h" #include "libc/sock/sock.h" #include "libc/sysv/consts/af.h" @@ -25,8 +24,8 @@ TEST(inet_pton, testLocalhost) { uint32_t addr; - EXPECT_EQ(htonl(INADDR_LOOPBACK), - PROGN(ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", &addr)), addr)); + ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", &addr)); + EXPECT_EQ(htonl(INADDR_LOOPBACK), addr); } TEST(inet_pton, testBadAddresses) { diff --git a/test/libc/str/memcpy_test.c b/test/libc/str/memcpy_test.c index ff3e6f25d..8a6acb849 100644 --- a/test/libc/str/memcpy_test.c +++ b/test/libc/str/memcpy_test.c @@ -172,12 +172,12 @@ void *MemCpy(void *, const void *, size_t); free(s); \ } while (0) -#define BB(N) \ - do { \ - B(memmove_pure, N); \ - B(memcpy, N); \ - B(MemCpy, N); \ - fprintf(stderr, "\n"); \ +#define BB(N) \ + do { \ + B(memmove_pure, N); \ + B(memcpy, N); \ + B(MemCpy, N); \ + (fprintf)(stderr, "\n"); \ } while (0) BENCH(memcpy, bench) { diff --git a/test/libc/str/memmem_test.c b/test/libc/str/memmem_test.c index 21478b10c..4b2695df0 100644 --- a/test/libc/str/memmem_test.c +++ b/test/libc/str/memmem_test.c @@ -23,20 +23,15 @@ #include "libc/str/str.h" #include "libc/testlib/testlib.h" -void *(*memmemi)(const void *, size_t, const void *, size_t) = memmem; -FIXTURE(memmem, tiny) { - memmemi = tinymemmem; -} - #define MakeMemory(SL) memcpy(malloc(sizeof(SL) - 1), SL, sizeof(SL) - 1) TEST(memmem, test) { char *needle = MakeMemory("abcdefgh"); char *haystk = MakeMemory("acccccccbbbbbbbbabcdefghdddddddd"); - EXPECT_BINEQ(u"abcdefghdddddddd", memmemi(haystk, 32, needle, 8)); + EXPECT_BINEQ(u"abcdefghdddddddd", memmem(haystk, 32, needle, 8)); memcpy(needle, "aaaaaaaa", 8); memcpy(haystk, "acccccccbbbbbbbbaaaaaaaadddddddd", 32); - EXPECT_BINEQ(u"aaaaaaaadddddddd", memmemi(haystk, 32, needle, 8)); + EXPECT_BINEQ(u"aaaaaaaadddddddd", memmem(haystk, 32, needle, 8)); free(haystk); free(needle); } @@ -44,7 +39,7 @@ TEST(memmem, test) { TEST(memmem, testNoMatch) { char *needle = MakeMemory("abcdefzh"); char *haystk = MakeMemory("acccccccbbbbbbbbabcdefghdddddddd"); - EXPECT_EQ(NULL, memmemi(haystk, 32, needle, 8)); + EXPECT_EQ(NULL, memmem(haystk, 32, needle, 8)); free(haystk); free(needle); } @@ -52,7 +47,7 @@ TEST(memmem, testNoMatch) { TEST(memmem, testStartOfMemory) { char *needle = MakeMemory("acccc"); char *haystk = MakeMemory("acccccccbbbbbbbbabcdefghdddddddd"); - EXPECT_EQ(&haystk[0], memmemi(haystk, 32, needle, 5)); + EXPECT_EQ(&haystk[0], memmem(haystk, 32, needle, 5)); free(haystk); free(needle); } @@ -60,7 +55,7 @@ TEST(memmem, testStartOfMemory) { TEST(memmem, testEndOfMemory) { char *needle = MakeMemory("123"); char *haystk = MakeMemory("abc123"); - EXPECT_EQ(&haystk[3], memmemi(haystk, 6, needle, 3)); + EXPECT_EQ(&haystk[3], memmem(haystk, 6, needle, 3)); free(haystk); free(needle); } @@ -68,7 +63,7 @@ TEST(memmem, testEndOfMemory) { TEST(memmem, testCrossesSseRegister) { char *needle = MakeMemory("eeeeeeeeeeeeefffffffffffff"); char *haystk = MakeMemory("eeeeeeeeeeeeeeeeffffffffffffffffrrrrrrrrrrrrrrrr"); - EXPECT_EQ(&haystk[3], memmemi(haystk, 16 * 3, needle, 26)); + EXPECT_EQ(&haystk[3], memmem(haystk, 16 * 3, needle, 26)); free(haystk); free(needle); } @@ -77,7 +72,7 @@ TEST(memmem, testHasNulCharacters) { char *needle = MakeMemory("eeeeeeeeeeeee\0ffffffffffff"); char *haystk = MakeMemory("eeeeeeeeeeeeeeee\0fffffffffffffffrrrrrrrrrrrrrrrr"); - EXPECT_EQ(&haystk[3], memmemi(haystk, 16 * 3, needle, 26)); + EXPECT_EQ(&haystk[3], memmem(haystk, 16 * 3, needle, 26)); free(haystk); free(needle); } @@ -85,7 +80,7 @@ TEST(memmem, testHasNulCharacters) { TEST(memmem, testWeird) { char *needle = MakeMemory("-*-+-+-+-+-+-+-+"); char *haystk = MakeMemory("-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-+"); - EXPECT_EQ(14, (intptr_t)memmemi(haystk, 32, needle, 16) - (intptr_t)haystk); + EXPECT_EQ(14, (intptr_t)memmem(haystk, 32, needle, 16) - (intptr_t)haystk); free(haystk); free(needle); } @@ -93,7 +88,7 @@ TEST(memmem, testWeird) { TEST(memmem, testEmptyNeedle_matchesStartOfHaystack) { char *needle = malloc(0); char *haystk = MakeMemory("-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-+"); - EXPECT_EQ(0, (intptr_t)memmemi(haystk, 32, needle, 0) - (intptr_t)haystk); + EXPECT_EQ(0, (intptr_t)memmem(haystk, 32, needle, 0) - (intptr_t)haystk); free(haystk); free(needle); } @@ -101,8 +96,8 @@ TEST(memmem, testEmptyNeedle_matchesStartOfHaystack) { TEST(memmem, testEmptyHaystack_alwaysReturnsNull) { char *needle = MakeMemory("-*-+-+-+-+-+-+-+"); char *haystk = malloc(0); - EXPECT_EQ(NULL, memmemi(haystk, 0, needle, 16)); - EXPECT_EQ(NULL, memmemi(haystk, 0, needle, 1)); + EXPECT_EQ(NULL, memmem(haystk, 0, needle, 16)); + EXPECT_EQ(NULL, memmem(haystk, 0, needle, 1)); free(haystk); free(needle); } @@ -110,7 +105,11 @@ TEST(memmem, testEmptyHaystack_alwaysReturnsNull) { TEST(memmem, testEmptyHaystackAndNeedle_returnsHaystack) { char *needle = malloc(0); char *haystk = malloc(0); - EXPECT_EQ(haystk, memmemi(haystk, 0, needle, 0)); + EXPECT_EQ(haystk, memmem(haystk, 0, needle, 0)); free(haystk); free(needle); } + +TEST(memmem, testWut) { + ASSERT_STREQ("x", memmem("x", 1, "x", 1)); +} diff --git a/test/libc/str/strstr_test.c b/test/libc/str/strstr_test.c index 82a8f1527..1a4262188 100644 --- a/test/libc/str/strstr_test.c +++ b/test/libc/str/strstr_test.c @@ -32,52 +32,46 @@ char *strstr_kmp(const char *haystak, const char *needle) { return memmem(haystak, strlen(haystak), needle, strlen(needle)); } -char *(*strstri)(const char *, const char *) = strstr_kmp; - -FIXTURE(strstr, sse42_) { - if (X86_HAVE(SSE4_2)) { - strstri = strstr_sse42; - } -} - TEST(strstr, test_emptyString_isFoundAtBeginning) { MAKESTRING(haystack, "abc123def"); - ASSERT_STREQ(&haystack[0], strstri(haystack, gc(strdup("")))); ASSERT_STREQ(&haystack[0], strstr(haystack, gc(strdup("")))); free(haystack); } TEST(strstr, test_notFound) { MAKESTRING(haystack, "abc123def"); - ASSERT_EQ(NULL, strstri(haystack, gc(strdup("xyz")))); ASSERT_EQ(NULL, strstr(haystack, gc(strdup("xyz")))); free(haystack); } TEST(strstr, test_middleOfString) { MAKESTRING(haystack, "abc123def"); - ASSERT_STREQ(&haystack[3], strstri(haystack, gc(strdup("123")))); ASSERT_STREQ(&haystack[3], strstr(haystack, gc(strdup("123")))); free(haystack); } TEST(strstr, test_endOfString) { MAKESTRING(haystack, "abc123def"); - ASSERT_STREQ(&haystack[8], strstri(haystack, gc(strdup("f")))); ASSERT_STREQ(&haystack[8], strstr(haystack, gc(strdup("f")))); free(haystack); } TEST(strstr, test_secondXmmWord) { MAKESTRING(haystack, "eeeeeeeeeeeeeeeebbbbbbbbbbb123"); - ASSERT_STREQ(&haystack[27], strstri(haystack, gc(strdup("123")))); ASSERT_STREQ(&haystack[27], strstr(haystack, gc(strdup("123")))); free(haystack); } TEST(strstr, test_overlapsXmmWords) { MAKESTRING(haystack, "eeeeeeeeeeeeeeeebbbbbbbbbbbbbbb"); - ASSERT_STREQ(&haystack[15], strstri(haystack, gc(strdup("eb")))); ASSERT_STREQ(&haystack[15], strstr(haystack, gc(strdup("eb")))); free(haystack); } + +TEST(strstr, test) { + ASSERT_EQ(NULL, strstr("x86_64-linux-musl-gcc", "clang")); + ASSERT_STREQ("gcc", strstr("x86_64-linux-musl-gcc", "gcc")); + ASSERT_EQ(NULL, strstr("-Wl,--gc-sections", "stack-protector")); + ASSERT_EQ(NULL, strstr("-Wl,--gc-sections", "sanitize")); + ASSERT_STREQ("x", strstr("x", "x")); +} diff --git a/test/libc/str/tpdecode_test.c b/test/libc/str/tpdecode_test.c deleted file mode 100644 index 411951510..000000000 --- a/test/libc/str/tpdecode_test.c +++ /dev/null @@ -1,86 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/bits/bits.h" -#include "libc/bits/progn.internal.h" -#include "libc/bits/safemacros.h" -#include "libc/errno.h" -#include "libc/fmt/bing.internal.h" -#include "libc/limits.h" -#include "libc/runtime/gc.h" -#include "libc/str/str.h" -#include "libc/str/tpdecode.internal.h" -#include "libc/testlib/testlib.h" - -wint_t wc; - -TEST(tpdecode, testEmptyString_consumesNulTerminator) { - wc = 123; - EXPECT_EQ(1, tpdecode("", &wc)); - EXPECT_EQ(0, wc); -} - -TEST(tpdecode, testGlyph) { - EXPECT_EQ(u'→', PROGN(ASSERT_EQ(3, tpdecode("→", &wc)), wc)); - EXPECT_EQ(L'𐌰', PROGN(ASSERT_EQ(4, tpdecode("𐌰𐌱𐌲𐌳", &wc)), wc)); - EXPECT_EQ(u'ち', PROGN(ASSERT_EQ(3, tpdecode("ち", &wc)), wc)); - EXPECT_EQ(u'‱', PROGN(ASSERT_EQ(3, tpdecode("‱", &wc)), wc)); -} - -TEST(tpdecode, testNul_canonicalizesWithFiniteOverlongConsumption) { - EXPECT_EQ('\0', PROGN(ASSERT_EQ(1, tpdecode("\0\0\0\0", &wc)), wc)); - EXPECT_EQ('\0', - PROGN(ASSERT_EQ(2, tpdecode(gc(unbingstr(u"└ÇÇÇÇÇ")), &wc)), wc)); - EXPECT_EQ('\0', - PROGN(ASSERT_EQ(3, tpdecode(gc(unbingstr(u"αÇÇÇÇÇ")), &wc)), wc)); - EXPECT_EQ('\0', - PROGN(ASSERT_EQ(4, tpdecode(gc(unbingstr(u"≡ÇÇÇÇÇ")), &wc)), wc)); - EXPECT_EQ('\0', - PROGN(ASSERT_EQ(5, tpdecode(gc(unbingstr(u"°ÇÇÇÇÇ")), &wc)), wc)); - EXPECT_EQ('\0', - PROGN(ASSERT_EQ(6, tpdecode(gc(unbingstr(u"ⁿÇÇÇÇÇ")), &wc)), wc)); -} - -TEST(tpdecode, testSynchronization_skipsLeadingContinuations) { - EXPECT_EQ('a', - PROGN(EXPECT_EQ(7, tpdecode(gc(unbingstr(u"Ç╗╝╜╛┐a")), &wc)), wc)); -} - -TEST(tpdecode, testSpace) { - EXPECT_EQ(0x20, PROGN(ASSERT_EQ(1, tpdecode(" ", &wc)), wc)); -} - -TEST(tpdecode, testNegativeNumbers) { - EXPECT_EQ(-1, PROGN(ASSERT_EQ(6, tpdecode(gc(unbingstr(u"λ┐┐┐┐┐")), &wc)), - (wchar_t)wc)); - EXPECT_EQ(INT_MIN, - PROGN(ASSERT_EQ(6, tpdecode(gc(unbingstr(u"■ÇÇÇÇÇ")), &wc)), - (wchar_t)wc)); - EXPECT_EQ(0x80000000u, - PROGN(ASSERT_EQ(6, tpdecode(gc(unbingstr(u"■ÇÇÇÇÇ")), &wc)), wc)); - EXPECT_EQ(0xC0000000u, - PROGN(ASSERT_EQ(6, tpdecode(gc(unbingstr(u"λÇÇÇÇÇ")), &wc)), wc)); -} - -TEST(tpdecode, testInvalidEncoding_endOfString) { - EXPECT_EQ(u'�', PROGN(EXPECT_EQ(-1, tpdecode(gc(unbingstr(u"≡")), &wc)), wc)); -} - -TEST(tpdecode, testInvalidEncoding_tooFewContinuations) { - EXPECT_EQ(u'�', PROGN(EXPECT_EQ(-1, tpdecode(gc(unbingstr(u"≡")), &wc)), wc)); -} diff --git a/test/libc/str/tpencode_test.c b/test/libc/str/tpencode_test.c deleted file mode 100644 index 2323380a3..000000000 --- a/test/libc/str/tpencode_test.c +++ /dev/null @@ -1,66 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/bits/bits.h" -#include "libc/bits/progn.internal.h" -#include "libc/bits/safemacros.h" -#include "libc/str/str.h" -#include "libc/str/tpencode.internal.h" -#include "libc/testlib/testlib.h" - -char buf[8]; - -TEST(tpencode, testNul) { - ASSERT_BINEQ(u" ", PROGN(ASSERT_EQ(1, tpencode(buf, 8, 0, false)), buf)); - ASSERT_BINEQ(u" ", PROGN(ASSERT_EQ(1, (tpencode)(buf, 8, 0, false)), buf)); -} - -TEST(tpencode, testSpace) { - ASSERT_BINEQ(u" ", PROGN(ASSERT_EQ(1, tpencode(buf, 8, 0x20, false)), buf)); - ASSERT_BINEQ(u" ", PROGN(ASSERT_EQ(1, (tpencode)(buf, 8, 0x20, false)), buf)); -} - -TEST(tpencode, testGlyph) { - ASSERT_EQ(3, tpencode(buf, 8, u'→', false)); - ASSERT_BINEQ(u"ΓåÆ", buf); - ASSERT_EQ(3, (tpencode)(buf, 8, u'→', false)); - ASSERT_BINEQ(u"ΓåÆ", buf); -} - -TEST(tpencode, testMathematicalNotMuhPolicyDrivenBehavior_negativeOne) { - ASSERT_BINEQ(u"λ┐┐┐┐┐", - PROGN(ASSERT_EQ(6, tpencode(buf, 8, -1, false)), buf)); - ASSERT_BINEQ(u"λ┐┐┐┐┐", - PROGN(ASSERT_EQ(6, (tpencode)(buf, 8, -1, false)), buf)); -} - -TEST(tpencode, testMathematicalNotMuhPolicyDrivenBehavior_twosComplementBane) { - ASSERT_BINEQ(u"■ÇÇÇÇÇ", - PROGN(ASSERT_EQ(6, tpencode(buf, 8, 0x80000000, false)), buf)); - ASSERT_BINEQ(u"■ÇÇÇÇÇ", - PROGN(ASSERT_EQ(6, (tpencode)(buf, 8, 0x80000000, false)), buf)); -} - -TEST(tpencode, testMathematicalNotMuhPolicyDrivenBehavior_nonCanonicalNul) { - ASSERT_BINEQ(u"└Ç", PROGN(ASSERT_EQ(2, tpencode(buf, 8, 0, true)), buf)); - ASSERT_BINEQ(u"└Ç", PROGN(ASSERT_EQ(2, (tpencode)(buf, 8, 0, true)), buf)); -} - -TEST(tpencode, testC1Csi) { - ASSERT_BINEQ(u"┬¢", PROGN(ASSERT_EQ(2, tpencode(buf, 8, 0x9B, false)), buf)); -} diff --git a/third_party/chibicc/test/test.h b/third_party/chibicc/test/test.h index 201b2e902..7d1a35376 100644 --- a/third_party/chibicc/test/test.h +++ b/third_party/chibicc/test/test.h @@ -3,6 +3,9 @@ #include "libc/stdio/stdio.h" #include "libc/str/str.h" +STATIC_YOINK("__mmap"); /* asan needs it */ +STATIC_YOINK("TrackMemoryInterval"); /* asan needs it */ + #define ASSERT(x, y) Assert2(x, y, #y, __FILE__, __LINE__) #define ASSERT128(x, y) Assert128(x, y, #y, __FILE__, __LINE__) diff --git a/third_party/chibicc/test/test.mk b/third_party/chibicc/test/test.mk index 142846f09..13c14ad46 100644 --- a/third_party/chibicc/test/test.mk +++ b/third_party/chibicc/test/test.mk @@ -90,6 +90,9 @@ o/$(MODE)/third_party/chibicc/test/%2.com.dbg: \ $(APE) @$(APELINK) +.PRECIOUS: $(THIRD_PARTY_CHIBICC_TEST_OBJS) +.PRECIOUS: $(THIRD_PARTY_CHIBICC_TEST2_OBJS) + .PHONY: o/$(MODE)/third_party/chibicc/test o/$(MODE)/third_party/chibicc/test: \ $(THIRD_PARTY_CHIBICC_TEST_BINS) \ diff --git a/tool/build/ar.c b/tool/build/ar.c index 8c9652fa2..835ba1380 100644 --- a/tool/build/ar.c +++ b/tool/build/ar.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/alg/arraylist2.internal.h" #include "libc/bits/bits.h" +#include "libc/bits/safemacros.h" #include "libc/calls/calls.h" #include "libc/calls/struct/iovec.h" #include "libc/calls/struct/stat.h" @@ -53,6 +54,11 @@ * directory be a .a prerequisite so archives rebuild on file deletion. */ +struct Args { + size_t n; + char **p; +}; + struct String { size_t i, n; char *p; @@ -95,14 +101,18 @@ static void MakeHeader(struct Header *h, const char *name, int ref, int mode, } int main(int argc, char *argv[]) { + FILE *f; void *elf; + char *line; char *strs; ssize_t rc; + size_t wrote; + size_t remain; struct stat *st; uint32_t outpos; Elf64_Sym *syms; + struct Args args; uint64_t outsize; - char **objectargs; uint8_t *tablebuf; struct iovec iov[7]; const char *symname; @@ -112,7 +122,6 @@ int main(int argc, char *argv[]) { struct String symbols; struct String filenames; struct Header *header1, *header2; - size_t wrote, remain, objectargcount; int *offsets, *modes, *sizes, *names; int i, j, fd, err, name, outfd, tablebufsize; @@ -121,6 +130,25 @@ int main(int argc, char *argv[]) { return 1; } + memset(&args, 0, sizeof(args)); + for (i = 3; i < argc; ++i) { + if (argv[i][0] != '@') { + args.p = realloc(args.p, ++args.n * sizeof(*args.p)); + args.p[args.n - 1] = strdup(argv[i]); + } else { + CHECK_NOTNULL((f = fopen(argv[i] + 1, "r"))); + while ((line = chomp(xgetline(f)))) { + if (!isempty(line)) { + args.p = realloc(args.p, ++args.n * sizeof(*args.p)); + args.p[args.n - 1] = line; + } else { + free(line); + } + } + CHECK_NE(-1, fclose(f)); + } + } + st = xmalloc(sizeof(struct stat)); symbols.i = 0; symbols.n = 4096; @@ -133,32 +161,29 @@ int main(int argc, char *argv[]) { symnames.p = xmalloc(symnames.n * sizeof(int)); outpath = argv[2]; - objectargs = argv + 3; - objectargcount = argc - 3; - modes = xmalloc(sizeof(int) * objectargcount); - names = xmalloc(sizeof(int) * objectargcount); - sizes = xmalloc(sizeof(int) * objectargcount); + modes = xmalloc(sizeof(int) * args.n); + names = xmalloc(sizeof(int) * args.n); + sizes = xmalloc(sizeof(int) * args.n); // load global symbols and populate page cache - for (i = 0; i < objectargcount; ++i) { + for (i = 0; i < args.n; ++i) { TryAgain: - CHECK_NE(-1, (fd = open(objectargs[i], O_RDONLY))); + CHECK_NE(-1, (fd = open(args.p[i], O_RDONLY)), "%s", args.p[i]); CHECK_NE(-1, fstat(fd, st)); CHECK_LT(st->st_size, 0x7ffff000); - if (!st->st_size || S_ISDIR(st->st_mode) || - endswith(objectargs[i], ".pkg")) { + if (!st->st_size || S_ISDIR(st->st_mode) || endswith(args.p[i], ".pkg")) { close(fd); - for (j = i; j + 1 < objectargcount; ++j) { - objectargs[j] = objectargs[j + 1]; + for (j = i; j + 1 < args.n; ++j) { + args.p[j] = args.p[j + 1]; } - --objectargcount; + --args.n; goto TryAgain; } names[i] = filenames.i; sizes[i] = st->st_size; modes[i] = st->st_mode; - CONCAT(&filenames.p, &filenames.i, &filenames.n, basename(objectargs[i]), - strlen(basename(objectargs[i]))); + CONCAT(&filenames.p, &filenames.i, &filenames.n, basename(args.p[i]), + strlen(basename(args.p[i]))); CONCAT(&filenames.p, &filenames.i, &filenames.n, "/\n", 2); CHECK_NE(MAP_FAILED, (elf = mmap(NULL, st->st_size, PROT_READ, MAP_PRIVATE, fd, 0))); @@ -182,7 +207,7 @@ int main(int argc, char *argv[]) { outsize = 0; tablebufsize = 4 + symnames.i * 4; tablebuf = xmalloc(tablebufsize); - offsets = xmalloc(objectargcount * 4); + offsets = xmalloc(args.n * 4); header1 = xmalloc(sizeof(struct Header)); header2 = xmalloc(sizeof(struct Header)); iov[0].iov_base = "!\n"; @@ -199,7 +224,7 @@ int main(int argc, char *argv[]) { outsize += (iov[5].iov_len = 60); iov[6].iov_base = filenames.p; outsize += (iov[6].iov_len = filenames.i); - for (i = 0; i < objectargcount; ++i) { + for (i = 0; i < args.n; ++i) { outsize += outsize & 1; offsets[i] = outsize; outsize += 60; @@ -219,8 +244,8 @@ int main(int argc, char *argv[]) { CHECK_NE(-1, (outfd = open(outpath, O_WRONLY | O_TRUNC | O_CREAT, 0644))); ftruncate(outfd, outsize); if ((outsize = writev(outfd, iov, ARRAYLEN(iov))) == -1) goto fail; - for (i = 0; i < objectargcount; ++i) { - if ((fd = open(objectargs[i], O_RDONLY)) == -1) goto fail; + for (i = 0; i < args.n; ++i) { + if ((fd = open(args.p[i], O_RDONLY)) == -1) goto fail; iov[0].iov_base = "\n"; outsize += (iov[0].iov_len = outsize & 1); iov[1].iov_base = header1; @@ -233,6 +258,8 @@ int main(int argc, char *argv[]) { } close(outfd); + for (i = 0; i < args.n; ++i) free(args.p[i]); + free(args.p); free(header2); free(header1); free(offsets); diff --git a/tool/build/compile.c b/tool/build/compile.c new file mode 100644 index 000000000..519e72307 --- /dev/null +++ b/tool/build/compile.c @@ -0,0 +1,337 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/safemacros.h" +#include "libc/calls/calls.h" +#include "libc/calls/sigbits.h" +#include "libc/calls/struct/sigset.h" +#include "libc/errno.h" +#include "libc/fmt/conv.h" +#include "libc/log/log.h" +#include "libc/mem/mem.h" +#include "libc/runtime/runtime.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/sig.h" +#include "libc/x/x.h" + +#define MANUAL \ + "\ +OVERVIEW\n\ +\n\ + GNU/LLVM Compiler Collection Frontend Frontend\n\ +\n\ +DESCRIPTION\n\ +\n\ + This launches gcc or clang while filtering out\n\ + flags they whine about.\n\ +\n\ +EXAMPLE\n\ +\n\ + compile.com gcc -o program program.c\n\ +\n" + +struct Flags { + size_t n; + char **p; +}; + +struct Command { + size_t n; + char *p; +}; + +bool iscc; +bool isclang; +bool isgcc; +bool wantasan; +bool wantfentry; +bool wantframe; +bool wantnop; +bool wantnopg; +bool wantpg; +bool wantrecord; +bool wantubsan; + +char *cc; +char *colorflag; +char *outdir; +char *outpath; +char ccpath[PATH_MAX]; +int ccversion; + +struct Flags flags; +struct Command command; + +void AddFlag(char *s) { + size_t n; + flags.p = realloc(flags.p, ++flags.n * sizeof(*flags.p)); + flags.p[flags.n - 1] = s; + if (s) { + n = strlen(s); + if (command.n) { + command.p = realloc(command.p, command.n + 1 + n); + command.p[command.n] = ' '; + memcpy(command.p + command.n + 1, s, n); + command.n += 1 + n; + } else { + command.p = realloc(command.p, command.n + n); + memcpy(command.p + command.n, s, n); + command.n += n; + } + } else { + command.p = realloc(command.p, command.n + 1); + command.p[command.n] = '\n'; + command.n += 1; + } +} + +int main(int argc, char *argv[]) { + int i, ws, pid; + sigset_t mask, savemask; + + if (argc == 1) { + write(2, MANUAL, sizeof(MANUAL) - 1); + exit(1); + } + + if (argc == 2 && !strcmp(argv[1], "--do-nothing")) { + exit(0); + } + + if (!isdirectory("o/third_party/gcc")) { + system("third_party/gcc/unbundle.sh"); + } + + cc = argv[1]; + if (!strchr(cc, '/')) { + if (!(cc = commandv(argv[1], ccpath))) exit(127); + } + + ccversion = atoi(firstnonnull(emptytonull(getenv("CCVERSION")), "4")); + isgcc = strstr(basename(cc), "gcc"); + isclang = strstr(basename(cc), "clang"); + iscc = isgcc | isclang; + + for (i = 1; i < argc; ++i) { + if (argv[i][0] != '-') { + AddFlag(argv[i]); + continue; + } + if (!strcmp(argv[i], "-o")) { + AddFlag(argv[i]); + AddFlag((outpath = argv[++i])); + continue; + } + if (iscc) { + AddFlag(argv[i]); + continue; + } + if (!strcmp(argv[i], "-w")) { + AddFlag(argv[i]); + AddFlag("-D__W__"); + } else if (!strcmp(argv[i], "-Oz")) { + if (isclang) { + AddFlag(argv[i]); + } else { + AddFlag("-Os"); + } + } else if (!strcmp(argv[i], "-pg")) { + wantpg = true; + } else if (!strcmp(argv[i], "-x-no-pg")) { + wantnopg = true; + } else if (!strcmp(argv[i], "-mfentry")) { + wantfentry = true; + } else if (!strcmp(argv[i], "-mnop-mcount")) { + wantnop = true; + } else if (!strcmp(argv[i], "-mrecord-mcount")) { + wantrecord = true; + } else if (!strcmp(argv[i], "-fno-omit-frame-pointer")) { + wantframe = true; + } else if (!strcmp(argv[i], "-fomit-frame-pointer")) { + wantframe = false; + } else if (!strcmp(argv[i], "-mno-vzeroupper")) { + if (isgcc) { + AddFlag("-Wa,-msse2avx"); + AddFlag("-D__MNO_VZEROUPPER__"); + } else if (isclang) { + AddFlag("-mllvm"); + AddFlag("-x86-use-vzeroupper=0"); + } + } else if (!strcmp(argv[i], "-msse2avx")) { + if (isgcc) { + AddFlag(argv[i]); + } else if (isclang) { + AddFlag("-Wa,-msse2avx"); + } + } else if (!strcmp(argv[i], "-fsanitize=address")) { + if (isgcc && ccversion >= 6) wantasan = true; + } else if (!strcmp(argv[i], "-fsanitize=undefined")) { + if (isgcc && ccversion >= 6) wantubsan = true; + } else if (!strcmp(argv[i], "-fno-sanitize=address")) { + wantasan = false; + } else if (!strcmp(argv[i], "-fno-sanitize=undefined")) { + wantubsan = false; + } else if (!strcmp(argv[i], "-fno-sanitize=all")) { + wantasan = false; + wantubsan = false; + } else if (startswith(argv[i], "-fsanitize=implicit") && + strstr(argv[i], "integer")) { + if (isgcc) AddFlag(argv[i]); + } else if (startswith(argv[i], "-fvect-cost") || + startswith(argv[i], "-mstringop") || + startswith(argv[i], "-gz") || + strstr(argv[i], "stack-protector") || + strstr(argv[i], "sanitize") || + startswith(argv[i], "-fvect-cost") || + startswith(argv[i], "-fvect-cost")) { + if (isgcc && ccversion >= 6) { + AddFlag(argv[i]); + } + } else if (startswith(argv[i], "-fdiagnostic-color=")) { + colorflag = argv[i]; + } else if (startswith(argv[i], "-R") || + !strcmp(argv[i], "-fsave-optimization-record")) { + if (isclang) AddFlag(argv[i]); + } else if (isclang && + (!strcmp(argv[i], "-gstabs") || !strcmp(argv[i], "-ftrapv") || + !strcmp(argv[i], "-fsignaling-nans") || + !strcmp(argv[i], "-fcx-limited-range") || + !strcmp(argv[i], "-fno-fp-int-builtin-inexact") || + !strcmp(argv[i], "-Wno-unused-but-set-variable") || + !strcmp(argv[i], "-Wunsafe-loop-optimizations") || + !strcmp(argv[i], "-mdispatch-scheduler") || + !strcmp(argv[i], "-ftracer") || + !strcmp(argv[i], "-frounding-math") || + !strcmp(argv[i], "-fmerge-constants") || + !strcmp(argv[i], "-fmodulo-sched") || + !strcmp(argv[i], "-fopt-info-vec") || + !strcmp(argv[i], "-fopt-info-vec-missed") || + !strcmp(argv[i], "-fmodulo-sched-allow-regmoves") || + !strcmp(argv[i], "-freschedule-modulo-scheduled-loops") || + !strcmp(argv[i], "-fipa-pta") || + !strcmp(argv[i], "-fsched2-use-superblocks") || + !strcmp(argv[i], "-fbranch-target-load-optimize") || + !strcmp(argv[i], "-fdelete-dead-exceptions") || + !strcmp(argv[i], "-funsafe-loop-optimizations") || + !strcmp(argv[i], "-mmitigate-rop") || + !strcmp(argv[i], "-fno-align-jumps") || + !strcmp(argv[i], "-fno-align-labels") || + !strcmp(argv[i], "-fno-align-loops") || + !strcmp(argv[i], "-fivopts") || + !strcmp(argv[i], "-fschedule-insns") || + !strcmp(argv[i], "-fno-semantic-interposition") || + !strcmp(argv[i], "-mno-fentry") || + !strcmp(argv[i], "-fversion-loops-for-strides") || + !strcmp(argv[i], "-femit-struct-debug-baseonly") || + !strcmp(argv[i], "-ftree-loop-vectorize") || + !strcmp(argv[i], "-gdescribe-dies") || + !strcmp(argv[i], "-flimit-function-alignment") || + !strcmp(argv[i], "-ftree-loop-im") || + !strcmp(argv[i], "-fno-instrument-functions") || + !strcmp(argv[i], "-fstack-clash-protection") || + !strcmp(argv[i], "-mfpmath=sse+387") || + !strcmp(argv[i], "-Wa,--noexecstack") || + !strcmp(argv[i], "-freg-struct-return") || + !strcmp(argv[i], "-mcall-ms2sysv-xlogues") || + startswith(argv[i], "-ffixed-") || + startswith(argv[i], "-fcall-saved") || + startswith(argv[i], "-fcall-used") || + startswith(argv[i], "-fgcse-") || + strstr(argv[i], "shrink-wrap") || + strstr(argv[i], "schedule-insns2") || + startswith(argv[i], "-fvect-cost-model=") || + startswith(argv[i], "-fsimd-cost-model=") || + startswith(argv[i], "-fopt-info") || + startswith(argv[i], "-mstringop-strategy=") || + startswith(argv[i], "-mpreferred-stack-boundary=") || + strstr(argv[i], "gnu-unique") || + startswith(argv[i], "-Wframe-larger-than=") || + strstr(argv[i], "whole-program") || + startswith(argv[i], "-Wa,--size-check=") || + startswith(argv[i], "-Wa,--listing"))) { + /* ignore flag so clang won't whine */ + } else { + AddFlag(argv[i]); + } + } + + if (iscc) { + if (isclang) { + AddFlag("-fno-integrated-as"); + AddFlag("-Wno-unused-command-line-argument"); + AddFlag("-Wno-incompatible-pointer-types-discards-qualifiers"); + } + AddFlag("-no-canonical-prefixes"); + if (!IsTerminalInarticulate()) { + AddFlag(firstnonnull(colorflag, "-fdiagnostics-color=always")); + } + if (wantpg && !wantnopg) { + AddFlag("-pg"); + AddFlag("-D__PG__"); + if (wantnop && !isclang) { + AddFlag("-mnop-mcount"); + AddFlag("-D__MNOP_MCOUNT__"); + } + if (wantrecord) { + AddFlag("-mrecord-mcount"); + AddFlag("-D__MRECORD_MCOUNT__"); + } + if (wantfentry) { + AddFlag("-mfentry"); + AddFlag("-D__MFENTRY__"); + } + } + if (wantasan) { + AddFlag("-fsanitize=address"); + AddFlag("-D__FSANITIZE_ADDRESS__"); + } + if (wantubsan) { + AddFlag("-fsanitize=undefined"); + AddFlag("-fno-data-sections"); + } + } + + AddFlag(NULL); + + if (outpath) { + outdir = xdirname(outpath); + if (!isdirectory(outdir)) { + makedirs(outdir, 0755); + } + } + + write(2, command.p, command.n); + + sigfillset(&mask); + sigprocmask(SIG_BLOCK, &mask, &savemask); + if ((pid = vfork()) == -1) exit(errno); + if (!pid) { + sigprocmask(SIG_SETMASK, &savemask, NULL); + execv(cc, flags.p); + _exit(127); + } + while (waitpid(pid, &ws, 0) == -1) { + if (errno != EINTR) exit(errno); + } + + if (WIFEXITED(ws)) { + return WEXITSTATUS(ws); + } else { + return 128 + WTERMSIG(ws); + } +} diff --git a/tool/emacs/cosmo-stuff.el b/tool/emacs/cosmo-stuff.el index eeb77c7cc..b8e8acd58 100644 --- a/tool/emacs/cosmo-stuff.el +++ b/tool/emacs/cosmo-stuff.el @@ -174,7 +174,7 @@ (runs (format "o/$m/%s.com.runs TESTARGS=-b" name)) (buns (format "o/$m/test/%s_test.com.runs TESTARGS=-b" name))) (cond ((not (member ext '("c" "cc" "s" "S" "rl" "f"))) - (format "m=%s; make -j8 -O MODE=$m SILENT=0 o/$m/%s" + (format "m=%s; make -j8 -O MODE=$m V=1 o/$m/%s" mode (directory-file-name (file-name-directory @@ -187,7 +187,7 @@ (file-exists-p (format "%s" buddy))) (format (cosmo-join " && " - '("m=%s; n=%s; make -j8 -O o/$m/$n%s.o MODE=$m SILENT=0" + '("m=%s; n=%s; make -j8 -O o/$m/$n%s.o MODE=$m V=1" ;; "bloat o/$m/%s.o | head" ;; "nm -C --size o/$m/%s.o | sort -r" "echo" @@ -199,7 +199,7 @@ (cosmo-join " && " `("m=%s; f=o/$m/%s.com" - ,(concat "make -j8 -O $f MODE=$m SILENT=0") + ,(concat "make -j8 -O $f MODE=$m V=1") "./$f")) mode name)) ((and (file-regular-p this) @@ -210,7 +210,7 @@ (cosmo-join " && " `("m=%s; f=o/$m/%s%s.o" - ,(concat "make -j8 -O $f MODE=$m SILENT=0") + ,(concat "make -j8 -O $f MODE=$m V=1") ;; "nm -C --size $f | sort -r" "echo" "size -A $f | grep '^[.T]' | grep -v 'debug\\|command.line\\|stack' | sort -rnk2" @@ -419,7 +419,7 @@ (error "don't know how to show assembly for non c/c++ source file")) (let* ((default-directory root) (compile-command - (format "make %s SILENT=0 -j8 -O MODE=%s %s %s" + (format "make %s V=1 -j8 -O MODE=%s %s %s" (or extra-make-flags "") mode asm-gcc asm-clang))) (save-buffer) (set-visited-file-modtime (current-time)) @@ -440,8 +440,8 @@ ;; -ffast-math -funsafe-math-optimizations -fsched2-use-superblocks -fjump-tables (cond ((not (eq 0 (logand 8 arg))) (cosmo--assembly (setq arg (logand (lognot 8))) - "SILENT=0 OVERRIDE_COPTS='-fverbose-asm -fsanitize=address'")) - (t (cosmo--assembly arg "SILENT=0 OVERRIDE_COPTS='' CPPFLAGS='-DSTACK_FRAME_UNLIMITED'")))) + "V=1 OVERRIDE_COPTS='-fverbose-asm -fsanitize=address'")) + (t (cosmo--assembly arg "V=1 OVERRIDE_COPTS='' CPPFLAGS='-DSTACK_FRAME_UNLIMITED'")))) (defun cosmo-assembly-native (arg) (interactive "P") @@ -449,11 +449,11 @@ (cond ((not (eq 0 (logand 8 arg))) (cosmo--assembly (setq arg (logand (lognot 8))) - "SILENT=0 CCFLAGS=--verbose COPTS='$(IEEE_MATH)' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' TARGET_ARCH='-march=k8'")) ;; znver2 + "V=1 CCFLAGS=--verbose COPTS='$(IEEE_MATH)' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' TARGET_ARCH='-march=k8'")) ;; znver2 (t (cosmo--assembly arg - "SILENT=0 CCFLAGS=--verbose COPTS='$(MATHEMATICAL) -O3' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' TARGET_ARCH='-march=k8'")))) ;; znver2 + "V=1 CCFLAGS=--verbose COPTS='$(MATHEMATICAL) -O3' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' TARGET_ARCH='-march=k8'")))) ;; znver2 (defun cosmo-assembly-icelake (arg) (interactive "P") @@ -461,15 +461,15 @@ (cond ((not (eq 0 (logand 8 arg))) (cosmo--assembly (setq arg (logand (lognot 8))) - "SILENT=0 CCFLAGS=--verbose COPTS='$(MATHEMATICAL) -O3' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' TARGET_ARCH='-march=icelake-client'")) + "V=1 CCFLAGS=--verbose COPTS='$(MATHEMATICAL) -O3' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' TARGET_ARCH='-march=icelake-client'")) (t (cosmo--assembly arg - "SILENT=0 CCFLAGS=--verbose COPTS='$(MATHEMATICAL) -O3' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' TARGET_ARCH='-march=icelake-client'")))) + "V=1 CCFLAGS=--verbose COPTS='$(MATHEMATICAL) -O3' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' TARGET_ARCH='-march=icelake-client'")))) (defun cosmo-assembly-balanced (arg) (interactive "P") - (cosmo--assembly (or arg 5) "CFLAGS='-O2 -ftrapv' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' SILENT=0")) + (cosmo--assembly (or arg 5) "CFLAGS='-O2 -ftrapv' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' V=1")) (defun cosmo-mca (arg) (interactive "P") diff --git a/tool/viz/bf.c b/tool/viz/bf.c new file mode 100644 index 000000000..5ead78f6d --- /dev/null +++ b/tool/viz/bf.c @@ -0,0 +1,104 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/fmt/itoa.h" +#include "libc/runtime/runtime.h" +#include "libc/str/str.h" +#include "libc/str/tpenc.h" +#include "libc/sysv/consts/o.h" + +/** + * @fileoverview BingFold - A Hexdump Tool + */ + +#define W 64 +#define C 253 + +void bf(int fd) { + ssize_t rc; + uint64_t w; + int c, fg, fg2; + size_t i, n, o; + char ibuf[W], obuf[12 + 1 + W * 6 + 1 + W * (2 + 11) + 11 + 1]; + o = 0; + do { + if ((rc = read(fd, ibuf, W)) == -1) exit(2); + if (rc) { + n = 0; + n += uint64toarray_fixed16(o, obuf + n, 48); + o += rc; + obuf[n++] = ' '; + for (i = 0; i < rc; ++i) { + c = ibuf[i] & 0xff; + w = tpenc(kCp437[c]); + do { + obuf[n++] = w; + } while ((w >>= 8)); + } + for (i = 0; i < W - rc + 1; ++i) { + obuf[n++] = ' '; + } + for (fg = -1, i = 0; i < rc; ++i) { + c = ibuf[i] & 0xff; + if (c < 32) { + fg2 = 237 + c * ((C - 237) / 32.); + } else if (c >= 232) { + fg2 = C + (c - 232) * ((255 - C) / (256. - 232)); + } else { + fg2 = C; + } + if (fg2 != fg) { + fg = fg2; + obuf[n++] = '\e'; + obuf[n++] = '['; + obuf[n++] = '3'; + obuf[n++] = '8'; + obuf[n++] = ';'; + obuf[n++] = '5'; + obuf[n++] = ';'; + n += int64toarray_radix10(o, obuf + n); + obuf[n++] = 'm'; + } + obuf[n++] = "0123456789abcdef"[c >> 4]; + obuf[n++] = "0123456789abcdef"[c & 15]; + /* obuf[n++] = ' '; */ + } + obuf[n++] = '\e'; + obuf[n++] = '['; + obuf[n++] = '0'; + obuf[n++] = 'm'; + obuf[n++] = '\n'; + write(1, obuf, n); + } + } while (rc == W); +} + +int main(int argc, char *argv[]) { + int i, fd; + if (argc > 1) { + for (i = 1; i < argc; ++i) { + if (i > 1) write(1, "\n", 1); + if ((fd = open(argv[i], O_RDONLY)) == -1) exit(1); + bf(fd); + } + } else { + bf(0); + } + return 0; +} diff --git a/tool/viz/lib/formatstringtable-testlib.h b/tool/viz/lib/formatstringtable-testlib.h index 62ee4f445..8fccae854 100644 --- a/tool/viz/lib/formatstringtable-testlib.h +++ b/tool/viz/lib/formatstringtable-testlib.h @@ -46,21 +46,23 @@ EXPECT_MATRIXEQ_(__FILE__, __LINE__, __FUNCTION__, YN, XN, M, #M, WANT, \ StringifyMatrixShort, NULL, NULL, NULL) -#define EXPECT_MATRIXEQ_(FILE, LINE, FUNC, YN, XN, M, MC, WANT, F, ...) \ - do { \ - char *Got; \ - const char *Want; \ - Want = (WANT); \ - Got = F(YN, XN, M, FormatStringTableForAssertion, __VA_ARGS__); \ - if (testlib_strequals(sizeof(char), Want, Got)) { \ - testlib_free(Got); \ - } else { \ - TESTLIB_ONFAIL(FILE, FUNC); \ - TESTLIB_SHOWERROR(testlib_showerror_expect_matrixeq, LINE, "...", MC, \ - testlib_formatstr(sizeof(char), Want, -1), \ - testlib_formatstr(sizeof(char), Got, -1), ""); \ - } \ +#define EXPECT_MATRIXEQ_(FILE, LINE, FUNC, YN, XN, M, MC, WANT, F, ...) \ + do { \ + char *Got; \ + const char *Want; \ + Want = (WANT); \ + Got = F(YN, XN, M, FormatStringTableForAssertion, __VA_ARGS__); \ + if (testlib_strequals(sizeof(char), Want, Got)) { \ + testlib_free(Got); \ + } else { \ + testlib_showerror_expect_matrixeq( \ + LINE, "...", MC, testlib_formatstr(sizeof(char), Want, -1), \ + testlib_formatstr(sizeof(char), Got, -1), ""); \ + } \ } while (0) +void testlib_showerror_expect_matrixeq(int, const char *, const char *, char *, + char *, const char *, ...); + #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_TOOL_VIZ_LIB_FORMATSTRINGTABLE_TESTLIB_H_ */