Make numerous improvements

- Python static hello world now 1.8mb
- Python static fully loaded now 10mb
- Python HTTPS client now uses MbedTLS
- Python REPL now completes import stmts
- Increase stack size for Python for now
- Begin synthesizing posixpath and ntpath
- Restore Python \N{UNICODE NAME} support
- Restore Python NFKD symbol normalization
- Add optimized code path for Intel SHA-NI
- Get more Python unit tests passing faster
- Get Python help() pagination working on NT
- Python hashlib now supports MbedTLS PBKDF2
- Make memcpy/memmove/memcmp/bcmp/etc. faster
- Add Mersenne Twister and Vigna to LIBC_RAND
- Provide privileged __printf() for error code
- Fix zipos opendir() so that it reports ENOTDIR
- Add basic chmod() implementation for Windows NT
- Add Cosmo's best functions to Python cosmo module
- Pin function trace indent depth to that of caller
- Show memory diagram on invalid access in MODE=dbg
- Differentiate stack overflow on crash in MODE=dbg
- Add stb_truetype and tools for analyzing font files
- Upgrade to UNICODE 13 and reduce its binary footprint
- COMPILE.COM now logs resource usage of build commands
- Start implementing basic poll() support on bare metal
- Set getauxval(AT_EXECFN) to GetModuleFileName() on NT
- Add descriptions to strerror() in non-TINY build modes
- Add COUNTBRANCH() macro to help with micro-optimizations
- Make error / backtrace / asan / memory code more unbreakable
- Add fast perfect C implementation of μ-Law and a-Law audio codecs
- Make strtol() functions consistent with other libc implementations
- Improve Linenoise implementation (see also github.com/jart/bestline)
- COMPILE.COM now suppresses stdout/stderr of successful build commands
This commit is contained in:
Justine Tunney 2021-09-27 22:58:51 -07:00
parent fa7b4f5bd1
commit 39bf41f4eb
806 changed files with 77494 additions and 63859 deletions

View file

@ -59,10 +59,9 @@
#
# build/config.mk
SHELL = /bin/sh
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 xnu win7 win10
SANITY := $(shell build/sanitycheck $$PPID)
GNUMAKEFLAGS += --output-sync
SHELL = /bin/sh
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 xnu win7 win10
SANITY := $(shell build/sanitycheck $$PPID)
.SUFFIXES:
.DELETE_ON_ERROR:
@ -169,6 +168,7 @@ include test/libc/runtime/test.mk
include test/libc/sock/test.mk
include test/libc/bits/test.mk
include test/libc/str/test.mk
include test/libc/log/test.mk
include test/libc/unicode/test.mk
include test/libc/calls/test.mk
include test/libc/x/test.mk

View file

@ -5,16 +5,16 @@
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.
above copyright notice & 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.
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
THE AUTHOR BE LIABLE FOR ANY SPECIAL DIRECT INDIRECT, OR EVEN
CONSEQUENTIAL DAMAGE OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS WHETHER IN AN ACTION OF CONTRACT
NEGLIGENCE OR OTHER TORTIOUS ACTION, THAT ARISE OUT OF, OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View file

@ -237,6 +237,7 @@ SECTIONS {
/*BEGIN: nt addressability guarantee */
.text . : {
BYTE(0x90) /* TODO: fix blinkenlights symbol __map_phdrs */
/* Code that needs to be addressable in Real Mode */
*(.text.real)
KEEP(*(SORT_BY_NAME(.sort.text.real.*)))

Binary file not shown.

Binary file not shown.

View file

@ -75,7 +75,7 @@ TARGET_ARCH ?= \
-msse3
PYFLAGS += \
-B
-O1
endif
@ -161,6 +161,7 @@ CONFIG_CCFLAGS += \
TARGET_ARCH ?= \
-msse3
PYFLAGS += \
-O2 \
-B
endif

View file

@ -42,7 +42,6 @@
# ASFLAGS assembler flags (don't use -Wa, frontend prefix)
# TARGET_ARCH microarchitecture flags (e.g. -march=native)
V ?= 1
LC_ALL = C
SOURCE_DATE_EPOCH = 0
@ -70,7 +69,7 @@ GCC = o/third_party/gcc/bin/x86_64-linux-musl-gcc
STRIP = o/third_party/gcc/bin/x86_64-linux-musl-strip
OBJCOPY = o/third_party/gcc/bin/x86_64-linux-musl-objcopy
OBJDUMP = o/third_party/gcc/bin/x86_64-linux-musl-objdump
ADDR2LINE = o/third_party/gcc/bin/x86_64-linux-musl-addr2line
ADDR2LINE = $(shell pwd)/o/third_party/gcc/bin/x86_64-linux-musl-addr2line
COMMA := ,
PWD := $(shell pwd)
@ -78,14 +77,13 @@ IMAGE_BASE_VIRTUAL ?= 0x400000
HELLO := $(shell build/hello)
TMPDIR := $(shell build/findtmp)
SPAWNER := $(shell build/getcompile) -V$(shell build/getccversion $(CC))
COMPILE = $(SPAWNER) $(QUOTA)
COMPILE = $(SPAWNER) $(HARNESSFLAGS) $(QUOTA)
export ADDR2LINE
export LC_ALL
export MODE
export SOURCE_DATE_EPOCH
export TMPDIR
export V
FTRACE = \
-pg
@ -96,7 +94,6 @@ SANITIZER = \
NO_MAGIC = \
-mno-fentry \
-fno-stack-protector \
-fno-sanitize=all \
-fwrapv
OLD_CODE = \
@ -164,11 +161,11 @@ DEFAULT_ASFLAGS = \
DEFAULT_LDFLAGS = \
-static \
-nostdlib \
-m elf_x86_64 \
-melf_x86_64 \
--gc-sections \
--build-id=none \
--no-dynamic-linker \
-z max-page-size=0x1000
-zmax-page-size=0x1000 --cref -Map=$@.map
ZIPOBJ_FLAGS = \
-b$(IMAGE_BASE_VIRTUAL)
@ -208,7 +205,7 @@ cpp.flags = \
$(CONFIG_CPPFLAGS) \
$(CPPFLAGS) \
$(OVERRIDE_CPPFLAGS) \
-include libc/integral/normalize.inc
-includelibc/integral/normalize.inc
copt.flags = \
$(TARGET_ARCH) \

View file

@ -31,8 +31,8 @@ o/%.o: o/%.cc ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx
o/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
o/%.inc: %.h ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) -D__ASSEMBLER__ -P $<
o/%.pkg: ; @$(COMPILE) -APACKAGE -T$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) $(filter %.o,$^)
o/%.h.ok: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.c) -x c -g0 -o $@ $<
o/%.h.okk: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.cxx) -x c++ -g0 -o $@ $<
o/%.h.ok: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.c) -xc -g0 -o $@ $<
o/%.h.okk: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
o/%.greg.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
o/%.zip.o: o/% ; @$(COMPILE) -AZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
@ -61,9 +61,9 @@ o/$(MODE)/%.s: o/$(MODE)/%.i ; @$(COMPILE) -ACOMPILE.i $(COMPILE.i) $(OUTP
o/$(MODE)/%.o: %.cc ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
o/$(MODE)/%.o: o/$(MODE)/%.cc ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
o/$(MODE)/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
o/$(MODE)/%.h.ok: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.c) -x c -g0 -o $@ $<
o/$(MODE)/%.h.okk: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.cxx) -x c++ -g0 -o $@ $<
o/$(MODE)/%.cxx.o: %.c ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) -x c++ $(OUTPUT_OPTION) $<
o/$(MODE)/%.h.ok: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.c) -xc -g0 -o $@ $<
o/$(MODE)/%.h.okk: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
o/$(MODE)/%.cxx.o: %.c ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) -xc++ $(OUTPUT_OPTION) $<
o/$(MODE)/%.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
o/$(MODE)/%.greg.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
o/$(MODE)/%.ansi.o: %.ansi.c ; @$(COMPILE) -AOBJECTIFY.ansi $(OBJECTIFY.ansi.c) $(OUTPUT_OPTION) $<
@ -74,18 +74,19 @@ o/$(MODE)/%.c2x.o: %.c2x.c ; @$(COMPILE) -AOBJECTIFY.c2x $(OBJECTIFY.c2x
o/$(MODE)/%.initabi.o: %.initabi.c ; @$(COMPILE) -AOBJECTIFY.init $(OBJECTIFY.initabi.c) $(OUTPUT_OPTION) $<
o/$(MODE)/%.ncabi.o: %.ncabi.c ; @$(COMPILE) -AOBJECTIFY.nc $(OBJECTIFY.ncabi.c) $(OUTPUT_OPTION) $<
o/$(MODE)/%.real.o: %.c ; @$(COMPILE) -AOBJECTIFY.real $(OBJECTIFY.real.c) $(OUTPUT_OPTION) $<
o/$(MODE)/%.runs: o/$(MODE)/% ; @$(COMPILE) -ACHECK -tT$@ $< $(TESTARGS)
o/$(MODE)/%.pkg: ; @$(COMPILE) -APACKAGE -T$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) $(filter %.o,$^)
o/$(MODE)/%.zip.o: % ; @$(COMPILE) -AZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
o/$(MODE)/%-gcc.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
o/$(MODE)/%-clang.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $< || echo / need $(CLANG) >$@
o/$(MODE)/%-clang.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
o/$(MODE)/%-clang.asm: CC = $(CLANG)
o/$(MODE)/%.o: %.py o/$(MODE)/third_party/python/pyobj
@$(COMPILE) -APYOBJ o/$(MODE)/third_party/python/pyobj $(PYFLAGS) -o $@ $<
o/$(MODE)/%.o: %.py o/$(MODE)/third_party/python/pyobj.com
@$(COMPILE) -APYOBJ o/$(MODE)/third_party/python/pyobj.com $(PYFLAGS) -o $@ $<
o/$(MODE)/%.pyc: %.py o/$(MODE)/third_party/python/pycomp
@$(COMPILE) -APYCOMP o/$(MODE)/third_party/python/pycomp $(PYCFLAGS) -o $@ $<
o/$(MODE)/%.pyc: %.py o/$(MODE)/third_party/python/pycomp.com
@$(COMPILE) -APYCOMP o/$(MODE)/third_party/python/pycomp.com $(PYCFLAGS) -o $@ $<
o/$(MODE)/%.lua: %.lua o/$(MODE)/third_party/lua/luac
@$(COMPILE) -ALUAC -T$@ o/$(MODE)/third_party/lua/luac -s -o $@ $<
o/$(MODE)/%.lua: %.lua o/$(MODE)/third_party/lua/luac.com
@$(COMPILE) -ALUAC o/$(MODE)/third_party/lua/luac.com -s -o $@ $<

View file

@ -16,30 +16,31 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/str/str.h"
static inline noasan size_t strlen_pure_x64(const char *s, size_t i) {
uint64_t w;
for (;; i += 8) {
w = READ64LE(s + i);
if ((w = ~w & (w - 0x0101010101010101) & 0x8080808080808080)) {
return i + ((unsigned)__builtin_ctzll(w) >> 3);
}
}
}
#include "dsp/core/core.h"
/**
* Returns length of NUL-terminated string.
* Compresses 16-bit signed linear audio sample with a-Law.
*
* @param x is clamped to 16-bits of which the top 14 are considered
* @return coded number in range [0..255]
* @see ITU G.711
*/
size_t strlen_pure(const char *s) {
size_t i;
for (i = 0; (uintptr_t)(s + i) & 7; ++i) {
if (!s[i]) return i;
int alaw(int x) {
int a, b, e, i;
if ((a = x) < 0) a = ~a;
a >>= 4;
if (a > 15) {
if ((i = a >> 5)) {
b = (__builtin_clz(i) ^ 31) + 1;
a >>= b;
a -= 16;
a += (b + 1) << 4;
} else {
e = 1;
a -= 16;
a += 16;
}
}
i = strlen_pure_x64(s, i);
assert(!i || s[0]);
assert(!s[i]);
return i;
if (x >= 0) a |= 128;
return a ^ 85;
}

View file

@ -3,23 +3,19 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/**
* @fileoverview Cosmopolitan Digital Signal Processing.
*/
int alaw(int);
int unalaw(int);
int mulaw(int);
int unmulaw(int);
void *double2byte(long, const void *, double, double) vallocesque;
void *byte2double(long, const void *, double, double) vallocesque;
void *dct(float[8][8], float, float, float, float, float);
void *dctjpeg(float[8][8]);
double det3(const double[3][3]) nosideeffect;
void *inv3(double[restrict 3][3], const double[restrict 3][3], double);
void *matmul3(double[restrict 3][3], const double[3][3], const double[3][3]);
void *vmatmul3(double[restrict 3], const double[3], const double[3][3]);
void *matvmul3(double[restrict 3], const double[3][3], const double[3]);
double rgb2stdtv(double) pureconst;
double rgb2lintv(double) pureconst;
double rgb2stdpc(double, double) pureconst;

View file

@ -51,6 +51,9 @@ o/$(MODE)/dsp/core/scalevolume.o: \
OVERRIDE_CFLAGS += \
$(MATHEMATICAL)
o/$(MODE)/dsp/core/alaw.o: \
CC = clang
o/tiny/dsp/core/scalevolume.o: \
OVERRIDE_CFLAGS += \
-Os

View file

@ -1,63 +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.internal.h"
#define BIAS 0x84
// Encodes audio sample with µ-Law.
//
// This is both the highest quality and most widely supported
// telephony codec, whose use was phased out in the 2000's in
// favor of cost-saving GSM audio compression that was so bad
// consumers were willing to pay more cash, for the privilege
// of saving telcos even more money w/ text messaging. Mu Law
// reduces PCM data to half its original size, by diminishing
// audio bands not vocalized by human voice.
//
// @param %edi is pcm sample
// @return %eax is uint8_t encoded sample
mulaw: .leafprologue
.profilable
mov $BIAS,%eax
xor %edx,%edx
test %edi,%edi
js 1f
lea (%edi,%eax),%eax
mov $0xFF,%dl
jmp 2f
1: sub %edi,%eax
mov $0x7F,%dl
2: mov %eax,%esi
or $0xFF,%sil
bsr %esi,%esi
sub $7,%esi
cmp $8,%esi
jge 4f
lea 3(%rdx),%ecx
sar %cl,%eax
and $0xF,%eax
shl $4,%esi
or %esi,%eax
xor %edx,%eax
3: .leafepilogue
4: xor $0x7F,%dl
mov %edx,%eax
jmp 3b
.endfn mulaw,globl
.source __FILE__

40
dsp/core/mulaw.c Normal file
View file

@ -0,0 +1,40 @@
/*-*- 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 "dsp/core/core.h"
/**
* Compresses 16-bit signed linear audio sample with μ-Law.
*
* @param x is clamped to 16-bits of which the top 14 are considered
* @return coded number in range [0..255]
* @see ITU G.711
*/
int mulaw(int x) {
int b, i, a, s, l, h;
a = x < 0 ? (~x >> 2) + 33 : (x >> 2) + 33;
if (a > 8191) a = 8191;
i = a >> 6;
s = i ? (__builtin_clz(i) ^ 31) + 2 : 1;
h = 8 - s;
l = (a >> s) & 15;
l = 15 - l;
b = (h << 4) | l;
if (x >= 0) b |= 128;
return b;
}

38
dsp/core/unalaw.c Normal file
View file

@ -0,0 +1,38 @@
/*-*- 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 "dsp/core/core.h"
/**
* Expands a-Law coded to audio sample.
*
* @param x is coded number masked to range [0..255]
* @return 16-bit signed linear audio sample
* @note generate lut to save 2 cycles
* @see ITU G.711
*/
int unalaw(int x) {
int e, i, m, r;
i = (x ^ 85) & 127;
e = i >> 4;
m = i & 15;
if (e > 0) m += 16;
m = (m << 4) + 8;
if (e > 1) m = m << (e - 1);
return x & 128 ? m : -m;
}

37
dsp/core/unmulaw.c Normal file
View file

@ -0,0 +1,37 @@
/*-*- 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 "dsp/core/core.h"
#include "libc/bits/likely.h"
/**
* Expands μ-Law coded to audio sample.
*
* @param x is coded number masked to range [0..255]
* @return 16-bit signed linear audio sample
* @note generate lut to save 2 cycles
* @see ITU G.711
*/
int unmulaw(int x) {
int e, m, k, s;
e = (~x >> 4) & 7;
m = ~x & 15;
k = 4 << (e + 1);
s = (128 << e) + k * m + k / 2 - 4 * 33;
return x & 128 ? s : -s;
}

View file

@ -7,8 +7,10 @@
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/log/backtrace.internal.h"
#include "libc/log/log.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/stdio/stdio.h"
int main(int argc, char *argv[]) {

View file

@ -51,6 +51,7 @@ EXAMPLES_DIRECTDEPS = \
LIBC_NT_NTDLL \
LIBC_NT_USER32 \
LIBC_NT_WS2_32 \
LIBC_NT_ADVAPI32 \
LIBC_OHMYPLUS \
LIBC_RAND \
LIBC_RUNTIME \
@ -131,6 +132,8 @@ o/$(MODE)/examples/nesemu1.com.dbg: \
$(APE)
@$(APELINK)
o/$(MODE)/examples/nesemu1.o: QUOTA += -M512m
o/$(MODE)/examples/loader.elf: \
o/$(MODE)/examples/loader.o \
examples/loader.lds

View file

@ -14,7 +14,9 @@
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/nt/runtime.h"
#include "libc/rand/rand.h"
#include "libc/rand/xorshift.h"
#include "libc/stdio/stdio.h"
@ -94,14 +96,6 @@ uint64_t knuth(void) {
return a | b << 32;
}
uint64_t vigna(void) {
static uint64_t x;
uint64_t z = (x += 0x9e3779b97f4a7c15);
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
return z ^ (z >> 31);
}
uint64_t rngset64(void) {
static unsigned i;
static uint64_t s;
@ -130,66 +124,97 @@ uint64_t libc(void) {
return x;
}
uint64_t kernel(void) {
uint64_t GetRandom(void) {
uint64_t x;
CHECK_EQ(8, getrandom(&x, 8, GRND_NORDRND));
CHECK_EQ(8, getrandom(&x, 8, 0));
return x;
}
uint64_t hardware(void) {
uint64_t x;
CHECK_EQ(8, getrandom(&x, 8, GRND_NOSYSTEM));
uint32_t python(void) {
#define K 0 // 624 /* wut */
#define N 624
#define M 397
static int index;
static char once;
static uint32_t mt[N];
static const uint32_t mag01[2] = {0, 0x9908b0dfu};
uint32_t y;
int kk;
if (!once) {
char *sp;
ssize_t rc;
uint32_t i, j, k, s[K];
mt[0] = 19650218;
for (i = 1; i < N; i++) {
mt[i] = (1812433253u * (mt[i - 1] ^ (mt[i - 1] >> 30)) + i);
}
if (K) {
for (sp = (char *)s, i = 0; i < sizeof(s); i += rc) {
if ((rc = getrandom(sp + i, sizeof(s) - i, 0)) == -1) {
if (errno != EINTR) abort();
}
}
for (i = 1, j = 0, k = MAX(N, K); k; k--) {
mt[i] =
(mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525u)) + s[j] + j;
if (++i >= N) mt[0] = mt[N - 1], i = 1;
if (++j >= K) j = 0;
}
for (k = N - 1; k; k--) {
mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1566083941u)) - i;
if (++i >= N) mt[0] = mt[N - 1], i = 1;
}
mt[0] = 0x80000000;
explicit_bzero(s, sizeof(s));
}
once = 1;
}
if (index >= N) {
for (kk = 0; kk < N - M; kk++) {
y = (mt[kk] & 0x80000000u) | (mt[kk + 1] & 0x7fffffff);
mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 1];
}
for (; kk < N - 1; kk++) {
y = (mt[kk] & 0x80000000u) | (mt[kk + 1] & 0x7fffffff);
mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 1];
}
y = (mt[N - 1] & 0x80000000u) | (mt[0] & 0x7fffffffu);
mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 1];
index = 0;
}
y = mt[index++];
y ^= y >> 11;
y ^= (y << 7) & 0x9d2c5680u;
y ^= (y << 15) & 0xefc60000u;
y ^= y >> 18;
return y;
#undef M
#undef N
#undef K
}
uint64_t pythonx2(void) {
uint64_t x = python();
x <<= 32;
x |= python();
return x;
}
uint64_t rdrnd(void) {
char cf;
int i = 0;
uint64_t x;
CHECK(X86_HAVE(RDRND));
for (;;) {
asm volatile(CFLAG_ASM("rdrand\t%1")
: CFLAG_CONSTRAINT(cf), "=r"(x)
: /* no inputs */
: "cc");
if (cf) return x;
if (++i < 10) continue;
asm volatile("pause");
i = 0;
}
}
uint64_t rdseed(void) {
char cf;
int i = 0;
uint64_t x;
CHECK(X86_HAVE(RDSEED));
for (;;) {
asm volatile(CFLAG_ASM("rdseed\t%1")
: CFLAG_CONSTRAINT(cf), "=r"(x)
: /* no inputs */
: "cc");
if (cf) return x;
if (++i < 10) continue;
asm volatile("pause");
i = 0;
}
}
const struct Function {
const char *s;
uint64_t (*f)(void);
} kFunctions[] = {
{"ape", ape}, //
{"hardware", hardware}, //
{"getrandom", GetRandom}, //
{"inc", inc}, //
{"kernel", kernel}, //
{"knuth", knuth}, //
{"libc", libc}, //
{"moby", moby}, //
{"mt19937", _mt19937}, //
{"python", pythonx2}, //
{"rand64", rand64}, //
{"rdrand", rdrnd}, //
{"rdrnd", rdrnd}, //
{"rdrand", rdrand}, //
{"rdrnd", rdrand}, //
{"rdseed", rdseed}, //
{"rngset64", rngset64}, //
{"unixv6", unixv6}, //
@ -224,7 +249,7 @@ int main(int argc, char *argv[]) {
break;
case 'c':
case 'n':
count = strtoul(optarg, 0, 0);
count = sizetol(optarg, 1024);
break;
case 'h':
PrintUsage(stdout, EXIT_SUCCESS);

View file

@ -7,8 +7,10 @@
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/nt/process.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
@ -70,6 +72,8 @@ int main(int argc, char *argv[], char **envp) {
unsigned long *auxp;
char fmt[64], **env;
struct AuxiliaryValue *auxinfo;
uint32_t varlen;
char16_t var[PATH_MAX];
printf("\nArguments:\n");
for (i = 0; i < __argc; ++i) {
printf(" ☼ %s\n", argv[i]);

View file

@ -10,11 +10,13 @@
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/fmt/fmt.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/runtime/gc.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/s.h"
#include "libc/x/x.h"
/**
@ -23,16 +25,45 @@
* This demonstrates the more powerful aspects of the printf() DSL.
*/
bool numeric;
const char *DescribeFileType(unsigned mode) {
switch (mode & S_IFMT) {
case S_IFIFO:
return "S_IFIFO"; /* pipe */
case S_IFCHR:
return "S_IFCHR"; /* character device */
case S_IFDIR:
return "S_IFDIR"; /* directory */
case S_IFBLK:
return "S_IFBLK"; /* block device */
case S_IFREG:
return "S_IFREG"; /* regular file */
case S_IFLNK:
return "S_IFLNK"; /* symbolic link */
case S_IFSOCK:
return "S_IFSOCK"; /* socket */
default:
return "wut";
}
}
void PrintFileMetadata(const char *pathname, struct stat *st) {
int fd;
printf("\n%s:", pathname);
CHECK_NE(-1, stat(pathname, st));
if (numeric) {
fd = atoi(pathname);
CHECK_NE(-1, fstat(fd, st), "fd=%d", fd);
} else {
CHECK_NE(-1, stat(pathname, st), "pathname=%s", pathname);
}
printf("\n"
"%-32s%,ld\n"
"%-32s%,ld\n"
"%-32s%#lx\n"
"%-32s%#lx\n"
"%-32s%ld\n"
"%-32s%#o\n"
"%-32s%#o (%s)\n"
"%-32s%d\n"
"%-32s%d\n"
"%-32s%d\n"
@ -46,10 +77,11 @@ void PrintFileMetadata(const char *pathname, struct stat *st) {
"bytes in file", st->st_size, "physical bytes", st->st_blocks * 512,
"device id w/ file", st->st_dev, "inode", st->st_ino,
"hard link count", st->st_nlink, "mode / permissions", st->st_mode,
"owner id", st->st_uid, "group id", st->st_gid, "flags", st->st_flags,
"gen", st->st_gen, "device id (if special)", st->st_rdev, "block size",
st->st_blksize, "access time", _gc(xiso8601(&st->st_atim)),
"modified time", _gc(xiso8601(&st->st_mtim)), "c[omplicated]time",
DescribeFileType(st->st_mode), "owner id", st->st_uid, "group id",
st->st_gid, "flags", st->st_flags, "gen", st->st_gen,
"device id (if special)", st->st_rdev, "block size", st->st_blksize,
"access time", _gc(xiso8601(&st->st_atim)), "modified time",
_gc(xiso8601(&st->st_mtim)), "c[omplicated]time",
_gc(xiso8601(&st->st_ctim)), "birthtime",
_gc(xiso8601(&st->st_birthtim)));
}
@ -58,7 +90,11 @@ int main(int argc, char *argv[]) {
size_t i;
struct stat st;
for (i = 1; i < argc; ++i) {
PrintFileMetadata(argv[i], &st);
if (!strcmp(argv[i], "-n")) {
numeric = true;
} else {
PrintFileMetadata(argv[i], &st);
}
}
return 0;
}

View file

@ -5745,7 +5745,7 @@ retry:
linenoiseSetFreeHintsCallback(free);
linenoiseSetHintsCallback(ShellHint);
linenoiseSetCompletionCallback(ShellCompletion);
if ((p = ezlinenoise("$ ", "unbourne"))) {
if ((p = linenoiseWithHistory("$ ", "unbourne"))) {
nr = min(strlen(p), IBUFSIZ - 2);
memcpy(buf, p, nr);
buf[nr++] = '\n';

View file

@ -16,85 +16,69 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/str/str.h"
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/dce.h"
#include "libc/nexgen32e/x86feature.h"
/**
* Sets memory.
* Returns population count of array.
*
* @param p is memory address
* @param c is masked with 255 and used as repeated byte
* @param n is byte length
* @return p
* @asyncsignalsafe
* @param a is byte sequence
* @return number of bits set to one
* @note 30gbps on Nehalem (Intel 2008+) otherwise 3gbps
*/
void *memset_pure(void *p, int c, size_t n) {
char *b;
size_t _countbits(const void *a, size_t n) {
int i;
size_t t;
unsigned b;
uint64_t x;
b = p;
x = 0x0101010101010101ul * (c & 0xff);
switch (n) {
case 0:
return p;
case 1:
__builtin_memcpy(b, &x, 1);
return p;
case 2:
__builtin_memcpy(b, &x, 2);
return p;
case 3:
__builtin_memcpy(b, &x, 2);
__builtin_memcpy(b + 1, &x, 2);
return p;
case 4:
__builtin_memcpy(b, &x, 4);
return p;
case 5 ... 7:
__builtin_memcpy(b, &x, 4);
__builtin_memcpy(b + n - 4, &x, 4);
return p;
case 8:
__builtin_memcpy(b, &x, 8);
return p;
case 9 ... 16:
__builtin_memcpy(b, &x, 8);
__builtin_memcpy(b + n - 8, &x, 8);
return p;
default:
do {
n -= 16;
__builtin_memcpy(b + n, &x, 8);
asm volatile("" ::: "memory");
__builtin_memcpy(b + n + 8, &x, 8);
} while (n >= 16);
switch (n) {
case 0:
return p;
case 1:
__builtin_memcpy(b, &x, 1);
return p;
case 2:
__builtin_memcpy(b, &x, 2);
return p;
case 3:
__builtin_memcpy(b, &x, 2);
__builtin_memcpy(b + 1, &x, 2);
return p;
case 4:
__builtin_memcpy(b, &x, 4);
return p;
case 5 ... 7:
__builtin_memcpy(b, &x, 4);
__builtin_memcpy(b + n - 4, &x, 4);
return p;
case 8:
__builtin_memcpy(b, &x, 8);
return p;
case 9 ... 15:
__builtin_memcpy(b, &x, 8);
__builtin_memcpy(b + n - 8, &x, 8);
return p;
default:
unreachable;
long Ai, Bi, Ci, Di;
long Ao, Bo, Co, Do;
const char *p, *e;
t = 0;
p = a;
e = p + n;
if (!IsTiny()) {
if (X86_HAVE(POPCNT)) {
while (p + sizeof(long) * 4 <= e) {
__builtin_memcpy(&Ai, p + 000, sizeof(long));
__builtin_memcpy(&Bi, p + 010, sizeof(long));
__builtin_memcpy(&Ci, p + 020, sizeof(long));
__builtin_memcpy(&Di, p + 030, sizeof(long));
asm("popcnt\t%1,%0" : "=r"(Ao) : "r"(Ai) : "cc");
asm("popcnt\t%1,%0" : "=r"(Bo) : "r"(Bi) : "cc");
asm("popcnt\t%1,%0" : "=r"(Co) : "r"(Ci) : "cc");
asm("popcnt\t%1,%0" : "=r"(Do) : "r"(Di) : "cc");
t += Ao + Bo + Co + Do;
p += sizeof(long) * 4;
}
while (p + sizeof(long) <= e) {
__builtin_memcpy(&Ai, p, 8);
asm("popcnt\t%1,%0" : "=r"(Ao) : "rm"(Ai) : "cc");
p += sizeof(long);
t += Ao;
}
} else {
while (p + 8 <= e) {
__builtin_memcpy(&x, p, 8);
x = x - ((x >> 1) & 0x5555555555555555);
x = ((x >> 2) & 0x3333333333333333) + (x & 0x3333333333333333);
x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f;
x = (x + (x >> 32)) & 0xffffffff;
x = x + (x >> 16);
x = (x + (x >> 8)) & 0x7f;
t += x;
p += 8;
}
}
}
while (p < e) {
b = *p++ & 255;
b = b - ((b >> 1) & 0x55);
b = ((b >> 2) & 0x33) + (b & 0x33);
b = (b + (b >> 4)) & 15;
t += b;
}
return t;
}

View file

@ -4,6 +4,7 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
size_t _countbits(const void *, size_t);
unsigned long popcnt(unsigned long) pureconst;
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)

16
libc/bits/xadd.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef COSMOPOLITAN_LIBC_BITS_XADD_H_
#define COSMOPOLITAN_LIBC_BITS_XADD_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define _xadd(p, v) \
({ \
typeof(*(p)) Res; \
autotype(Res) Val = (v); \
asm volatile("xadd\t%0,%1" : "=r"(Res), "+m"(*(p)) : "0"(Val)); \
Res + Val; \
})
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_BITS_XADD_H_ */

View file

@ -17,18 +17,21 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/macros.internal.h"
#include "libc/nt/errors.h"
#include "libc/nt/files.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/synchronization.h"
#include "libc/sysv/errfuns.h"
textwindows int sys_chdir_nt(const char *path) {
uint32_t n;
int e, ms, len;
char16_t path16[PATH_MAX];
char16_t path16[PATH_MAX], var[4];
if ((len = __mkntpath(path, path16)) == -1) return -1;
if (path16[len - 1] != u'\\') {
if (len + 1 + 1 > PATH_MAX) return enametoolong();
if (len && path16[len - 1] != u'\\') {
if (len + 2 > PATH_MAX) return enametoolong();
path16[len + 0] = u'\\';
path16[len + 1] = u'\0';
}
@ -38,7 +41,28 @@ textwindows int sys_chdir_nt(const char *path) {
*/
for (ms = 1;; ms *= 2) {
if (SetCurrentDirectory(path16)) {
return 0;
/*
* Now we need to set a magic environment variable.
*/
if ((n = GetCurrentDirectory(ARRAYLEN(path16), path16))) {
if (n < ARRAYLEN(path16)) {
if (!((path16[0] == '/' && path16[1] == '/') ||
(path16[0] == '\\' && path16[1] == '\\'))) {
var[0] = '=';
var[1] = path16[0];
var[2] = ':';
var[3] = 0;
if (!SetEnvironmentVariable(var, path16)) {
return __winerr();
}
}
return 0;
} else {
return enametoolong();
}
} else {
return __winerr();
}
} else {
e = GetLastError();
if (ms <= 512 &&

View file

@ -32,8 +32,6 @@
* CHECK_NE(-1, chmod("/usr/bin/sudo", 04755)); // setuid bit
* CHECK_NE(-1, chmod("/usr/bin/wall", 02755)); // setgid bit
*
* This works on Windows NT if you ignore the error ;-)
*
* @param pathname must exist
* @param mode contains octal flags (base 8)
* @errors ENOENT, ENOTDIR, ENOSYS

View file

@ -19,6 +19,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/macros.internal.h"
#include "libc/sock/internal.h"
#include "libc/sysv/errfuns.h"
@ -36,6 +37,7 @@
*/
int close(int fd) {
int rc;
if (fd == -1) return 0;
if (fd < 0) return einval();
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = weaken(__zipos_close)(fd);
@ -59,5 +61,6 @@ int close(int fd) {
}
}
__releasefd(fd);
SYSDEBUG("close(%d) -> %d", fd, rc);
return rc;
}

View file

@ -22,8 +22,9 @@
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
static bool AccessCommand(char path[hasatleast PATH_MAX], const char *name,
size_t namelen, size_t pathlen) {
static noasan bool AccessCommand(char path[hasatleast PATH_MAX],
const char *name, size_t namelen,
size_t pathlen) {
if (pathlen + 1 + namelen + 1 + 4 + 1 > PATH_MAX) return -1;
if (pathlen && (path[pathlen - 1] != '/' && path[pathlen - 1] != '\\')) {
path[pathlen] = !IsWindows() ? '/'
@ -40,8 +41,8 @@ static bool AccessCommand(char path[hasatleast PATH_MAX], const char *name,
return false;
}
static bool SearchPath(char path[hasatleast PATH_MAX], const char *name,
size_t namelen) {
static noasan bool SearchPath(char path[hasatleast PATH_MAX], const char *name,
size_t namelen) {
size_t i;
const char *p;
p = firstnonnull(emptytonull(getenv("PATH")), "/bin:/usr/local/bin:/usr/bin");
@ -70,7 +71,7 @@ static bool SearchPath(char path[hasatleast PATH_MAX], const char *name,
* @asyncsignalsafe
* @vforksafe
*/
char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
noasan char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
char *p;
size_t namelen;
int rc, olderr;

View file

@ -33,7 +33,7 @@
#include "libc/time/time.h"
static textwindows int sys_copyfile_nt(const char *src, const char *dst,
int flags) {
int flags) {
int64_t fhsrc, fhdst;
struct NtFileTime accessed, modified;
char16_t src16[PATH_MAX], dst16[PATH_MAX];
@ -99,6 +99,13 @@ static int sys_copyfile(const char *src, const char *dst, int flags) {
/**
* Copies file.
*
* This implementation goes 2x faster than the `cp` command that comes
* included with most systems since we use the newer copy_file_range()
* system call rather than sendfile().
*
* @param flags may have COPYFILE_PRESERVE_TIMESTAMPS, COPYFILE_NOCLOBBER
* @return 0 on success, or -1 w/ errno
*/
int copyfile(const char *src, const char *dst, int flags) {
if (!IsWindows()) {

View file

@ -47,6 +47,7 @@ textwindows int sys_dup_nt(int oldfd, int newfd, int flags) {
if (DuplicateHandle(proc, g_fds.p[oldfd].handle, proc, &g_fds.p[newfd].handle,
0, true, kNtDuplicateSameAccess)) {
g_fds.p[newfd].kind = g_fds.p[oldfd].kind;
g_fds.p[newfd].extra = g_fds.p[oldfd].extra;
g_fds.p[newfd].flags = flags;
return newfd;
} else {

View file

@ -35,7 +35,7 @@ int __ensurefds(int fd) {
n2 = MAX(fd + 1, n1 + (n1 << 1));
if ((p2 = weaken(malloc)(n2 * sizeof(*p1)))) {
memcpy(p2, p1, n1 * sizeof(*p1));
memset(p2 + n1, 0, (n2 - n1) * sizeof(*p1));
bzero(p2 + n1, (n2 - n1) * sizeof(*p1));
if (p1 != g_fds.__init_p && weaken(free)) weaken(free)(p1);
if (cmpxchg(&g_fds.p, p1, p2)) {
g_fds.n = n2;

View file

@ -37,7 +37,7 @@ textwindows int sys_execve_nt(const char *program, char *const argv[],
uint32_t dwExitCode;
struct NtStartupInfo startinfo;
struct NtProcessInformation procinfo;
memset(&startinfo, 0, sizeof(startinfo));
bzero(&startinfo, sizeof(startinfo));
startinfo.cb = sizeof(struct NtStartupInfo);
startinfo.dwFlags = kNtStartfUsestdhandles;
startinfo.hStdInput = g_fds.p[0].handle;

View file

@ -18,8 +18,10 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/log/libfatal.internal.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
@ -44,6 +46,19 @@ int execve(const char *program, char *const argv[], char *const envp[]) {
!__asan_is_valid_strlist(envp))) {
return efault();
}
if (DEBUGSYS) {
__printf("SYS: execve(%s, {", program);
for (i = 0; argv[i]; ++i) {
if (i) __printf(", ");
__printf("%s", argv[i]);
}
__printf("}, {");
for (i = 0; envp[i]; ++i) {
if (i) __printf(", ");
__printf("%s", envp[i]);
}
__printf("})\n");
}
for (i = 3; i < g_fds.n; ++i) {
if (g_fds.p[i].kind != kFdEmpty && (g_fds.p[i].flags & O_CLOEXEC)) {
close(i);

39
libc/calls/fchmodat-nt.c Normal file
View file

@ -0,0 +1,39 @@
/*-*- 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/internal.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/files.h"
textwindows int sys_fchmodat_nt(int dirfd, const char *path, uint32_t mode,
int flags) {
uint32_t attr;
uint16_t path16[PATH_MAX];
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
if ((attr = GetFileAttributes(path16)) != -1) {
if (mode & 0200) {
attr &= ~kNtFileAttributeReadonly;
} else {
attr |= kNtFileAttributeReadonly;
}
if (SetFileAttributes(path16, attr)) {
return 0;
}
}
return __winerr();
}

View file

@ -31,8 +31,6 @@
* CHECK_NE(-1, fchmodat(AT_FDCWD, "o/default/program.com", 0755));
* CHECK_NE(-1, fchmodat(AT_FDCWD, "privatefolder/", 0700));
*
* This works on Windows NT if you ignore the error ;-)
*
* @param path must exist
* @param mode contains octal flags (base 8)
* @param flags can have `AT_SYMLINK_NOFOLLOW`

View file

@ -29,7 +29,7 @@ textwindows int sys_flock_nt(int fd, int op) {
struct NtOverlapped ov;
struct NtByHandleFileInformation info;
if (!__isfdkind(fd, kFdFile)) return ebadf();
memset(&ov, 0, sizeof(ov));
bzero(&ov, sizeof(ov));
if (GetFileInformationByHandle(g_fds.p[fd].handle, &info) &&
((!(op & LOCK_UN) &&
LockFileEx(g_fds.p[fd].handle, op, 0, info.nFileSizeLow,

View file

@ -25,7 +25,7 @@
int sys_fstat_metal(int fd, struct stat *st) {
if (fd < 0) return einval();
if (fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
memset(st, 0, sizeof(*st));
bzero(st, sizeof(*st));
st->st_dev = g_fds.p[fd].handle;
st->st_rdev = g_fds.p[fd].handle;
st->st_nlink = 1;

View file

@ -76,7 +76,7 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
struct NtByHandleFileInformation wst;
if (!st) return efault();
if ((filetype = GetFileType(handle))) {
memset(st, 0, sizeof(*st));
bzero(st, sizeof(*st));
switch (filetype) {
case kNtFileTypeChar:
st->st_mode = S_IFCHR | 0644;

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
@ -41,6 +42,7 @@ int32_t sys_fstat(int32_t fd, struct stat *st) {
__stat2cosmo(st, &ms);
return 0;
} else {
SYSDEBUG("sys_fstat(%d) failed w/ %m", fd);
return -1;
}
}

View file

@ -32,9 +32,7 @@ textwindows int sys_fstatat_nt(int dirfd, const char *path, struct stat *st,
uint16_t path16[PATH_MAX];
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
if ((fh = CreateFile(
path16, kNtFileReadAttributes,
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, NULL,
kNtOpenExisting,
path16, kNtFileReadAttributes, 0, 0, kNtOpenExisting,
kNtFileAttributeNormal | kNtFileFlagBackupSemantics |
((flags & AT_SYMLINK_NOFOLLOW) ? kNtFileFlagOpenReparsePoint
: 0),

View file

@ -34,7 +34,7 @@ textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
struct NtFileTime UserFileTime;
if (!usage) return efault();
if (who == 99) return enosys(); /* @see libc/sysv/consts.sh */
memset(usage, 0, sizeof(*usage));
bzero(usage, sizeof(*usage));
if ((who == RUSAGE_SELF ? GetProcessTimes : GetThreadTimes)(
(who == RUSAGE_SELF ? GetCurrentProcess : GetCurrentThread)(),
&CreationFileTime, &ExitFileTime, &KernelFileTime, &UserFileTime)) {

View file

@ -29,6 +29,6 @@ int sys_gettimeofday_nt(struct timeval *tv, struct timezone *tz) {
struct NtFileTime ft;
GetSystemTimeAsFileTime(&ft);
if (tv) *tv = FileTimeToTimeVal(ft);
if (tz) memset(tz, 0, sizeof(*tz));
if (tz) bzero(tz, sizeof(*tz));
return 0;
}

View file

@ -261,6 +261,7 @@ int sys_execve_nt(const char *, char *const[], char *const[]) hidden;
int sys_faccessat_nt(int, const char *, int, uint32_t) hidden;
int sys_fadvise_nt(int, u64, u64, int) hidden;
int sys_fchdir_nt(int) hidden;
int sys_fchmodat_nt(int, const char *, uint32_t, int) hidden;
int sys_fcntl_nt(int, int, uintptr_t) hidden;
int sys_fdatasync_nt(int) hidden;
int sys_flock_nt(int, int) hidden;

View file

@ -76,7 +76,7 @@ static int ioctl_siocgifconf_sysv(int fd, struct ifconf *ifc) {
fam = p[IsBsd() ? 17 : 16] & 255;
if (fam != AF_INET) continue;
ip = READ32BE(p + 20);
memset(req, 0, sizeof(*req));
bzero(req, sizeof(*req));
memcpy(req->ifr_name, p, 16);
memcpy(&req->ifr_addr, p + 16, 16);
req->ifr_addr.sa_family = fam;

View file

@ -34,7 +34,7 @@ textwindows int ioctl_tcgets_nt(int ignored, struct termios *tio) {
inok = GetConsoleMode((in = g_fds.p[0].handle), &inmode);
outok = GetConsoleMode((out = g_fds.p[1].handle), &outmode);
if (inok | outok) {
memset(tio, 0, sizeof(*tio));
bzero(tio, sizeof(*tio));
if (inok) {
if (inmode & kNtEnableLineInput) tio->c_lflag |= ICANON;
if (inmode & kNtEnableEchoInput) tio->c_lflag |= ECHO;

View file

@ -29,7 +29,7 @@
int ioctl_tcgets_nt(int, struct termios *) hidden;
static int ioctl_tcgets_metal(int fd, struct termios *tio) {
memset(tio, 0, sizeof(*tio));
bzero(tio, sizeof(*tio));
tio->c_iflag = TTYDEF_IFLAG;
tio->c_oflag = TTYDEF_OFLAG;
tio->c_lflag = TTYDEF_LFLAG;

View file

@ -38,7 +38,7 @@ textwindows int ioctl_tiocgwinsz_nt(int fd, struct winsize *ws) {
for (i = 0; i < ARRAYLEN(fds); ++i) {
if (__isfdkind(fds[i], kFdFile) || __isfdkind(fds[i], kFdConsole)) {
if (GetConsoleMode(g_fds.p[fds[i]].handle, &mode)) {
memset(&sbinfo, 0, sizeof(sbinfo));
bzero(&sbinfo, sizeof(sbinfo));
sbinfo.cbSize = sizeof(sbinfo);
if (GetConsoleScreenBufferInfoEx(g_fds.p[fds[i]].handle, &sbinfo)) {
ws->ws_col = sbinfo.srWindow.Right - sbinfo.srWindow.Left + 1;

View file

@ -31,7 +31,9 @@ bool32 isatty(int fd) {
bool32 res;
struct winsize ws;
if (fd >= 0) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
if (__isfdkind(fd, kFdZip)) {
return false;
} else if (IsMetal()) {
return false;
} else if (!IsWindows()) {
err = errno;

View file

@ -19,9 +19,19 @@
#include "libc/log/log.h"
#include "libc/runtime/runtime.h"
bool g_isrunningundermake;
/**
* Returns true if current process was spawned by GNU Make.
*/
bool IsRunningUnderMake(void) {
return !!getenv("MAKEFLAGS");
return g_isrunningundermake;
}
textstartup void g_isrunningundermake_init(void) {
g_isrunningundermake = !!getenv("MAKEFLAGS");
}
const void *const g_isrunningundermake_ctor[] initarray = {
g_isrunningundermake_init,
};

View file

@ -23,6 +23,22 @@
#include "libc/str/utf16.h"
#include "libc/sysv/errfuns.h"
#define APPEND(c) \
do { \
cmdline[k++] = c; \
if (k == ARG_MAX) return e2big(); \
} while (0)
static noasan bool NeedsQuotes(const char *s) {
if (!*s) return true;
do {
if (*s == ' ' || *s == '\t') {
return true;
}
} while (*s++);
return false;
}
/**
* Converts System V argv to Windows-style command line.
*
@ -34,7 +50,6 @@
* @param prog is used as argv[0]
* @param argv is an a NULL-terminated array of UTF-8 strings
* @return freshly allocated lpCommandLine or NULL w/ errno
* @kudos Daniel Colascione for teaching how to quote
* @see libc/runtime/dosargv.c
*/
textwindows noasan int mkntcmdline(char16_t cmdline[ARG_MAX], const char *prog,
@ -43,36 +58,19 @@ textwindows noasan int mkntcmdline(char16_t cmdline[ARG_MAX], const char *prog,
uint64_t w;
wint_t x, y;
int slashes, n;
size_t i, j, k;
bool needsquote;
char16_t cbuf[2];
size_t i, j, k, s;
for (arg = prog, k = i = 0; arg; arg = argv[++i]) {
if (i) {
cmdline[k++] = u' ';
if (k == ARG_MAX) return e2big();
}
needsquote = !arg[0] || arg[strcspn(arg, " \t\n\v\"")];
if (needsquote) {
cmdline[k++] = u'"';
if (k == ARG_MAX) return e2big();
}
for (j = 0;;) {
if (needsquote) {
slashes = 0;
while (arg[j] && arg[j] == '\\') slashes++, j++;
slashes <<= 1;
if (arg[j] == '"') slashes++;
while (slashes--) {
cmdline[k++] = u'\\';
if (k == ARG_MAX) return e2big();
}
}
x = arg[j++] & 0xff;
if (i) APPEND(u' ');
if ((needsquote = NeedsQuotes(arg))) APPEND(u'"');
for (slashes = j = 0;;) {
x = arg[j++] & 255;
if (x >= 0300) {
n = ThomPikeLen(x);
x = ThomPikeByte(x);
while (--n) {
if ((y = arg[j++] & 0xff)) {
if ((y = arg[j++] & 255)) {
x = ThomPikeMerge(x, y);
} else {
x = 0;
@ -81,16 +79,34 @@ textwindows noasan int mkntcmdline(char16_t cmdline[ARG_MAX], const char *prog,
}
}
if (!x) break;
if (!i && x == '/') x = '\\';
w = EncodeUtf16(x);
do {
cmdline[k++] = w;
if (k == ARG_MAX) return e2big();
} while ((w >>= 16));
if (!i && x == '/') {
x = '\\';
}
if (x == '\\') {
++slashes;
} else if (x == '"') {
for (s = 0; s < slashes * 2; ++s) {
APPEND(u'\\');
}
slashes = 0;
APPEND(u'\\');
APPEND(u'"');
} else {
for (s = 0; s < slashes; ++s) {
APPEND(u'\\');
}
slashes = 0;
w = EncodeUtf16(x);
do {
APPEND(w);
} while ((w >>= 16));
}
}
for (s = 0; s < (slashes << needsquote); ++s) {
APPEND(u'\\');
}
if (needsquote) {
cmdline[k++] = u'"';
if (k == ARG_MAX) return e2big();
APPEND(u'"');
}
}
cmdline[k] = u'\0';

View file

@ -25,7 +25,8 @@
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
textwindows int sys_nanosleep_nt(const struct timespec *req, struct timespec *rem) {
textwindows int sys_nanosleep_nt(const struct timespec *req,
struct timespec *rem) {
int64_t millis, hectonanos, relasleep;
if (rem) memcpy(rem, req, sizeof(*rem));
hectonanos = req->tv_sec * 10000000ull + div100int64(req->tv_nsec);
@ -38,6 +39,6 @@ textwindows int sys_nanosleep_nt(const struct timespec *req, struct timespec *re
return eintr();
}
}
if (rem) memset(rem, 0, sizeof(*rem));
if (rem) bzero(rem, sizeof(*rem));
return 0;
}

View file

@ -63,7 +63,7 @@ textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
s = (void *)buffer;
secsize = sizeof(buffer);
privsize = sizeof(privileges);
memset(&privileges, 0, sizeof(privileges));
bzero(&privileges, sizeof(privileges));
mapping.GenericRead = kNtFileGenericRead;
mapping.GenericWrite = kNtFileGenericWrite;
mapping.GenericExecute = kNtFileGenericExecute;

View file

@ -33,6 +33,14 @@ textwindows void ntcontext2linux(ucontext_t *ctx, const struct NtContext *cr) {
ctx->uc_mcontext.rbp = cr->Rbp;
ctx->uc_mcontext.rsp = cr->Rsp;
ctx->uc_mcontext.rip = cr->Rip;
ctx->uc_mcontext.r8 = cr->R8;
ctx->uc_mcontext.r9 = cr->R9;
ctx->uc_mcontext.r10 = cr->R10;
ctx->uc_mcontext.r11 = cr->R11;
ctx->uc_mcontext.r12 = cr->R12;
ctx->uc_mcontext.r13 = cr->R13;
ctx->uc_mcontext.r14 = cr->R14;
ctx->uc_mcontext.r15 = cr->R15;
ctx->uc_mcontext.cs = cr->SegCs;
ctx->uc_mcontext.gs = cr->SegGs;
ctx->uc_mcontext.fs = cr->SegFs;

View file

@ -19,6 +19,7 @@
#include "libc/bits/pushpop.h"
#include "libc/calls/internal.h"
#include "libc/calls/ntspawn.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/macros.internal.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/pageflags.h"
@ -69,8 +70,10 @@ textwindows int ntspawn(
int64_t handle;
size_t blocksize;
struct SpawnBlock *block;
char16_t prog16[PATH_MAX];
rc = -1;
block = NULL;
if (__mkntpath(prog, prog16) == -1) return -1;
blocksize = ROUNDUP(sizeof(*block), FRAMESIZE);
if ((handle = CreateFileMappingNuma(
-1,
@ -83,7 +86,7 @@ textwindows int ntspawn(
blocksize, NULL, kNtNumaNoPreferredNode))) {
if (mkntcmdline(block->cmdline, prog, argv) != -1 &&
mkntenvblock(block->envvars, envp, extravar) != -1) {
if (CreateProcess(NULL, block->cmdline, opt_lpProcessAttributes,
if (CreateProcess(prog16, block->cmdline, opt_lpProcessAttributes,
opt_lpThreadAttributes, bInheritHandles,
dwCreationFlags | kNtCreateUnicodeEnvironment,
block->envvars, opt_lpCurrentDirectory, lpStartupInfo,
@ -92,6 +95,7 @@ textwindows int ntspawn(
} else {
__winerr();
}
SYSDEBUG("CreateProcess(`%S`, `%S`) -> %d", prog16, block->cmdline, rc);
}
} else {
__winerr();

View file

@ -23,7 +23,7 @@
textwindows struct NtOverlapped *offset2overlap(int64_t opt_offset,
struct NtOverlapped *mem) {
if (opt_offset == -1) return NULL;
memset(mem, 0, sizeof(struct NtOverlapped));
bzero(mem, sizeof(struct NtOverlapped));
mem->Pointer = (void *)(uintptr_t)opt_offset;
return mem;
}

View file

@ -52,7 +52,7 @@ textwindows bool32 __onntconsoleevent(uint32_t CtrlType) {
case (uintptr_t)SIG_IGN:
return true;
default:
memset(&info, 0, sizeof(info));
bzero(&info, sizeof(info));
info.si_signo = sig;
((sigaction_f)(_base + rva))(sig, &info, NULL);
__interrupted = true;

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/sysv/consts/f.h"
@ -32,7 +33,7 @@ int sys_openat(int dirfd, const char *file, int flags, unsigned mode) {
* flag. Other times, it return -530 which makes no sense.
*/
if (!IsLinux() || !(flags & O_CLOEXEC) || modernize) {
return __sys_openat(dirfd, file, flags, mode);
d = __sys_openat(dirfd, file, flags, mode);
} else if (once) {
if ((d = __sys_openat(dirfd, file, flags & ~O_CLOEXEC, mode)) != -1) {
e = errno;
@ -54,8 +55,13 @@ int sys_openat(int dirfd, const char *file, int flags, unsigned mode) {
once = true;
} else if (errno > 255) {
once = true;
return sys_openat(dirfd, file, flags, mode);
d = sys_openat(dirfd, file, flags, mode);
}
}
if (d != -1) {
SYSDEBUG("sys_openat(0x%x, %s, %d, %d) -> %d", dirfd, file, flags, mode, d);
} else {
SYSDEBUG("sys_openat(0x%x, %s, %d, %d) -> %m", dirfd, file, flags, mode);
}
return d;
}

View file

@ -24,6 +24,7 @@
#include "libc/log/log.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"

View file

@ -205,7 +205,7 @@ ssize_t readansi(int fd, char *p, size_t n) {
case kCsi1:
if (0x20 <= c && c <= 0x2f) {
t = kCsi2;
} else if (c == '[' && i == 3) {
} else if (c == '[' && (i == 3 || (i == 4 && p[1] == '\e'))) {
/* linux function keys */
} else if (0x40 <= c && c <= 0x7e) {
t = kDone;

View file

@ -29,8 +29,8 @@
#include "libc/str/str.h"
static textwindows noinline int sys_sched_setaffinity_nt(int pid,
uint64_t bitsetsize,
const void *bitset) {
uint64_t bitsetsize,
const void *bitset) {
int rc;
uintptr_t mask;
int64_t handle;

View file

@ -49,12 +49,12 @@
autotype((S2).B) b = (typeof((S2).B))(S1).B; \
autotype((S2).C) c = (typeof((S2).C))(S1).C; \
typeof((S2).D) d; \
memset(&d, 0, sizeof(d)); \
bzero(&d, sizeof(d)); \
memcpy(&d, &((S1).D), MIN(sizeof(d), sizeof((S1).D))); \
(S2).A = a; \
(S2).B = b; \
(S2).C = c; \
memset(&((S2).D), 0, sizeof((S2).D)); \
bzero(&((S2).D), sizeof((S2).D)); \
memcpy(&((S2).D), &d, MIN(sizeof(d), sizeof((S2).D))); \
} while (0);
#endif
@ -217,7 +217,7 @@ int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) {
}
} else {
if (oldact) {
memset(oldact, 0, sizeof(*oldact));
bzero(oldact, sizeof(*oldact));
}
rc = 0;
}

View file

@ -26,6 +26,6 @@
* @asyncsignalsafe
*/
int sigemptyset(sigset_t *set) {
memset(set->__bits, 0, sizeof(set->__bits));
bzero(set->__bits, sizeof(set->__bits));
return 0;
}

View file

@ -124,7 +124,7 @@ void __sigenter_freebsd(int sig, struct siginfo_freebsd *si,
ucontext_t uc;
rva = __sighandrvas[sig & (NSIG - 1)];
if (rva >= kSigactionMinRva) {
memset(&uc, 0, sizeof(uc));
bzero(&uc, sizeof(uc));
if (ctx) {
uc.uc_mcontext.fpregs = &uc.__fpustate;
uc.uc_stack.ss_sp = ctx->uc_stack.ss_sp;
@ -155,6 +155,7 @@ void __sigenter_freebsd(int sig, struct siginfo_freebsd *si,
uc.uc_mcontext.gs = ctx->uc_mcontext.mc_gs;
uc.uc_mcontext.err = ctx->uc_mcontext.mc_err;
uc.uc_mcontext.trapno = ctx->uc_mcontext.mc_trapno;
memcpy(&uc.__fpustate, &ctx->uc_mcontext.mc_fpstate, 512);
}
((sigaction_f)(_base + rva))(sig, (void *)si, &uc);
if (ctx) {
@ -186,6 +187,7 @@ void __sigenter_freebsd(int sig, struct siginfo_freebsd *si,
ctx->uc_mcontext.mc_err = uc.uc_mcontext.err;
ctx->uc_mcontext.mc_rip = uc.uc_mcontext.rip;
ctx->uc_mcontext.mc_rsp = uc.uc_mcontext.rsp;
memcpy(&ctx->uc_mcontext.mc_fpstate, &uc.__fpustate, 512);
}
}
/*

View file

@ -132,8 +132,8 @@ void __sigenter_netbsd(int sig, struct siginfo_netbsd *si,
struct siginfo si2;
rva = __sighandrvas[sig & (NSIG - 1)];
if (rva >= kSigactionMinRva) {
memset(&uc, 0, sizeof(uc));
memset(&si2, 0, sizeof(si2));
bzero(&uc, sizeof(uc));
bzero(&si2, sizeof(si2));
if (si) {
si2.si_signo = si->_signo;
si2.si_code = si->_code;

View file

@ -97,8 +97,8 @@ void __sigenter_openbsd(int sig, struct siginfo_openbsd *si,
struct siginfo si2;
rva = __sighandrvas[sig & (NSIG - 1)];
if (rva >= kSigactionMinRva) {
memset(&uc, 0, sizeof(uc));
memset(&si2, 0, sizeof(si2));
bzero(&uc, sizeof(uc));
bzero(&si2, sizeof(si2));
if (si) {
si2.si_signo = si->si_signo;
si2.si_code = si->si_code;

View file

@ -25,7 +25,7 @@
*/
int sigignore(int sig) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
bzero(&sa, sizeof(sa));
sa.sa_handler = SIG_IGN;
return (sigaction)(sig, &sa, 0);
}

View file

@ -48,7 +48,7 @@ int sigqueue(int pid, int sig, const union sigval value) {
if (IsFreebsd()) {
return sys_sigqueue(pid, sig, value);
} else {
memset(&info, 0, sizeof(info));
bzero(&info, sizeof(info));
info.si_signo = sig;
info.si_code = SI_QUEUE;
info.si_pid = getpid();

View file

@ -1,9 +1,13 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_SYSDEBUG_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_SYSDEBUG_INTERNAL_H_
#include "libc/calls/calls.h"
#include "libc/log/libfatal.internal.h"
#if 0
#define SYSDEBUG(FMT, ...) (dprintf)(2, FMT "\n", ##__VA_ARGS__)
#ifndef DEBUGSYS
#define DEBUGSYS 0
#endif
#if DEBUGSYS
#define SYSDEBUG(FMT, ...) __printf("SYS: " FMT "\n", ##__VA_ARGS__)
#else
#define SYSDEBUG(FMT, ...) (void)0
#endif

View file

@ -41,7 +41,7 @@ int sysinfo(struct sysinfo *info) {
return efault();
}
}
memset(info, 0, sizeof(*info));
bzero(info, sizeof(*info));
if (!IsWindows()) {
rc = sys_sysinfo(info);
} else {

View file

@ -29,7 +29,7 @@ int uname(struct utsname *lool) {
char *out;
size_t i, j, len;
char tmp[sizeof(struct utsname)];
memset(tmp, 0, sizeof(tmp));
bzero(tmp, sizeof(tmp));
if (sys_uname(tmp) != -1) {
out = (char *)lool;
i = 0;
@ -45,7 +45,7 @@ int uname(struct utsname *lool) {
}
return 0;
} else {
memset(lool, 0, sizeof(struct utsname));
bzero(lool, sizeof(struct utsname));
return -1;
}
}

View file

@ -20,12 +20,11 @@
#include "libc/sysv/consts/at.h"
/**
* Deletes file.
* Removes file.
*
* Please note the deletion process has different interesting properties
* on each platform. For example, on System V, if open descriptors exist
* then only the name of the file is removed and it's actually deleted
* later on when appropriate.
* This may be used to delete files but it can't be used to delete
* directories. The exception are symlinks, which this will delete
* however not the linked directory.
*
* @return 0 on success, or -1 w/ errno
* @asyncsignalsafe

View file

@ -18,17 +18,29 @@
*/
#include "libc/calls/internal.h"
#include "libc/errno.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/io.h"
#include "libc/nt/errors.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/win32fileattributedata.h"
#include "libc/nt/struct/win32finddata.h"
#include "libc/nt/synchronization.h"
#include "libc/sysv/consts/at.h"
static textwindows int sys_unlink_nt(const char16_t *path) {
if (DeleteFile(path)) {
return 0;
static textwindows bool IsDirectorySymlink(const char16_t *path) {
int64_t h;
struct NtWin32FindData data;
struct NtWin32FileAttributeData info;
if (GetFileAttributesEx(path, 0, &info) &&
((info.dwFileAttributes & kNtFileAttributeDirectory) &&
(info.dwFileAttributes & kNtFileAttributeReparsePoint)) &&
(h = FindFirstFile(path, &data)) != -1) {
FindClose(h);
return data.dwReserved0 == kNtIoReparseTagSymlink ||
data.dwReserved0 == kNtIoReparseTagMountPoint;
} else {
return __winerr();
return false;
}
}
@ -54,6 +66,11 @@ static textwindows int sys_rmdir_nt(const char16_t *path) {
return -1;
}
static textwindows int sys_unlink_nt(const char16_t *path) {
if (IsDirectorySymlink(path)) return sys_rmdir_nt(path);
return DeleteFile(path) ? 0 : __winerr();
}
textwindows int sys_unlinkat_nt(int dirfd, const char *path, int flags) {
uint16_t path16[PATH_MAX];
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;

View file

@ -84,7 +84,7 @@ textwindows int sys_wait4_nt(int pid, int *opt_out_wstatus, int options,
*opt_out_wstatus = (dwExitCode & 0xff) << 8;
}
if (opt_out_rusage) {
memset(opt_out_rusage, 0, sizeof(*opt_out_rusage));
bzero(opt_out_rusage, sizeof(*opt_out_rusage));
if (GetProcessTimes(g_fds.p[pids[i]].handle, &createfiletime,
&exitfiletime, &kernelfiletime, &userfiletime)) {
opt_out_rusage->ru_utime =

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/wait4.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
@ -37,6 +38,7 @@
*/
int wait4(int pid, int *opt_out_wstatus, int options,
struct rusage *opt_out_rusage) {
int rc, ws;
if (IsAsan() &&
((opt_out_wstatus &&
!__asan_is_valid(opt_out_wstatus, sizeof(*opt_out_wstatus))) ||
@ -44,9 +46,13 @@ int wait4(int pid, int *opt_out_wstatus, int options,
!__asan_is_valid(opt_out_rusage, sizeof(*opt_out_rusage))))) {
return efault();
}
ws = 0;
if (!IsWindows()) {
return sys_wait4(pid, opt_out_wstatus, options, opt_out_rusage);
rc = sys_wait4(pid, &ws, options, opt_out_rusage);
} else {
return sys_wait4_nt(pid, opt_out_wstatus, options, opt_out_rusage);
rc = sys_wait4_nt(pid, &ws, options, opt_out_rusage);
}
SYSDEBUG("waitpid(%d, [0x%x], %d) -> [%d]", pid, ws, options, rc);
if (opt_out_wstatus) *opt_out_wstatus = ws;
return rc;
}

View file

@ -25,7 +25,7 @@ void __winalarm(void *lpArgToCompletionRoutine, uint32_t dwTimerLowValue,
uint32_t dwTimerHighValue) {
int rva;
siginfo_t info;
memset(&info, 0, sizeof(info));
bzero(&info, sizeof(info));
info.si_signo = SIGALRM;
rva = __sighandrvas[SIGALRM];
if (rva >= kSigactionMinRva) {

View file

@ -70,7 +70,7 @@ textwindows unsigned __wincrash(struct NtExceptionPointers *ep) {
default:
return kNtExceptionContinueSearch;
}
memset(&g, 0, sizeof(g));
bzero(&g, sizeof(g));
rva = __sighandrvas[sig];
if (rva >= kSigactionMinRva) {
ntcontext2linux(&g.ctx, ep->ContextRecord);

View file

@ -61,7 +61,7 @@ int ResolveDns(const struct ResolvConf *resolvconf, int af, const char *name,
if (addrsize < kMinSockaddr4Size) return einval();
if (af != AF_INET && af != AF_UNSPEC) return eafnosupport();
if (!resolvconf->nameservers.i) return 0;
memset(&h, 0, sizeof(h));
bzero(&h, sizeof(h));
rc = ebadmsg();
h.id = rand64();
h.bf1 = 1; /* recursion desired */
@ -69,7 +69,7 @@ int ResolveDns(const struct ResolvConf *resolvconf, int af, const char *name,
q.qname = name;
q.qtype = DNS_TYPE_A;
q.qclass = DNS_CLASS_IN;
memset(msg, 0, sizeof(msg));
bzero(msg, sizeof(msg));
SerializeDnsHeader(msg, &h);
if ((n = SerializeDnsQuestion(msg + 12, 500, &q)) == -1) return -1;
if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) return -1;

View file

@ -63,7 +63,7 @@ int ResolveDnsReverse(const struct ResolvConf *resolvconf, int af,
uint16_t rtype, rclass, rdlength;
if (af != AF_INET && af != AF_UNSPEC) return eafnosupport();
if (!resolvconf->nameservers.i) return 0;
memset(&h, 0, sizeof(h));
bzero(&h, sizeof(h));
rc = ebadmsg();
h.id = rand64();
h.bf1 = 1; /* recursion desired */
@ -71,7 +71,7 @@ int ResolveDnsReverse(const struct ResolvConf *resolvconf, int af,
q.qname = name;
q.qtype = DNS_TYPE_PTR;
q.qclass = DNS_CLASS_IN;
memset(msg, 0, sizeof(msg));
bzero(msg, sizeof(msg));
SerializeDnsHeader(msg, &h);
if ((n = SerializeDnsQuestion(msg + 12, 500, &q)) == -1) return -1;
if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) return -1;

View file

@ -13,6 +13,7 @@ COSMOPOLITAN_C_START_
*/
char *GetElfStringTable(const Elf64_Ehdr *, size_t);
char *GetElfStrs(const Elf64_Ehdr *, size_t, size_t *);
Elf64_Sym *GetElfSymbolTable(const Elf64_Ehdr *, size_t, Elf64_Xword *);
bool IsElf64Binary(const Elf64_Ehdr *, size_t);
void CheckElfAddress(const Elf64_Ehdr *, size_t, intptr_t, size_t);

39
libc/elf/getelfstrs.c Normal file
View file

@ -0,0 +1,39 @@
/*-*- 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/elf/def.h"
#include "libc/elf/elf.h"
#include "libc/str/str.h"
char *GetElfStrs(const Elf64_Ehdr *elf, size_t mapsize, size_t *out_size) {
char *name;
Elf64_Half i;
Elf64_Shdr *shdr;
for (i = 0; i < elf->e_shnum; ++i) {
shdr = GetElfSectionHeaderAddress(elf, mapsize, i);
if (shdr->sh_type == SHT_STRTAB) {
name = GetElfSectionName(elf, mapsize,
GetElfSectionHeaderAddress(elf, mapsize, i));
if (name && !strcmp(name, ".strtab")) {
if (out_size) *out_size = shdr->sh_size;
return GetElfSectionAddress(elf, mapsize, shdr);
}
}
}
return 0;
}

View file

@ -24,6 +24,16 @@
/**
* Decodes decimal integer from ASCII string.
*
* atoi 10 22𝑐 7𝑛𝑠
* strtol 10 37𝑐 12𝑛𝑠
* strtoul 10 35𝑐 11𝑛𝑠
* wcstol 10 30𝑐 10𝑛𝑠
* wcstoul 10 30𝑐 10𝑛𝑠
* strtoimax 10 80𝑐 26𝑛𝑠
* strtoumax 10 78𝑐 25𝑛𝑠
* wcstoimax 10 77𝑐 25𝑛𝑠
* wcstoumax 10 76𝑐 25𝑛𝑠
*
* @param s is a non-null nul-terminated string
* @return the decoded signed saturated integer
*/

View file

@ -69,6 +69,7 @@ char *dirname(char *);
char *basename(const char *) nosideeffect;
char *basename_n(const char *, size_t) nosideeffect;
bool isabspath(const char *) paramsnonnull() nosideeffect;
char *stripext(char *);
char *stripexts(char *);
/*───────────────────────────────────────────────────────────────────────────│─╗

View file

@ -391,7 +391,8 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
s = weaken(__fmt_dtoa)(pun.d, 3, prec, &decpt, &sgn, &se);
if (decpt == 9999) {
Format9999:
p = q = memset(special, 0, sizeof(special));
bzero(special, sizeof(special));
p = q = special;
if (sgn) {
*q++ = '-';
} else if (flags & FLAGS_PLUS) {
@ -423,12 +424,10 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
if (flags & FLAGS_ZEROPAD) {
if (sign) PUT(sign);
sign = 0;
do
PUT('0');
do PUT('0');
while (--width > 0);
} else {
do
PUT(' ');
do PUT(' ');
while (--width > 0);
}
}
@ -530,12 +529,10 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
if (flags & FLAGS_ZEROPAD) {
if (sign) PUT(sign);
sign = 0;
do
PUT('0');
do PUT('0');
while (--width > 0);
} else {
do
PUT(' ');
do PUT(' ');
while (--width > 0);
}
}
@ -682,12 +679,10 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
PUT(sign);
sign = 0;
}
do
PUT('0');
do PUT('0');
while (--width > 0);
} else {
do
PUT(' ');
do PUT(' ');
while (--width > 0);
}
}

View file

@ -58,6 +58,8 @@ $(LIBC_FMT_A_OBJS): \
OVERRIDE_CFLAGS += \
-fno-jump-tables
o/$(MODE)/libc/fmt/formatint64.o \
o/$(MODE)/libc/fmt/formatint64thousands.o \
o/$(MODE)/libc/fmt/dosdatetimetounix.o \
o/$(MODE)/libc/fmt/itoa64radix10.greg.o: \
OVERRIDE_CFLAGS += \

55
libc/fmt/formatint64.c Normal file
View file

@ -0,0 +1,55 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/itoa.h"
/**
* Converts unsigned 64-bit integer to string.
*
* @param p needs at least 21 bytes
* @return pointer to nul byte
*/
noinline char *FormatUint64(char p[static 21], uint64_t x) {
char t;
size_t i, a, b;
i = 0;
do {
p[i++] = x % 10 + '0';
x = x / 10;
} while (x > 0);
p[i] = '\0';
if (i) {
for (a = 0, b = i - 1; a < b; ++a, --b) {
t = p[a];
p[a] = p[b];
p[b] = t;
}
}
return p + i;
}
/**
* Converts signed 64-bit integer to string.
*
* @param p needs at least 21 bytes
* @return pointer to nul byte
*/
char *FormatInt64(char p[static 21], int64_t x) {
if (x < 0) *p++ = '-', x = -(uint64_t)x;
return FormatUint64(p, x);
}

View file

@ -0,0 +1,53 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/itoa.h"
/**
* Converts unsigned 64-bit integer to string w/ commas.
*
* @param p needs at least 21 bytes
* @return pointer to nul byte
*/
noinline char *FormatUint64Thousands(char p[static 27], uint64_t x) {
size_t i;
char m[26];
i = 0;
do {
m[i++] = x % 10 + '0';
x = x / 10;
} while (x);
for (;;) {
*p++ = m[--i];
if (!i) break;
if (!(i % 3)) *p++ = ',';
}
*p = '\0';
return p;
}
/**
* Converts 64-bit integer to string w/ commas.
*
* @param p needs at least 21 bytes
* @return pointer to nul byte
*/
char *FormatInt64Thousands(char p[static 27], int64_t x) {
if (x < 0) *p++ = '-', x = -(uint64_t)x;
return FormatUint64Thousands(p, x);
}

View file

@ -16,6 +16,10 @@ COSMOPOLITAN_C_START_
- uint128toarray_radix10(0x31337, a) l: 93 (27ns) m: 141 (41ns)
- int128toarray_radix10(0x31337, a) l: 96 (28ns) m: 173 (51ns) */
char *FormatInt64(char[hasatleast 21], int64_t);
char *FormatUint64(char[hasatleast 21], uint64_t);
char *FormatInt64Thousands(char[hasatleast 27], int64_t);
char *FormatUint64Thousands(char[hasatleast 27], uint64_t);
size_t int64toarray_radix10(int64_t, char[hasatleast 21]);
size_t uint64toarray_radix10(uint64_t, char[hasatleast 21]);
size_t uint64toarray_radix16(uint64_t, char[hasatleast 17]);

View file

@ -20,7 +20,6 @@
#include "libc/fmt/itoa.h"
size_t uint64toarray_fixed16(uint64_t x, char b[hasatleast 17], uint8_t k) {
int i;
char *p;
assert(k <= 64 && !(k & 3));
for (p = b; k > 0;) *p++ = "0123456789abcdef"[(x >> (k -= 4)) & 15];

183
libc/fmt/kerrornameslong.S Normal file
View file

@ -0,0 +1,183 @@
/*-*- 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/macros.internal.h"
.macro .e e s
.long \e - kErrorNamesLong
.long 1f - kErrorNamesLong
.rodata.str1.1
1: .asciz "\s"
.previous
.endm
.section .rodata
.align 4
kErrorNamesLong:
.e EPIPE,"EPIPE[Broken pipe]"
.e ENODEV,"ENODEV[No such device]"
.e EINVAL,"EINVAL[Invalid argument]"
.e EINTR,"EINTR[Interrupted system call]"
.e ENOTBLK,"ENOTBLK[Block device required]"
.e ENOSYS,"ENOSYS[Function not implemented]"
.e EHOSTUNREACH,"EHOSTUNREACH[No route to host]"
.e ESRCH,"ESRCH[No such process]"
.e EUSERS,"EUSERS[Too many users]"
.e EXDEV,"EXDEV[Cross-device link]"
.e E2BIG,"E2BIG[Arg list too long]"
.e EREMOTE,"EREMOTE[Object is remote]"
.e ECHILD,"ECHILD[No child processes]"
.e EMSGSIZE,"EMSGSIZE[Message too long]"
.e ENOTEMPTY,"ENOTEMPTY[Directory not empty]"
.e ENOBUFS,"ENOBUFS[No buffer space available]"
.e ELOOP,"ELOOP[Too many symbolic links encountered]"
.e EAFNOSUPPORT,"EAFNOSUPPORT[Address family not supported by protocol]"
.e EHOSTDOWN,"EHOSTDOWN[Host is down]"
.e EPFNOSUPPORT,"EPFNOSUPPORT[Protocol family not supported]"
.e ENOPROTOOPT,"ENOPROTOOPT[Protocol not available]"
.e EBUSY,"EBUSY[Device or resource busy]"
.e EWOULDBLOCK,"EWOULDBLOCK[Operation would block]"
.e EBADFD,"EBADFD[File descriptor in bad state]"
.e EISCONN,"EISCONN[Transport endpoint is already connected]"
.e ESHUTDOWN,"ESHUTDOWN[Cannot send after transport endpoint shutdown]"
.e ENONET,"ENONET[Machine is not on the network]"
.e EBADE,"EBADE[Invalid exchange]"
.e EBADF,"EBADF[Bad file number]"
.e EMULTIHOP,"EMULTIHOP[Multihop attempted]"
.e EIO,"EIO[I/O error]"
.e EUNATCH,"EUNATCH[Protocol driver not attached]"
.e EPROTOTYPE,"EPROTOTYPE[Protocol wrong type for socket]"
.e ENOSPC,"ENOSPC[No space left on device]"
.e ENOEXEC,"ENOEXEC[Exec format error]"
.e EALREADY,"EALREADY[Operation already in progress]"
.e ENETDOWN,"ENETDOWN[Network is down]"
.e ENOTNAM,"ENOTNAM[Not a XENIX named type file]"
.e EACCES,"EACCES[Permission denied]"
.e ELNRNG,"ELNRNG[Link number out of range]"
.e EILSEQ,"EILSEQ[Illegal byte sequence]"
.e ENOTDIR,"ENOTDIR[Not a directory]"
.e ENOTUNIQ,"ENOTUNIQ[Name not unique on network]"
.e EPERM,"EPERM[Operation not permitted]"
.e EDOM,"EDOM[Math argument out of domain of func]"
.e EXFULL,"EXFULL[Exchange full]"
.e ECONNREFUSED,"ECONNREFUSED[Connection refused]"
.e EISDIR,"EISDIR[Is a directory]"
.e EPROTONOSUPPORT,"EPROTONOSUPPORT[Protocol not supported]"
.e EROFS,"EROFS[Read-only file system]"
.e EADDRNOTAVAIL,"EADDRNOTAVAIL[Cannot assign requested address]"
.e EIDRM,"EIDRM[Identifier removed]"
.e ECOMM,"ECOMM[Communication error on send]"
.e ESRMNT,"ESRMNT[Srmount error]"
.e EREMOTEIO,"EREMOTEIO[Remote I/O error]"
.e EL3RST,"EL3RST[Level 3 reset]"
.e EBADMSG,"EBADMSG[Not a data message]"
.e ENFILE,"ENFILE[File table overflow]"
.e ELIBMAX,"ELIBMAX[Attempting to link in too many shared libraries]"
.e ESPIPE,"ESPIPE[Illegal seek]"
.e ENOLINK,"ENOLINK[Link has been severed]"
.e ENETRESET,"ENETRESET[Network dropped connection because of reset]"
.e ETIMEDOUT,"ETIMEDOUT[Connection timed out]"
.e ENOENT,"ENOENT[No such file or directory]"
.e EEXIST,"EEXIST[File exists]"
.e EDQUOT,"EDQUOT[Quota exceeded]"
.e ENOSTR,"ENOSTR[Device not a stream]"
.e EBADSLT,"EBADSLT[Invalid slot]"
.e EBADRQC,"EBADRQC[Invalid request code]"
.e ELIBACC,"ELIBACC[Can not access a needed shared library]"
.e EFAULT,"EFAULT[Bad address]"
.e EFBIG,"EFBIG[File too large]"
.e EDEADLK,"EDEADLK[Resource deadlock would occur]"
.e ENOTCONN,"ENOTCONN[Transport endpoint is not connected]"
.e EDESTADDRREQ,"EDESTADDRREQ[Destination address required]"
.e ELIBSCN,"ELIBSCN[.lib section in a.out corrupted]"
.e ENOLCK,"ENOLCK[No record locks available]"
.e EISNAM,"EISNAM[Is a named type file]"
.e ECONNABORTED,"ECONNABORTED[Software caused connection abort]"
.e ENETUNREACH,"ENETUNREACH[Network is unreachable]"
.e ESTALE,"ESTALE[Stale NFS file handle]"
.e ENOSR,"ENOSR[Out of streams resources]"
.e ENOMEM,"ENOMEM[Out of memory]"
.e ENOTSOCK,"ENOTSOCK[Socket operation on non-socket]"
.e ESTRPIPE,"ESTRPIPE[Streams pipe error]"
.e EMLINK,"EMLINK[Too many links]"
.e ERANGE,"ERANGE[Math result not representable]"
.e ELIBEXEC,"ELIBEXEC[Cannot exec a shared library directly]"
.e EL3HLT,"EL3HLT[Level 3 halted]"
.e ECONNRESET,"ECONNRESET[Connection reset by peer]"
.e EADDRINUSE,"EADDRINUSE[Address already in use]"
.e EOPNOTSUPP,"EOPNOTSUPP[Operation not supported on transport endpoint]"
.e EREMCHG,"EREMCHG[Remote address changed]"
.e EAGAIN,"EAGAIN[Try again]"
.e ENAMETOOLONG,"ENAMETOOLONG[File name too long]"
.e ENOTTY,"ENOTTY[Not a typewriter]"
.e ERESTART,"ERESTART[Interrupted system call should be restarted]"
.e ESOCKTNOSUPPORT,"ESOCKTNOSUPPORT[Socket type not supported]"
.e ETIME,"ETIME[Timer expired]"
.e ETOOMANYREFS,"ETOOMANYREFS[Too many references: cannot splice]"
.e EMFILE,"EMFILE[Too many open files]"
.e ETXTBSY,"ETXTBSY[Text file busy]"
.e EINPROGRESS,"EINPROGRESS[Operation now in progress]"
.e ENXIO,"ENXIO[No such device or address]"
.e ENOTSUP,"ENOTSUP[Operation not supported]"
.e EPROTO,"EPROTO[Protocol error]"
.e ENOMSG,"ENOMSG[No message of desired type]"
.e ENODATA,"ENODATA[No data available]"
.e EOVERFLOW,"EOVERFLOW[Value too large for defined data type]"
.e ENOMEDIUM,"ENOMEDIUM[No medium found]"
.e EMEDIUMTYPE,"EMEDIUMTYPE[Wrong medium type]"
.e ECANCELED,"ECANCELED[Operation Canceled]"
.e EOWNERDEAD,"EOWNERDEAD[Owner died]"
.e ENOTRECOVERABLE,"ENOTRECOVERABLE[State not recoverable]"
.e EOWNERDEAD,"EOWNERDEAD[Process died with the lock]"
.e ENOTRECOVERABLE,"ENOTRECOVERABLE[Lock is not recoverable]"
.e EFTYPE,"EFTYPE[Inappropriate file type or format]"
.e EAUTH,"EAUTH[Authentication error]"
.e EBADRPC,"EBADRPC[RPC struct is bad]"
.e ENEEDAUTH,"ENEEDAUTH[Need authenticator]"
.e ENOATTR,"ENOATTR[Attribute not found]"
.e EPROCUNAVAIL,"EPROCUNAVAIL[Bad procedure for program]"
.e EPROGMISMATCH,"EPROGMISMATCH[Program version wrong]"
.e EPROGUNAVAIL,"EPROGUNAVAIL[RPC prog. not avail]"
.e ERPCMISMATCH,"ERPCMISMATCH[RPC version wrong]"
.e EPROCLIM,"EPROCLIM[Too many processes]"
.e EBADARCH,"EBADARCH[Bad CPU type in executable]"
.e EBADEXEC,"EBADEXEC[Bad executable (or shared library)]"
.e EBADMACHO,"EBADMACHO[Malformed Mach-o file]"
.e EDEVERR,"EDEVERR[Device error]"
.e ENOPOLICY,"ENOPOLICY[Policy not found]"
.e EPWROFF,"EPWROFF[Device power is off]"
.e ESHLIBVERS,"ESHLIBVERS[Shared library version mismatch]"
.e ENOANO,"ENOANO[No anode]"
.e EADV,"EADV[Advertise error]"
.e EL2HLT,"EL2HLT[Level 2 halted]"
.e EDOTDOT,"EDOTDOT[RFS specific error]"
.e ENOPKG,"ENOPKG[Package not installed]"
.e EBADR,"EBADR[Invalid request descriptor]"
.e ENOCSI,"ENOCSI[No CSI structure available]"
.e ENOKEY,"ENOKEY[Required key not available]"
.e EUCLEAN,"EUCLEAN[Structure needs cleaning]"
.e ECHRNG,"ECHRNG[Channel number out of range]"
.e EL2NSYNC,"EL2NSYNC[Level 2 not synchronized]"
.e EKEYEXPIRED,"EKEYEXPIRED[Key has expired]"
.e ENAVAIL,"ENAVAIL[No XENIX semaphores available]"
.e EKEYREVOKED,"EKEYREVOKED[Key has been revoked]"
.e ELIBBAD,"ELIBBAD[Accessing a corrupted shared library]"
.e EKEYREJECTED,"EKEYREJECTED[Key was rejected by service]"
.e ERFKILL,"ERFKILL[Operation not possible due to RF-kill]"
.long 0
.endobj kErrorNamesLong,globl,hidden

View file

@ -27,10 +27,13 @@
#include "libc/nt/runtime.h"
#include "libc/str/str.h"
extern const struct Error {
struct Error {
int x;
int s;
} kErrorNames[];
};
extern const struct Error kErrorNames[];
extern const struct Error kErrorNamesLong[];
static const char *GetErrorName(long x) {
int i;
@ -44,6 +47,20 @@ static const char *GetErrorName(long x) {
return "EUNKNOWN";
}
static const char *GetErrorNameLong(long x) {
int i;
if (x) {
for (i = 0; kErrorNamesLong[i].x; ++i) {
if (x ==
*(const long *)((uintptr_t)kErrorNamesLong + kErrorNamesLong[i].x)) {
return (const char *)((uintptr_t)kErrorNamesLong +
kErrorNamesLong[i].s);
}
}
}
return "EUNKNOWN[No error information]";
}
/**
* Converts errno value to string.
* @return 0 on success, or error code
@ -52,7 +69,11 @@ int strerror_r(int err, char *buf, size_t size) {
char *p;
const char *s;
err &= 0xFFFF;
s = GetErrorName(err);
if (IsTiny()) {
s = GetErrorName(err);
} else {
s = GetErrorNameLong(err);
}
p = buf;
if (strlen(s) + 1 + 5 + 1 + 1 <= size) {
p = stpcpy(p, s);

View file

@ -1,7 +1,7 @@
/*-*- 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,25 +16,27 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/runtime/carsort.h"
#include "libc/fmt/fmt.h"
#include "libc/str/str.h"
/**
* Sorts int32 key-value arrays of trivial size.
* Removes file extension.
*
* @see test/libc/alg/carsort_test.c
* @see carsort1000() if larger
* @param s is mutated
* @return s
*/
textstartup void carsort100(size_t n, int32_t a[n][2]) {
int32_t t[2];
unsigned i, j;
for (i = 1; i < n; ++i) {
j = i;
memcpy(t, a[i], sizeof(t));
while (j > 0 && t[0] < a[j - 1][0]) {
memcpy(a[j], a[j - 1], sizeof(t));
--j;
char *stripext(char *s) {
size_t i;
for (i = strlen(s); i--;) {
switch (s[i]) {
case '.':
s[i] = 0;
return s;
case '/':
return s;
default:
break;
}
memcpy(a[j], t, sizeof(t));
}
return s;
}

View file

@ -37,21 +37,24 @@
* @see strtoumax()
*/
intmax_t strtoimax(const char *s, char **endptr, int base) {
char t = 0;
int d, c = *s;
intmax_t x = 0;
CONSUME_SPACES(s, c);
GET_SIGN(s, c, d);
GET_RADIX(s, c, base);
if ((c = kBase36[c & 255]) && --c < base) {
do {
if (__builtin_mul_overflow(x, base, &x) ||
__builtin_add_overflow(x, c * d, &x)) {
x = d > 0 ? INTMAX_MAX : INTMAX_MIN;
errno = ERANGE;
break;
}
} while ((c = kBase36[*++s & 255]) && --c < base);
if (!((t |= 1) & 2)) {
do {
if (__builtin_mul_overflow(x, base, &x) ||
__builtin_add_overflow(x, c * d, &x)) {
x = d > 0 ? INTMAX_MAX : INTMAX_MIN;
errno = ERANGE;
t |= 2;
}
} while ((c = kBase36[*++s & 255]) && --c < base);
}
}
if (endptr) *endptr = s;
if (t && endptr) *endptr = s;
return x;
}

View file

@ -25,6 +25,16 @@
/**
* Decodes signed integer from ASCII string.
*
* atoi 10 22𝑐 7𝑛𝑠
* strtol 10 37𝑐 12𝑛𝑠
* strtoul 10 35𝑐 11𝑛𝑠
* wcstol 10 30𝑐 10𝑛𝑠
* wcstoul 10 30𝑐 10𝑛𝑠
* strtoimax 10 80𝑐 26𝑛𝑠
* strtoumax 10 78𝑐 25𝑛𝑠
* wcstoimax 10 77𝑐 25𝑛𝑠
* wcstoumax 10 76𝑐 25𝑛𝑠
*
* @param s is a non-null nul-terminated string
* @param endptr if non-null will always receive a pointer to the char
* following the last one this function processed, which is usually
@ -36,21 +46,24 @@
* @return the decoded signed saturated number
*/
long strtol(const char *s, char **endptr, int base) {
char t = 0;
long x = 0;
int d, c = *s;
CONSUME_SPACES(s, c);
GET_SIGN(s, c, d);
GET_RADIX(s, c, base);
if ((c = kBase36[c & 255]) && --c < base) {
do {
if (__builtin_mul_overflow(x, base, &x) ||
__builtin_add_overflow(x, c * d, &x)) {
x = d > 0 ? LONG_MAX : LONG_MIN;
errno = ERANGE;
break;
}
} while ((c = kBase36[*++s & 255]) && --c < base);
if (!((t |= 1) & 2)) {
do {
if (__builtin_mul_overflow(x, base, &x) ||
__builtin_add_overflow(x, c * d, &x)) {
x = d > 0 ? LONG_MAX : LONG_MIN;
errno = ERANGE;
t |= 2;
}
} while ((c = kBase36[*++s & 255]) && --c < base);
}
}
if (endptr) *endptr = s;
if (t && endptr) *endptr = s;
return x;
}

View file

@ -2,6 +2,7 @@
#define COSMOPOLITAN_LIBC_FMT_STRTOL_H_
#define CONSUME_SPACES(s, c) \
if (endptr) *endptr = s; \
while (c == ' ' || c == '\t') c = *++s
#define GET_SIGN(s, c, d) \
@ -11,6 +12,7 @@
#define GET_RADIX(s, c, r) \
if (!(2 <= r && r <= 36)) { \
if (c == '0') { \
t |= 1; \
c = *++s; \
if (c == 'x' || c == 'X') { \
c = *++s; \
@ -25,6 +27,7 @@
r = 10; \
} \
} else if (c == '0') { \
t |= 1; \
c = *++s; \
if ((r == 2 && (c == 'b' || c == 'B')) || \
(r == 16 && (c == 'x' || c == 'X'))) { \

View file

@ -35,17 +35,19 @@
* @return decoded integer mod 2 negated if leading `-`
*/
unsigned long strtoul(const char *s, char **endptr, int base) {
char t = 0;
int d, c = *s;
unsigned long x = 0;
CONSUME_SPACES(s, c);
GET_SIGN(s, c, d);
GET_RADIX(s, c, base);
if ((c = kBase36[c & 255]) && --c < base) {
t |= 1;
do {
x *= base;
x += c;
} while ((c = kBase36[*++s & 255]) && --c < base);
}
if (endptr) *endptr = s;
if (t && endptr) *endptr = s;
return d > 0 ? x : -x;
}

View file

@ -35,17 +35,19 @@
* @see strtoimax()
*/
uintmax_t strtoumax(const char *s, char **endptr, int base) {
char t = 0;
int d, c = *s;
uintmax_t x = 0;
CONSUME_SPACES(s, c);
GET_SIGN(s, c, d);
GET_RADIX(s, c, base);
if ((c = kBase36[c & 255]) && --c < base) {
t |= 1;
do {
x *= base;
x += c;
} while ((c = kBase36[*++s & 255]) && --c < base);
}
if (endptr) *endptr = s;
if (t && endptr) *endptr = s;
return d > 0 ? x : -x;
}

View file

@ -37,25 +37,24 @@
* @see strtoumax()
*/
intmax_t wcstoimax(const wchar_t *s, wchar_t **endptr, int base) {
int c, d;
intmax_t x;
c = *s;
char t = 0;
intmax_t x = 0;
int d, c = *s;
CONSUME_SPACES(s, c);
GET_SIGN(s, c, d);
GET_RADIX(s, c, base);
x = 0;
if ((c = kBase36[c & 255]) && --c < base) {
do {
if (__builtin_mul_overflow(x, base, &x) ||
__builtin_add_overflow(x, c * d, &x)) {
x = d > 0 ? INTMAX_MAX : INTMAX_MIN;
errno = ERANGE;
break;
}
} while ((c = kBase36[*++s & 255]) && --c < base);
}
if (endptr) {
*endptr = s;
if (!((t |= 1) & 2)) {
do {
if (__builtin_mul_overflow(x, base, &x) ||
__builtin_add_overflow(x, c * d, &x)) {
x = d > 0 ? INTMAX_MAX : INTMAX_MIN;
errno = ERANGE;
t |= 2;
}
} while ((c = kBase36[*++s & 255]) && --c < base);
}
}
if (t && endptr) *endptr = s;
return x;
}

View file

@ -36,21 +36,24 @@
* @return the decoded signed saturated number
*/
long wcstol(const wchar_t *s, wchar_t **endptr, int base) {
char t = 0;
long x = 0;
int d, c = *s;
CONSUME_SPACES(s, c);
GET_SIGN(s, c, d);
GET_RADIX(s, c, base);
if ((c = kBase36[c & 255]) && --c < base) {
do {
if (__builtin_mul_overflow(x, base, &x) ||
__builtin_add_overflow(x, c * d, &x)) {
x = d > 0 ? LONG_MAX : LONG_MIN;
errno = ERANGE;
break;
}
} while ((c = kBase36[*++s & 255]) && --c < base);
if (!((t |= 1) & 2)) {
do {
if (__builtin_mul_overflow(x, base, &x) ||
__builtin_add_overflow(x, c * d, &x)) {
x = d > 0 ? LONG_MAX : LONG_MIN;
errno = ERANGE;
t |= 2;
}
} while ((c = kBase36[*++s & 255]) && --c < base);
}
}
if (endptr) *endptr = s;
if (t && endptr) *endptr = s;
return x;
}

View file

@ -35,17 +35,19 @@
* @return decoded integer mod 2 negated if leading `-`
*/
unsigned long wcstoul(const wchar_t *s, wchar_t **endptr, int base) {
char t = 0;
int d, c = *s;
unsigned long x = 0;
CONSUME_SPACES(s, c);
GET_SIGN(s, c, d);
GET_RADIX(s, c, base);
if ((c = kBase36[c & 255]) && --c < base) {
t |= 1;
do {
x *= base;
x += c;
} while ((c = kBase36[*++s & 255]) && --c < base);
}
if (endptr) *endptr = s;
if (t && endptr) *endptr = s;
return d > 0 ? x : -x;
}

View file

@ -35,21 +35,19 @@
* @see strtoimax()
*/
uintmax_t wcstoumax(const wchar_t *s, wchar_t **endptr, int base) {
int c, d;
uintmax_t x;
c = *s;
char t = 0;
int d, c = *s;
uintmax_t x = 0;
CONSUME_SPACES(s, c);
GET_SIGN(s, c, d);
GET_RADIX(s, c, base);
x = 0;
if ((c = kBase36[c & 255]) && --c < base) {
t |= 1;
do {
x *= base;
x += c;
} while ((c = kBase36[*++s & 255]) && --c < base);
}
if (endptr) {
*endptr = s;
}
if (t && endptr) *endptr = s;
return d > 0 ? x : -x;
}

Some files were not shown because too many files have changed in this diff Show more