mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
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:
parent
fa7b4f5bd1
commit
39bf41f4eb
806 changed files with 77494 additions and 63859 deletions
8
Makefile
8
Makefile
|
@ -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
|
||||
|
|
14
ape/ape.S
14
ape/ape.S
|
@ -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. │
|
||||
╠──────────────────────────────────────────────────────────────────────────────╣
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
|
|
|
@ -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.
|
@ -75,7 +75,7 @@ TARGET_ARCH ?= \
|
|||
-msse3
|
||||
|
||||
PYFLAGS += \
|
||||
-B
|
||||
-O1
|
||||
|
||||
endif
|
||||
|
||||
|
@ -161,6 +161,7 @@ CONFIG_CCFLAGS += \
|
|||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
PYFLAGS += \
|
||||
-O2 \
|
||||
-B
|
||||
endif
|
||||
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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 $@ $<
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
40
dsp/core/mulaw.c
Normal 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
38
dsp/core/unalaw.c
Normal 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
37
dsp/core/unmulaw.c
Normal 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;
|
||||
}
|
|
@ -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[]) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
16
libc/bits/xadd.h
Normal 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_ */
|
|
@ -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 &&
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
39
libc/calls/fchmodat-nt.c
Normal 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();
|
||||
}
|
|
@ -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`
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
39
libc/elf/getelfstrs.c
Normal 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;
|
||||
}
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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 *);
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
55
libc/fmt/formatint64.c
Normal 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);
|
||||
}
|
53
libc/fmt/formatint64thousands.c
Normal file
53
libc/fmt/formatint64thousands.c
Normal 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);
|
||||
}
|
|
@ -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]);
|
||||
|
|
|
@ -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
183
libc/fmt/kerrornameslong.S
Normal 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
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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'))) { \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue