Make improvements

main
Justine Tunney 2020-12-01 03:43:40 -08:00
parent 3e4fd4b0ad
commit e44a0cf6f8
256 changed files with 23100 additions and 2294 deletions

View File

@ -116,6 +116,7 @@ include libc/mem/mem.mk # │
include libc/ohmyplus/ohmyplus.mk # │
include libc/zipos/zipos.mk # │
include third_party/dtoa/dtoa.mk # │
include third_party/gdtoa/gdtoa.mk # │
include libc/time/time.mk # │
include libc/alg/alg.mk # │
include libc/calls/hefty/hefty.mk # │
@ -138,6 +139,7 @@ include dsp/tty/tty.mk # ├──online
include libc/dns/dns.mk # │
include libc/crypto/crypto.mk # │
include net/http/http.mk #─┘
include third_party/chibicc/chibicc.mk
include third_party/lemon/lemon.mk
include third_party/linenoise/linenoise.mk
include third_party/editline/editline.mk

View File

@ -35,7 +35,7 @@
*/
#include "ape/config.h"
#include "ape/lib/pc.h"
#include "ape/macros.h"
#include "ape/macros.internal.h"
#include "ape/notice.inc"
#include "ape/relocations.h"
#include "libc/elf/def.h"
@ -785,8 +785,8 @@ ape.pe: .ascin "PE",4
.long 0 # Checksum
.short v_ntsubsystem # Subsystem: 0=Neutral,2=GUI,3=Console
.short .LDLLEXE # DllCharacteristics
.quad 0x0000000000080000 # StackReserve
.quad 0x0000000000080000 # StackCommit
.quad 0x0000000000020000 # StackReserve
.quad 0x0000000000020000 # StackCommit
.quad 0 # HeapReserve
.quad 0 # HeapCommit
.long 0 # LoaderFlags

View File

@ -175,7 +175,7 @@
Until then, we can build for those platforms using Linux or WSL. */
#ifdef __LINKER__
#include "ape/macros.h"
#include "ape/macros.internal.h"
#include "ape/config.h"
#include "libc/nt/pedef.internal.h"
#include "libc/zip.h"

View File

@ -17,7 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "ape/macros.h"
#include "ape/macros.internal.h"
#include "ape/notice.inc"
.section .real,"ax",@progbits
.source __FILE__

View File

@ -19,7 +19,7 @@
*/
#include "ape/lib/pc.h"
#include "ape/config.h"
#include "ape/macros.h"
#include "ape/macros.internal.h"
#include "ape/notice.inc"
.section .real,"ax",@progbits
.source __FILE__

View File

@ -20,7 +20,7 @@
#include "ape/config.h"
#include "ape/lib/pc.h"
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/macros.h"
/**
* Virtualizes physical memory.
@ -33,27 +33,24 @@
*/
textreal void flattenhighmemory(struct SmapEntry *e820, struct PageTable *pml4t,
uint64_t *ptsp) {
struct SmapEntry *smap = e820;
struct SmapEntry *hole = e820;
uint64_t paddr = IMAGE_BASE_PHYSICAL;
uint64_t vaddr = IMAGE_BASE_VIRTUAL;
while (smap->size) {
uint64_t *entry, paddr, vaddr;
struct SmapEntry *smap, *hole;
for (smap = hole = e820, vaddr = IMAGE_BASE_VIRTUAL; smap->size; ++smap) {
while (smap->size && smap->type != kMemoryUsable) smap++;
paddr = roundup(max(paddr, smap->addr), PAGESIZE);
while (paddr < rounddown(smap->addr + smap->size, PAGESIZE)) {
paddr = ROUNDUP(MAX(IMAGE_BASE_PHYSICAL, smap->addr), PAGESIZE);
while (paddr < ROUNDDOWN(smap->addr + smap->size, PAGESIZE)) {
while (hole->size &&
(hole->type == kMemoryUsable || hole->addr + hole->size < paddr)) {
hole++;
}
if (paddr >= hole->addr && paddr < hole->addr + hole->size) {
paddr = roundup(hole->addr + hole->size, PAGESIZE);
paddr = ROUNDUP(hole->addr + hole->size, PAGESIZE);
} else {
uint64_t *entry = getpagetableentry(vaddr, 3, pml4t, ptsp);
entry = __getpagetableentry(vaddr, 3, pml4t, ptsp);
*entry = paddr | PAGE_V | PAGE_RW;
vaddr += 0x1000;
paddr += 0x1000;
}
}
smap++;
}
}

View File

@ -19,7 +19,7 @@
*/
#include "ape/lib/pc.h"
#include "ape/config.h"
#include "ape/macros.h"
#include "ape/macros.internal.h"
#include "ape/notice.inc"
.section .real,"ax",@progbits
.source __FILE__

View File

@ -19,7 +19,7 @@
*/
#include "ape/lib/pc.h"
#include "ape/config.h"
#include "ape/macros.h"
#include "ape/macros.internal.h"
#include "ape/notice.inc"
.section .real,"ax",@progbits
.source __FILE__

View File

@ -20,12 +20,13 @@
#include "ape/lib/pc.h"
#include "libc/assert.h"
textreal static uint64_t pushpagetable(uint64_t *ptsp) {
static textreal uint64_t __pushpagetable(uint64_t *ptsp) {
return (*ptsp -= PAGESIZE) | PAGE_V | PAGE_RW;
}
textreal uint64_t *getpagetableentry(int64_t vaddr, unsigned depth,
struct PageTable *pml4t, uint64_t *ptsp) {
textreal uint64_t *__getpagetableentry(int64_t vaddr, unsigned depth,
struct PageTable *pml4t,
uint64_t *ptsp) {
uint64_t *entry;
unsigned char shift;
assert(depth <= 3);
@ -36,7 +37,7 @@ textreal uint64_t *getpagetableentry(int64_t vaddr, unsigned depth,
entry = &pml4t->p[(vaddr >> shift) & 511];
if (!depth--) return entry;
shift -= 9;
if (!*entry) *entry = pushpagetable(ptsp);
if (!*entry) *entry = __pushpagetable(ptsp);
pml4t = (void *)(*entry & PAGE_TA);
}
}

View File

@ -19,7 +19,7 @@
*/
#include "ape/lib/pc.h"
#include "ape/config.h"
#include "ape/macros.h"
#include "ape/macros.internal.h"
#include "ape/notice.inc"
.section .real,"ax",@progbits
.source __FILE__

View File

@ -24,7 +24,7 @@
textreal static void __map_segment(uint64_t k, uint64_t a, uint64_t b) {
uint64_t *e;
for (; a < b; a += 0x1000) {
e = getpagetableentry(IMAGE_BASE_VIRTUAL + a, 3, &g_pml4t, &g_ptsp_xlm);
e = __getpagetableentry(IMAGE_BASE_VIRTUAL + a, 3, &g_pml4t, &g_ptsp_xlm);
*e = (IMAGE_BASE_REAL + a) | k;
}
}

View File

@ -22,7 +22,7 @@
textreal void pageunmap(int64_t vaddr) {
uint64_t *entry;
entry = getpagetableentry(vaddr, 3, &g_pml4t, &g_ptsp_xlm);
entry = __getpagetableentry(vaddr, 3, &g_pml4t, &g_ptsp_xlm);
*entry &= ~PAGE_V;
invlpg(vaddr);
}

View File

@ -214,7 +214,8 @@ extern uint64_t g_ptsp_xlm;
void bootdr(char drive) noreturn;
void smapsort(struct SmapEntry *);
uint64_t *getpagetableentry(int64_t, unsigned, struct PageTable *, uint64_t *);
uint64_t *__getpagetableentry(int64_t, unsigned, struct PageTable *,
uint64_t *);
void flattenhighmemory(struct SmapEntry *, struct PageTable *, uint64_t *);
void pageunmap(int64_t);

View File

@ -29,7 +29,6 @@
#include "libc/log/log.h"
#include "libc/macros.h"
#include "libc/runtime/gc.h"
#include "libc/runtime/rbx.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"

View File

@ -1,136 +0,0 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/termios.h"
#include "libc/fmt/fmt.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/termios.h"
int yn2, xn2;
int yn3, xn3;
char b[128], inbuf[128];
int y, x, yn, xn, my, mx;
struct termios term, oldterm;
int main(int argc, char *argv[]) {
int i;
setvbuf(stdout, inbuf, _IONBF, 128); /* make things slower */
/* raw mode */
ioctl(1, TCGETS, &oldterm);
memcpy(&term, &oldterm, sizeof(term));
term.c_cc[VMIN] = 1;
term.c_cc[VTIME] = 1;
term.c_iflag &= ~(INPCK | ISTRIP | PARMRK | INLCR | IGNCR | ICRNL | IXON);
term.c_lflag &= ~(IEXTEN | ICANON | ECHO | ECHONL);
term.c_cflag &= ~(CSIZE | PARENB);
term.c_oflag &= ~OPOST;
term.c_cflag |= CS8;
term.c_iflag |= IUTF8;
ioctl(1, TCSETSF, &term);
/* get cursor position and display dimensions */
printf("\e7\e[6n\e[9979;9979H\e[6n\e8");
read(0, b, sizeof(b));
sscanf(b, "\e[%d;%dR\e[%d;%dR", &y, &x, &yn, &xn);
printf("\e[1q"); /* turn on led one */
printf("\e[2J"); /* clear display */
printf("\e#8"); /* fill display with E's */
printf("\e[H");
/* clear display again */
printf("\e[2q"); /* turn on led two */
for (i = 0; i < yn; ++i) {
if (i) printf("\n");
printf(" ");
printf("\e[0K");
}
for (i = 0; i < yn - 1; ++i) {
if (i) printf("\eM");
printf("\e[1K");
}
printf("\e(0"); /* line drawing mode */
printf("\e[3q"); /* turn on led three */
printf("\e[H");
/* move to center */
my = yn / 2;
mx = xn / 2 - 7;
if (y > my) {
printf("\e[%dA", y - my);
} else if (y < my) {
printf("\e[%dB", my - y);
}
if (x > mx) {
printf("\e[%dD", x - mx);
} else if (x < mx) {
printf("\e[%dC", mx - x);
}
printf("\e[90;103m"); /* black on yellow */
printf("\e[90;103ma ` a"); /* draw nose */
printf("\e[0m"); /* reset style */
printf("\e(B"); /* ascii mode */
/* draw corners */
printf("\e[H"); /* top left */
printf("A");
printf("\e[9979C"); /* rightmost */
printf("B");
printf("\e[9979;9979H"); /* bottom right corner */
printf("\e[C"); /* move right gets clamped */
printf("D"); /* write, set redzone flag */
printf("\e[2A"); /* move up, unsets redzone */
/* gnu screen now reports out of bounds position */
/* kitty hasnt got a redzone reporting next line */
printf("\e[6n");
read(0, b, sizeof(b));
sscanf(b, "\e[%d;%dR", &yn2, &xn2);
/* writes to (yn-3,xn-1) normally and (yn-2,0) in gnu screen */
printf("!");
/* draw ruler on top */
printf("\e[H");
for (i = 8; i + 1 < xn; i += 8) {
printf("\e[%dG%d", i + 1, i); /* set column */
}
printf("\e[9979;9979H"); /* bottom right */
printf("\e[9979D"); /* leftmost */
printf("C");
/* let's break gnu screen again with multimonospace redzone */
printf("\e[%d;9979H", yn / 2); /* right middle */
printf("\e[D"); /* left */
printf("");
printf("\e[6n");
read(0, b, sizeof(b));
sscanf(b, "\e[%d;%dR", &yn2, &xn2);
printf("\e[%dH", yn / 2);
printf("%d %d vs. %d %d\r\n", yn, xn, yn2, xn2);
printf("%d %d vs. %d %d\r\n", yn / 2, xn, yn2, xn2);
printf("\e#6double width\e#5\r\n");
printf("\e[3mthis text is so \e[1mitalic\e[0m\r\n");
printf("\e[1;20mpress any fraktur exit\e[0m");
printf("\a");
read(0, b, sizeof(b));
printf("\r\n");
ioctl(1, TCSETS, &oldterm);
return 0;
}

View File

@ -33,7 +33,6 @@
* - libc/nexgen32e/bsf.h
* - libc/nexgen32e/tzcnt.h
* - libc/nexgen32e/cpuid4.internal.h
* - libc/nexgen32e/tinystrcmp.internal.h
* - https://gist.github.com/jart/fe8d104ef93149b5ba9b72912820282c
*/

View File

@ -16,13 +16,13 @@
#include "libc/stdio/stdio.h"
#include "libc/time/time.h"
noinline void dostuff(void) {
noinline void dostuff(const char *s) {
int i, us;
srand(rand64()); /* seeds rand() w/ intel rdrnd, auxv, etc. */
for (i = 0; i < 5; ++i) {
us = rand() % 500000;
usleep(us);
printf("%s%u%s%u [%s=%d]\n", "hello no. ", i, " from ", getpid(), "us", us);
printf("hello no. %u from %s %u [us=%d]\n", i, s, getpid(), us);
fflush(stdout);
}
}
@ -32,13 +32,14 @@ int main(int argc, char *argv[]) {
CHECK_NE(-1, (child = fork()));
if (!child) {
/* child process */
dostuff();
dostuff("child");
return 0;
} else {
/* parent process */
dostuff();
dostuff("parent");
/* note: abandoned children become zombies */
CHECK_NE(-1, (rc = wait(&wstatus)));
return WEXITSTATUS(wstatus);
CHECK_EQ(0, WEXITSTATUS(wstatus));
return 0;
}
}

View File

@ -42,7 +42,6 @@
/ @see also glibc static binaries which start at 800kb!!!
/ @see also go where interfaces sadly disempower ld prune
/ @see also the stl where bad linkage is due to tech debt
/ @see libc/macros-cpp.inc forthe getstr macro definition
/ @note libc/elf/elf.lds can be tinier with page align off
/ @note gas is more powerful than nasm due to rms notation
/ @noreturn

View File

@ -6,18 +6,17 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
unsigned long morton(unsigned long, unsigned long) libcesque pureconst;
axdx_t unmorton(unsigned long) libcesque pureconst;
unsigned long morton(unsigned long, unsigned long) libcesque;
axdx_t unmorton(unsigned long) libcesque;
#ifndef __STRICT_ANSI__
#define morton(Y, X) \
(X86_NEED(BMI2) \
? pdep(X, 0x5555555555555555ul) | pdep(Y, 0xAAAAAAAAAAAAAAAAul) \
: morton(Y, X))
#define unmorton(I) \
(X86_NEED(BMI2) ? (axdx_t){pext(I, 0xAAAAAAAAAAAAAAAAul), \
pext(I, 0x5555555555555555ul)} \
: unmorton(I))
#define morton(Y, X) \
(X86_NEED(BMI2) ? pdep(X, 0x5555555555555555) | pdep(Y, 0xAAAAAAAAAAAAAAAA) \
: morton(Y, X))
#define unmorton(I) \
(X86_NEED(BMI2) \
? (axdx_t){pext(I, 0xAAAAAAAAAAAAAAAA), pext(I, 0x5555555555555555)} \
: unmorton(I))
#endif
COSMOPOLITAN_C_END_

View File

@ -32,12 +32,12 @@
* @asyncsignalsafe
*/
int access(const char *path, int mode) {
char16_t path16[PATH_MAX];
if (!path) return efault();
if (!IsWindows()) {
return faccessat$sysv(AT_FDCWD, path, mode, 0);
} else {
char16_t path16[PATH_MAX];
if (mkntpath(path, path16) == -1) return -1;
if (__mkntpath(path, path16) == -1) return -1;
return ntaccesscheck(path16, mode);
}
}

View File

@ -25,7 +25,7 @@
textwindows int chdir$nt(const char *path) {
int len;
char16_t path16[PATH_MAX];
if ((len = mkntpath(path, path16)) == -1) return -1;
if ((len = __mkntpath(path, path16)) == -1) return -1;
if (path16[len - 1] != u'/' && path16[len - 1] != u'\\') {
path16[len + 0] = u'/';
path16[len + 1] = u'\0';

View File

@ -24,22 +24,15 @@
textwindows int close$nt(int fd) {
bool32 ok;
if (__isfdopen(fd)) {
if (g_fds.p[fd].kind == kFdFile) {
/*
* Like Linux, closing a file on Windows doesn't guarantee it's
* immediately synced to disk. But unlike Linux, this could cause
* subsequent operations, e.g. unlink() to break w/ access error.
*/
FlushFileBuffers(g_fds.p[fd].handle);
}
ok = CloseHandle(g_fds.p[fd].handle);
if (g_fds.p[fd].kind == kFdConsole) {
ok &= CloseHandle(g_fds.p[fd].extra);
}
__removefd(fd);
return ok ? 0 : __winerr();
} else {
return ebadf();
if (g_fds.p[fd].kind == kFdFile) {
/*
* Like Linux, closing a file on Windows doesn't guarantee it's
* immediately synced to disk. But unlike Linux, this could cause
* subsequent operations, e.g. unlink() to break w/ access error.
*/
FlushFileBuffers(g_fds.p[fd].handle);
}
ok = CloseHandle(g_fds.p[fd].handle);
if (g_fds.p[fd].kind == kFdConsole) ok &= CloseHandle(g_fds.p[fd].extra);
return ok ? 0 : __winerr();
}

View File

@ -43,7 +43,8 @@ int close(int fd) {
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSocket) {
rc = weaken(closesocket$nt)(fd);
} else if (fd < g_fds.n &&
(g_fds.p[fd].kind == kFdFile || g_fds.p[fd].kind == kFdConsole)) {
(g_fds.p[fd].kind == kFdFile || g_fds.p[fd].kind == kFdConsole ||
g_fds.p[fd].kind == kFdProcess)) {
rc = close$nt(fd);
} else {
rc = ebadf();

View File

@ -25,6 +25,6 @@
int faccessat$nt(int dirfd, const char *path, int mode, uint32_t flags) {
char16_t path16[PATH_MAX];
if (dirfd != AT_FDCWD || flags) return einval();
if (mkntpath(path, path16) == -1) return -1;
if (__mkntpath(path, path16) == -1) return -1;
return ntaccesscheck(path16, mode);
}

View File

@ -18,18 +18,16 @@
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/macros.h"
#include "libc/nt/files.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
textwindows char *getcwd$nt(char *buf, size_t size) {
uint16_t name16[PATH_MAX];
if (GetCurrentDirectory(PATH_MAX, name16)) {
if (tprecode16to8(buf, size, name16) < size - 1) {
return buf;
} else {
erange();
}
uint16_t name16[PATH_MAX + 1];
if (GetCurrentDirectory(ARRAYLEN(name16), name16)) {
tprecode16to8(buf, size, name16);
return buf;
} else {
__winerr();
}

View File

@ -31,8 +31,8 @@
int getdomainname(char *name, size_t len) {
uint32_t nSize;
char16_t name16[256];
struct utsname u;
char16_t name16[256];
if (len < 1) return einval();
if (!name) return efault();
if (!IsWindows()) {
@ -44,10 +44,11 @@ int getdomainname(char *name, size_t len) {
return 0;
} else {
nSize = ARRAYLEN(name16);
if (!GetComputerNameEx(kNtComputerNameDnsFullyQualified, name16, &nSize)) {
if (GetComputerNameEx(kNtComputerNameDnsFullyQualified, name16, &nSize)) {
tprecode16to8(name, len, name16);
return 0;
} else {
return __winerr();
}
tprecode16to8(name, MIN(MIN(ARRAYLEN(name16), nSize + 1), len), name16);
return 0;
}
}

View File

@ -49,10 +49,11 @@ int gethostname(char *name, size_t len) {
return 0;
} else {
nSize = ARRAYLEN(name16);
if (!GetComputerNameEx(kNtComputerNameDnsHostname, name16, &nSize)) {
if (GetComputerNameEx(kNtComputerNameDnsHostname, name16, &nSize)) {
tprecode16to8(name, len, name16);
return 0;
} else {
return __winerr();
}
tprecode16to8(name, MIN(MIN(ARRAYLEN(name16), nSize + 1), len), name16);
return 0;
}
}

View File

@ -23,7 +23,7 @@
#include "libc/macros.h"
#include "libc/nt/accounting.h"
#include "libc/runtime/runtime.h"
#include "libc/str/knuthmultiplicativehash.h"
#include "libc/str/knuthmultiplicativehash.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/auxv.h"

View File

@ -38,8 +38,8 @@ static textwindows int copyfile$nt(const char *src, const char *dst,
int64_t fhsrc, fhdst;
struct NtFileTime accessed, modified;
char16_t src16[PATH_MAX], dst16[PATH_MAX];
if (mkntpath(src, src16) == -1) return -1;
if (mkntpath(dst, dst16) == -1) return -1;
if (__mkntpath(src, src16) == -1) return -1;
if (__mkntpath(dst, dst16) == -1) return -1;
if (CopyFile(src16, dst16, !!(flags & COPYFILE_NOCLOBBER))) {
if (flags & COPYFILE_PRESERVE_TIMESTAMPS) {
fhsrc = CreateFile(src16, kNtFileReadAttributes, kNtFileShareRead, NULL,

View File

@ -62,7 +62,7 @@ static textwindows noinline DIR *opendir$nt(const char *name) {
int len;
DIR *res;
char16_t name16[PATH_MAX];
if ((len = mkntpath(name, name16)) == -1) return NULL;
if ((len = __mkntpath(name, name16)) == -1) return NULL;
if (len + 2 + 1 > PATH_MAX) return PROGN(enametoolong(), NULL);
if (name16[len - 1] == u'/' || name16[len - 1] == u'\\') {
name16[--len] = u'\0';
@ -87,7 +87,8 @@ static textwindows noinline struct dirent *readdir$nt(DIR *dir) {
dir->ent.d_off = dir->tell++;
dir->ent.d_reclen = sizeof(dir->ent) +
tprecode16to8(dir->ent.d_name, sizeof(dir->ent.d_name),
dir->windata.cFileName) +
dir->windata.cFileName)
.ax +
1;
switch (dir->windata.dwFileType) {
case kNtFileTypeDisk:

View File

@ -20,36 +20,49 @@
#include "libc/calls/hefty/internal.h"
#include "libc/calls/hefty/ntspawn.h"
#include "libc/calls/internal.h"
#include "libc/nt/accounting.h"
#include "libc/nt/enum/startf.h"
#include "libc/nt/enum/status.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/processinformation.h"
#include "libc/nt/struct/startupinfo.h"
#include "libc/nt/synchronization.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/sock.h"
static textwindows int64_t passstdhand$nt(int fd) {
if (g_fds.p[fd].kind != kFdEmpty &&
!(g_fds.p[fd].flags &
(g_fds.p[fd].kind == kFdSocket ? SOCK_CLOEXEC : O_CLOEXEC))) {
return g_fds.p[fd].handle;
} else {
return -1;
}
}
textwindows int execve$nt(const char *program, char *const argv[],
char *const envp[]) {
int i;
uint32_t dwExitCode;
struct NtStartupInfo startinfo;
struct NtProcessInformation procinfo;
memset(&startinfo, 0, sizeof(startinfo));
startinfo.cb = sizeof(struct NtStartupInfo);
startinfo.dwFlags = kNtStartfUsestdhandles;
startinfo.hStdInput = passstdhand$nt(STDIN_FILENO);
startinfo.hStdOutput = passstdhand$nt(STDOUT_FILENO);
startinfo.hStdError = passstdhand$nt(STDERR_FILENO);
if (ntspawn(program, argv, envp, NULL, NULL, true, 0, NULL, &startinfo,
NULL) != -1) {
for (;;) TerminateProcess(GetCurrentProcess(), 0);
startinfo.hStdInput = g_fds.p[0].handle;
startinfo.hStdOutput = g_fds.p[1].handle;
startinfo.hStdError = g_fds.p[2].handle;
for (i = 2; i < g_fds.n; ++i) {
if (g_fds.p[i].kind != kFdEmpty && (g_fds.p[i].flags & O_CLOEXEC)) {
close(i);
}
}
return -1;
if (ntspawn(program, argv, envp, NULL, NULL, true, 0, NULL, &startinfo,
&procinfo) == -1) {
return -1;
}
CloseHandle(procinfo.hThread);
for (i = 0; i < g_fds.n; ++i) {
if (g_fds.p[i].kind != kFdEmpty) {
close(i);
}
}
do {
WaitForSingleObject(procinfo.hProcess, -1);
dwExitCode = kNtStillActive;
GetExitCodeProcess(procinfo.hProcess, &dwExitCode);
} while (dwExitCode == kNtStillActive);
ExitProcess(dwExitCode);
}

View File

@ -17,20 +17,26 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/hefty/ntspawn.h"
#include "libc/calls/hefty/spawn.h"
#include "libc/calls/internal.h"
#include "libc/conv/itoa.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/pageflags.h"
#include "libc/nt/enum/startf.h"
#include "libc/nt/ipc.h"
#include "libc/nt/memory.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/memtrack.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
static textwindows int64_t ParseInt(char16_t **p) {
@ -42,8 +48,8 @@ static textwindows int64_t ParseInt(char16_t **p) {
return x;
}
static noinline textwindows void DoAll(int64_t h, void *buf, size_t n,
bool32 (*f)()) {
static noinline textwindows void ForkIo(int64_t h, void *buf, size_t n,
bool32 (*f)()) {
char *p;
size_t i;
uint32_t x;
@ -53,11 +59,11 @@ static noinline textwindows void DoAll(int64_t h, void *buf, size_t n,
}
static noinline textwindows void WriteAll(int64_t h, void *buf, size_t n) {
DoAll(h, buf, n, WriteFile);
ForkIo(h, buf, n, WriteFile);
}
static noinline textwindows void ReadAll(int64_t h, void *buf, size_t n) {
DoAll(h, buf, n, ReadFile);
ForkIo(h, buf, n, ReadFile);
}
textwindows void WinMainForked(void) {
@ -79,7 +85,7 @@ textwindows void WinMainForked(void) {
ReadAll(h, &_mmi.p[i], sizeof(_mmi.p[i]));
addr = (void *)((uint64_t)_mmi.p[i].x << 16);
size = ((uint64_t)(_mmi.p[i].y - _mmi.p[i].x) << 16) + FRAMESIZE;
switch (_mmi.p[i].prot) {
switch (_mmi.p[i].prot & (PROT_READ | PROT_WRITE | PROT_EXEC)) {
case PROT_READ | PROT_WRITE | PROT_EXEC:
protect = kNtPageExecuteReadwrite;
access = kNtFileMapRead | kNtFileMapWrite | kNtFileMapExecute;
@ -117,9 +123,12 @@ textwindows void WinMainForked(void) {
textwindows int fork$nt(void) {
jmp_buf jb;
int i, rc, pid;
int64_t reader, writer;
int i, rc, pid, fds[3];
char *p, buf[21 + 1 + 21 + 1];
struct NtStartupInfo startinfo;
struct NtProcessInformation procinfo;
if ((pid = __getemptyfd()) == -1) return -1;
if (!setjmp(jb)) {
if (CreatePipe(&reader, &writer, &kNtIsInheritable, 0)) {
p = buf;
@ -127,12 +136,19 @@ textwindows int fork$nt(void) {
*p++ = ' ';
p += uint64toarray_radix10(writer, p);
setenv("_FORK", buf, true);
fds[0] = 0;
fds[1] = 1;
fds[2] = 2;
/* TODO: CloseHandle(g_fds.p[pid].h) if SIGCHLD is SIG_IGN */
if ((pid = spawnve(0, fds, g_argv[0], g_argv, environ)) != -1) {
memset(&startinfo, 0, sizeof(startinfo));
startinfo.cb = sizeof(struct NtStartupInfo);
startinfo.dwFlags = kNtStartfUsestdhandles;
startinfo.hStdInput = g_fds.p[0].handle;
startinfo.hStdOutput = g_fds.p[1].handle;
startinfo.hStdError = g_fds.p[2].handle;
if (ntspawn(g_argv[0], g_argv, environ, &kNtIsInheritable, NULL, true, 0,
NULL, &startinfo, &procinfo) != -1) {
CloseHandle(reader);
CloseHandle(procinfo.hThread);
g_fds.p[pid].kind = kFdProcess;
g_fds.p[pid].handle = procinfo.hProcess;
g_fds.p[pid].flags = O_CLOEXEC;
WriteAll(writer, jb, sizeof(jb));
WriteAll(writer, &_mmi.i, sizeof(_mmi.i));
for (i = 0; i < _mmi.i; ++i) {
@ -144,11 +160,11 @@ textwindows int fork$nt(void) {
}
WriteAll(writer, _edata, _end - _edata);
CloseHandle(writer);
rc = pid;
} else {
rc = -1;
}
unsetenv("_FORK");
rc = pid;
} else {
rc = __winerr();
}

View File

@ -96,5 +96,3 @@ error:
free(cmdline_p);
return NULL;
}
#undef APPENDCHAR

View File

@ -68,8 +68,8 @@ textwindows int ntspawn(
char16_t program16[PATH_MAX], *lpCommandLine, *lpEnvironment;
lpCommandLine = NULL;
lpEnvironment = NULL;
if (mkntpath(program, program16) != -1 &&
(lpCommandLine = mkntcmdline(argv)) &&
if (__mkntpath(program, program16) != -1 &&
(lpCommandLine = mkntcmdline(&argv[1])) &&
(lpEnvironment = mkntenvblock(envp))) {
if (CreateProcess(program16, lpCommandLine, opt_lpProcessAttributes,
opt_lpThreadAttributes, bInheritHandles,

View File

@ -21,7 +21,6 @@
#include "libc/alg/arraylist.internal.h"
#include "libc/calls/hefty/ntspawn.h"
#include "libc/dce.h"
#include "libc/nexgen32e/tinystrcmp.internal.h"
#include "libc/str/str.h"
static int CompareStrings(const char *l, const char *r) {

View File

@ -94,6 +94,6 @@ textwindows int spawnve$nt(unsigned flags, int stdiofds[3], const char *program,
g_fds.p[pid].kind = kFdProcess;
g_fds.p[pid].handle = handle;
g_fds.p[pid].flags = flags;
g_fds.p[pid].flags = O_CLOEXEC;
return pid;
}

View File

@ -252,6 +252,7 @@ int nanosleep$nt(const struct timespec *, struct timespec *) hidden;
cosmopolitan § syscalls » windows nt » support
*/
int64_t ntreturn(uint32_t);
void WinMainForked(void) hidden;
void *GetProcAddressModule(const char *, const char *) hidden;
int getsetpriority$nt(int, unsigned, int, int (*)(int));
@ -261,19 +262,9 @@ bool32 ntsetprivilege(i64, const char16_t *, u32) hidden;
bool32 onntconsoleevent$nt(u32) hidden;
void __winalarm(void *, uint32_t, uint32_t) hidden;
int ntaccesscheck(const char16_t *, u32) paramsnonnull() hidden;
i64 ntreturn(u32);
i64 __winerr(void) nocallback privileged;
#define mkntpath(PATH, PATH16) mkntpath2(PATH, -1u, PATH16)
#define mkntpath2(PATH, FLAGS, PATH16) \
({ \
int Count; \
asm("call\tmkntpath" \
: "=a"(Count), "=m"(*PATH16) \
: "D"(PATH), "S"(FLAGS), "d"(&PATH16[0]), "m"((PATH)[0]) \
: "cc"); \
Count; \
})
int64_t __winerr(void) nocallback privileged;
int __mkntpath(const char *, char16_t[hasatleast PATH_MAX - 16]) hidden;
int __mkntpath2(const char *, char16_t[hasatleast PATH_MAX - 16], int) hidden;
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § syscalls » drivers

View File

@ -25,8 +25,8 @@
textwindows int link$nt(const char *existingpath, const char *newpath) {
char16_t newpath16[PATH_MAX];
char16_t existingpath16[PATH_MAX];
if (mkntpath(existingpath, existingpath16) != -1 &&
mkntpath(newpath, newpath16) != -1) {
if (__mkntpath(existingpath, existingpath16) != -1 &&
__mkntpath(newpath, newpath16) != -1) {
if (CreateHardLink(newpath16, existingpath16, NULL)) {
return 0;
} else {

View File

@ -27,7 +27,7 @@
static textwindows noinline int mkdir$nt(const char *path, uint32_t mode) {
uint16_t path16[PATH_MAX];
if (mkntpath(path, path16) == -1) return -1;
if (__mkntpath(path, path16) == -1) return -1;
if (CreateDirectory(path16, NULL)) {
return 0;
} else {

View File

@ -17,8 +17,8 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/calls/ntmagicpaths.internal.h"
#include "libc/nexgen32e/tinystrcmp.internal.h"
#include "libc/str/oldutf16.internal.h"
#include "libc/str/str.h"
#include "libc/str/tpdecode.internal.h"
@ -30,19 +30,24 @@ textwindows static const char *FixNtMagicPath(const char *path,
const struct NtMagicPaths *mp = &kNtMagicPaths;
asm("" : "+r"(mp));
if (path[0] != '/') return path;
if (tinystrcmp(path, mp->devtty) == 0) {
if (strcmp(path, mp->devtty) == 0) {
if ((flags & O_ACCMODE) == O_RDONLY) {
return mp->conin;
} else if ((flags & O_ACCMODE) == O_WRONLY) {
return mp->conout;
}
}
if (tinystrcmp(path, mp->devnull) == 0) return mp->nul;
if (tinystrcmp(path, mp->devstdin) == 0) return mp->conin;
if (tinystrcmp(path, mp->devstdout) == 0) return mp->conout;
if (strcmp(path, mp->devnull) == 0) return mp->nul;
if (strcmp(path, mp->devstdin) == 0) return mp->conin;
if (strcmp(path, mp->devstdout) == 0) return mp->conout;
return path;
}
textwindows int __mkntpath(const char *path,
char16_t path16[hasatleast PATH_MAX - 16]) {
return __mkntpath2(path, path16, -1);
}
/**
* Copies path for Windows NT.
*
@ -56,9 +61,9 @@ textwindows static const char *FixNtMagicPath(const char *path,
* @return short count excluding NUL on success, or -1 w/ errno
* @error ENAMETOOLONG
*/
forcealignargpointer textwindows int mkntpath(
const char *path, unsigned flags,
char16_t path16[hasatleast PATH_MAX - 16]) {
textwindows int __mkntpath2(const char *path,
char16_t path16[hasatleast PATH_MAX - 16],
int flags) {
/*
* 1. Reserve +1 for NUL-terminator
* 2. Reserve +1 for UTF-16 overflow
@ -66,31 +71,14 @@ forcealignargpointer textwindows int mkntpath(
* 4. Reserve 10 for CreateNamedPipe "\\.\pipe\" prefix requirement
* 5. Reserve 13 for mkdir() i.e. 1+8+3+1, e.g. "\\ffffffff.xxx\0"
*/
int rc;
wint_t wc;
size_t i, j;
size_t i, n;
path = FixNtMagicPath(path, flags);
i = 0;
j = 0;
for (;;) {
if ((rc = tpdecode(&path[i], &wc)) == -1) {
path16[0] = u'\0';
return -1;
}
if (!wc) break;
i += (size_t)rc;
if (wc == '/') wc = '\\';
if (j + 1 /* utf-16 */ + 1 /* chdir() */ + 1 /* NUL */ < PATH_MAX - 16) {
if ((rc = pututf16(&path16[j], 2, wc, false)) == -1) {
path16[0] = u'\0';
return -1;
}
j += (size_t)rc;
} else {
path16[0] = u'\0';
return enametoolong();
n = tprecode8to16(path16, PATH_MAX - 16, path).ax;
if (n == PATH_MAX - 16 - 1) return enametoolong();
for (i = 0; i < n; ++i) {
if (path16[i] == '/') {
path16[i] = '\\';
}
}
path16[j] = u'\0';
return j;
return n;
}

View File

@ -20,7 +20,6 @@
#include "libc/assert.h"
#include "libc/calls/internal.h"
#include "libc/calls/ntmagicpaths.internal.h"
#include "libc/nexgen32e/tinystrcmp.internal.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/creationdisposition.h"
@ -31,6 +30,7 @@
#include "libc/nt/errors.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
@ -40,7 +40,7 @@ static textwindows int64_t open$nt$impl(const char *file, uint32_t flags,
uint32_t br;
int64_t handle;
char16_t file16[PATH_MAX];
if (mkntpath2(file, flags, file16) == -1) return -1;
if (__mkntpath2(file, file16, flags) == -1) return -1;
if ((handle = CreateFile(
file16,
(flags & 0xf000000f) | (/* this is needed if we mmap(rwx+cow)
@ -119,7 +119,7 @@ textwindows ssize_t open$nt(const char *file, uint32_t flags, int32_t mode) {
size_t fd;
if ((fd = __getemptyfd()) == -1) return -1;
if ((flags & O_ACCMODE) == O_RDWR &&
tinystrcmp(file, kNtMagicPaths.devtty) == 0) {
strcmp(file, kNtMagicPaths.devtty) == 0) {
return open$nt$console(&kNtMagicPaths, flags, mode, fd);
} else {
return open$nt$file(file, flags, mode, fd);

View File

@ -27,8 +27,8 @@
textwindows int rename$nt(const char *oldpath, const char *newpath) {
char16_t oldpath16[PATH_MAX];
char16_t newpath16[PATH_MAX];
if (mkntpath(oldpath, oldpath16) == -1 ||
mkntpath(newpath, newpath16) == -1) {
if (__mkntpath(oldpath, oldpath16) == -1 ||
__mkntpath(newpath, newpath16) == -1) {
return -1;
}
if (MoveFileEx(oldpath16, newpath16, kNtMovefileReplaceExisting)) {

View File

@ -23,7 +23,7 @@
textwindows int rmdir$nt(const char *path) {
uint16_t path16[PATH_MAX];
if (mkntpath(path, path16) == -1) return -1;
if (__mkntpath(path, path16) == -1) return -1;
if (RemoveDirectory(path16)) {
return 0;
} else {

View File

@ -31,7 +31,7 @@ textwindows int stat$nt(const char *path, struct stat *st) {
int rc;
int64_t fh;
uint16_t path16[PATH_MAX];
if (mkntpath(path, path16) == -1) return -1;
if (__mkntpath(path, path16) == -1) return -1;
if ((fh = CreateFile(
path16, kNtFileReadAttributes,
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, NULL,

View File

@ -24,8 +24,8 @@
textwindows int symlink$nt(const char *target, const char *linkpath) {
char16_t linkpath16[PATH_MAX], target16[PATH_MAX];
uint32_t flags = isdirectory(target) ? kNtSymbolicLinkFlagDirectory : 0;
if (mkntpath(linkpath, linkpath16) == -1) return -1;
if (mkntpath(target, target16) == -1) return -1;
if (__mkntpath(linkpath, linkpath16) == -1) return -1;
if (__mkntpath(target, target16) == -1) return -1;
if (CreateSymbolicLink(linkpath16, target16, flags)) {
return 0;
} else {

View File

@ -29,7 +29,7 @@ textwindows int truncate$nt(const char *path, uint64_t length) {
bool32 ok;
int64_t fh;
uint16_t path16[PATH_MAX];
if (mkntpath(path, path16) == -1) return -1;
if (__mkntpath(path, path16) == -1) return -1;
if ((fh = CreateFile(path16, kNtGenericWrite, kNtFileShareRead, NULL,
kNtOpenExisting, kNtFileAttributeNormal, 0)) != -1) {
ok = ftruncate$nt(fh, length);

View File

@ -23,7 +23,7 @@
textwindows int unlink$nt(const char *name) {
uint16_t name16[PATH_MAX];
if (mkntpath(name, name16) == -1) return -1;
if (__mkntpath(name, name16) == -1) return -1;
if (DeleteFile(name16)) {
return 0;
} else {

View File

@ -42,7 +42,7 @@ textwindows int utimensat$nt(int dirfd, const char *path,
if (flags) return einval();
if (path) {
if (dirfd == AT_FDCWD) {
if (mkntpath(path, path16) == -1) return -1;
if (__mkntpath(path, path16) == -1) return -1;
if ((fh = CreateFile(path16, kNtFileWriteAttributes, kNtFileShareRead,
NULL, kNtOpenExisting, kNtFileAttributeNormal, 0)) !=
-1) {

View File

@ -2,7 +2,7 @@
#define COSMOPOLITAN_LIBC_COMPLEX_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#if __STDC_VERSION__ + 0 >= 201112
#if __STDC_VERSION__ + 0 >= 201112 && !defined(__STDC_NO_COMPLEX__)
#define complex _Complex
#define imaginary _Imaginary

View File

@ -36,7 +36,7 @@ textstartup char *basename_n(const char *path, size_t size) {
if (size) {
if (isslash(path[size - 1])) {
l = size - 1;
while (isslash(path[l - 1])) --l;
while (l && isslash(path[l - 1])) --l;
if (!l) return (/*unconst*/ char *)&path[size - 1];
size = l;
}

View File

@ -51,6 +51,7 @@ long convertmicros(const struct timeval *, long) paramsnonnull() nosideeffect;
cosmopolitan § conversion » manipulation
*/
char *dirname(char *);
char *basename(const char *) nosideeffect;
char *basename_n(const char *, size_t) nosideeffect;
bool isabspath(const char *) paramsnonnull() nosideeffect;
@ -83,7 +84,7 @@ div_t div(int, int) pureconst;
ldiv_t ldiv(long, long) pureconst;
lldiv_t lldiv(long long, long long) pureconst;
imaxdiv_t imaxdiv(intmax_t, intmax_t) pureconst;
double RoundDecimalPlaces(double, double, double(double));
double RoundDecimalPlaces(double, double, double (*)(double));
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § conversion » optimizations

View File

@ -0,0 +1,42 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/conv/conv.h"
#include "libc/str/str.h"
#define ISDELIM(c) (c == '/' || c == '\\' || c == '.')
char *dirname(char *s) {
size_t i, n;
if (!(n = strlen(s))) return s;
while (n && ISDELIM(s[n - 1])) --n;
if (n) {
while (n && !ISDELIM(s[n - 1])) --n;
if (n) {
while (n && ISDELIM(s[n - 1])) --n;
if (!n) ++n;
} else {
s[n++] = '.';
}
} else {
++n;
}
s[n] = '\0';
return s;
}

View File

@ -41,21 +41,24 @@
*/
textwindows int getntnameservers(struct ResolvConf *resolv) {
int rc;
int64_t hkInterfaces = kNtInvalidHandleValue;
uint32_t keycount = 0;
char value8[128];
int64_t hkInterfaces;
struct sockaddr_in nameserver;
char16_t value[128], ifaceuuid[64];
uint32_t i, keycount, valuebytes, ifaceuuidlen;
keycount = 0;
hkInterfaces = kNtInvalidHandleValue;
if (!RegOpenKeyEx(
kNtHkeyLocalMachine,
u"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces",
0, kNtKeyRead, &hkInterfaces) &&
!RegQueryInfoKey(hkInterfaces, NULL, NULL, NULL, &keycount, NULL, NULL,
NULL, NULL, NULL, NULL, NULL)) {
struct sockaddr_in nameserver;
nameserver.sin_family = AF_INET;
nameserver.sin_port = htons(DNS_PORT);
rc = 0;
for (uint32_t i = 0; i < keycount; ++i) {
char16_t value[128], ifaceuuid[64];
uint32_t valuebytes, ifaceuuidlen = sizeof(ifaceuuid);
for (i = 0; i < keycount; ++i) {
ifaceuuidlen = sizeof(ifaceuuid);
if (!RegEnumKeyEx(hkInterfaces, i, ifaceuuid, &ifaceuuidlen, NULL, NULL,
NULL, NULL) &&
((!RegGetValue(hkInterfaces, ifaceuuid, u"DhcpIpAddress",
@ -74,7 +77,6 @@ textwindows int getntnameservers(struct ResolvConf *resolv) {
kNtRrfRtRegSz | kNtRrfRtRegMultiSz, NULL, value,
((valuebytes = sizeof(value)), &valuebytes)) &&
valuebytes > 2 * sizeof(char16_t)))) {
char value8[128];
tprecode16to8(value8, sizeof(value8), value);
if (inet_pton(AF_INET, value8, &nameserver.sin_addr.s_addr) == 1) {
if (append(&resolv->nameservers, &nameserver) != -1) ++rc;

View File

@ -38,7 +38,8 @@ static struct ResolvConfInitialStaticMemory {
const struct ResolvConf *getresolvconf(void) {
int rc;
FILE *f;
struct ResolvConfInitialStaticMemory *init = &g_resolvconf_init;
struct ResolvConfInitialStaticMemory *init;
init = &g_resolvconf_init;
if (!g_resolvconf) {
g_resolvconf = &init->rv;
pushmov(&init->rv.nameservers.n, ARRAYLEN(init->nameservers));

View File

@ -23,19 +23,18 @@
#include "libc/sock/sock.h"
#include "libc/sysv/consts/af.h"
#define SIZE ROUNDUP(sizeof(struct addrinfo), sizeof(void *))
#define ADDRLEN sizeof(struct sockaddr_in)
struct addrinfo *newaddrinfo(uint16_t port) {
void *mem;
struct addrinfo *ai = NULL;
/* shoehorning is ok since this'll never be realloc()'d */
uint32_t size = ROUNDUP(sizeof(struct addrinfo), sizeof(void *));
uint32_t addrlen = sizeof(struct sockaddr_in);
if ((ai = mem = calloc(1, size + addrlen + DNS_NAME_MAX + 1))) {
struct addrinfo *ai;
if ((ai = calloc(1, SIZE + ADDRLEN + DNS_NAME_MAX + 1))) {
ai->ai_family = AF_INET;
ai->ai_addrlen = addrlen;
ai->ai_addr4 = (struct sockaddr_in *)((char *)mem + size);
ai->ai_addrlen = ADDRLEN;
ai->ai_addr4 = (struct sockaddr_in *)((char *)ai + SIZE);
ai->ai_addr4->sin_family = AF_INET;
ai->ai_addr4->sin_port = htons(port);
ai->ai_canonname = (char *)mem + size + addrlen;
ai->ai_canonname = (char *)ai + SIZE + ADDRLEN;
}
return ai;
}

View File

@ -44,9 +44,10 @@
* @see hoststxtsort() which is the logical next step
*/
int parsehoststxt(struct HostsTxt *ht, FILE *f) {
int rc = 0;
int rc;
char *line;
size_t linesize;
rc = 0;
line = NULL;
linesize = 0;
while ((getline(&line, &linesize, f)) != -1) {

View File

@ -44,16 +44,17 @@
*/
int parseresolvconf(struct ResolvConf *resolv, struct FILE *f) {
/* TODO(jart): options ndots:5 */
int rc = 0;
int rc;
char *line;
size_t linesize;
struct sockaddr_in nameserver;
char *directive, *value, *tok, *comment;
rc = 0;
line = NULL;
linesize = 0;
nameserver.sin_family = AF_INET;
nameserver.sin_port = htons(DNS_PORT);
while (getline(&line, &linesize, f) != -1) {
char *directive, *value, *tok, *comment;
if ((comment = strchr(line, '#'))) *comment = '\0';
if ((directive = strtok_r(line, " \t\r\n\v", &tok)) &&
(value = strtok_r(NULL, " \t\r\n\v", &tok))) {

View File

@ -32,15 +32,14 @@
* @return bytes written (excluding NUL) or -1 w/ errno
*/
int pascalifydnsname(uint8_t *buf, size_t size, const char *name) {
size_t i = 0;
size_t namelen = strlen(name);
if (namelen > DNS_NAME_MAX) return enametoolong();
size_t i, j, k, namelen;
if ((namelen = strlen(name)) > DNS_NAME_MAX) return enametoolong();
i = 0;
if (size || namelen) {
if (namelen + 1 > size) return enospc();
buf[0] = '\0';
size_t j = 0;
j = 0;
for (;;) {
size_t k;
for (k = 0; name[j + k] && name[j + k] != '.'; ++k) {
buf[i + k + 1] = name[j + k];
}

View File

@ -18,7 +18,7 @@ struct ResolvConf {
const struct ResolvConf *getresolvconf(void) returnsnonnull;
int parseresolvconf(struct ResolvConf *, struct FILE *) paramsnonnull();
void freeresolvconf(struct ResolvConf **) paramsnonnull();
int getntnameservers(struct ResolvConf *resolv) paramsnonnull();
int getntnameservers(struct ResolvConf *) paramsnonnull();
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View File

@ -34,6 +34,8 @@
#include "libc/sysv/consts/sock.h"
#include "libc/sysv/errfuns.h"
#define kMsgMax 512
/**
* Queries Domain Name System for address associated with name.
*
@ -48,10 +50,15 @@
*/
int resolvedns(const struct ResolvConf *resolvconf, int af, const char *name,
struct sockaddr *addr, uint32_t addrsize) {
size_t msgsize;
int res, fd, rc, rc2;
struct sockaddr_in *addr4;
struct DnsQuestion question;
uint16_t rtype, rclass, rdlength;
uint8_t *p, *pe, *outmsg, *inmsg;
struct DnsHeader header, response;
if (af != AF_INET && af != AF_UNSPEC) return eafnosupport();
if (!resolvconf->nameservers.i) return 0;
struct DnsHeader header;
struct DnsQuestion question;
memset(&header, 0, sizeof(header));
header.id = rand32();
header.bf1 = 1; /* recursion desired */
@ -59,28 +66,21 @@ int resolvedns(const struct ResolvConf *resolvconf, int af, const char *name,
question.qname = name;
question.qtype = DNS_TYPE_A;
question.qclass = DNS_CLASS_IN;
const size_t kMsgMax = 512;
uint8_t *outmsg = NULL;
uint8_t *inmsg = NULL;
size_t msgsize;
int res = -1;
int rc, rc2;
res = -1;
if ((outmsg = malloc(kMsgMax)) && (inmsg = malloc(kMsgMax)) &&
(rc = serializednsheader(outmsg, kMsgMax, header)) != -1 &&
(rc2 = serializednsquestion(outmsg + rc, kMsgMax - rc, question)) != -1) {
msgsize = rc + rc2;
int fd;
if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1 &&
sendto(fd, outmsg, msgsize, 0, (void *)&resolvconf->nameservers.p[0],
sizeof(resolvconf->nameservers.p[0])) == msgsize) {
struct DnsHeader response;
if ((rc = recv(fd, inmsg, kMsgMax, 0)) != -1 &&
(rc2 = deserializednsheader(&response, inmsg, rc)) != -1 &&
response.id == header.id) {
res = 0;
if (response.ancount) {
uint8_t *p = inmsg + rc2;
uint8_t *pe = inmsg + rc;
p = inmsg + rc2;
pe = inmsg + rc;
while (p < pe && response.qdcount) {
p += strnlen((char *)p, pe - p) + 1 + 4;
response.qdcount--;
@ -92,7 +92,6 @@ int resolvedns(const struct ResolvConf *resolvconf, int af, const char *name,
p += strnlen((char *)p, pe - p) + 1;
}
if (p + 2 + 2 + 4 + 2 < pe) {
uint16_t rtype, rclass, rdlength;
rtype = READ16BE(p), p += 2;
rclass = READ16BE(p), p += 2;
/* ttl */ p += 4;
@ -102,7 +101,7 @@ int resolvedns(const struct ResolvConf *resolvconf, int af, const char *name,
res = 1;
if (addrsize) {
if (addrsize >= kMinSockaddr4Size) {
struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
addr4 = (struct sockaddr_in *)addr;
addr4->sin_family = AF_INET;
memcpy(&addr4->sin_addr.s_addr, p, 4);
} else {

View File

@ -23,8 +23,8 @@
#include "libc/dns/hoststxt.h"
#include "libc/sock/sock.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
#include "libc/sysv/consts/af.h"
#include "libc/sysv/errfuns.h"
static int hoststxtgetcmp(const char *node, const struct HostsTxtEntry *entry,
const char *strings) {
@ -50,14 +50,15 @@ static int hoststxtgetcmp(const char *node, const struct HostsTxtEntry *entry,
int resolvehoststxt(const struct HostsTxt *ht, int af, const char *name,
struct sockaddr *addr, uint32_t addrsize,
const char **canon) {
struct sockaddr_in *addr4;
struct HostsTxtEntry *entry;
if (af != AF_INET && af != AF_UNSPEC) return eafnosupport();
struct HostsTxtEntry *entry = bsearch_r(
name, ht->entries.p, ht->entries.i, sizeof(struct HostsTxtEntry),
(void *)hoststxtgetcmp, ht->strings.p);
if (entry) {
if ((entry = bsearch_r(name, ht->entries.p, ht->entries.i,
sizeof(struct HostsTxtEntry), (void *)hoststxtgetcmp,
ht->strings.p))) {
if (addr) {
if (addrsize < kMinSockaddr4Size) return einval();
struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
addr4 = (struct sockaddr_in *)addr;
addr4->sin_family = AF_INET;
memcpy(&addr4->sin_addr.s_addr, &entry->ip[0], 4);
}

View File

@ -26,6 +26,7 @@ LIBC_ELF_A_CHECKS = \
LIBC_ELF_A_DIRECTDEPS = \
LIBC_NEXGEN32E \
LIBC_STR \
LIBC_STUBS
LIBC_ELF_A_DEPS := \

View File

@ -2,7 +2,7 @@
#define __attribute__(x)
#endif
#ifdef __STRICT_ANSI__
#if defined(__STRICT_ANSI__) && __STDC_VERSION__ + 0 < 201112
#define asm __asm__
#endif
@ -16,7 +16,8 @@
*/
#if !defined(__GNUC__) && __cplusplus + 0 >= 201103L
#define typeof(x) decltype(x)
#elif defined(__STRICT_ANSI__) || !defined(__GNUC__)
#elif (defined(__STRICT_ANSI__) || !defined(__GNUC__)) && \
__STDC_VERSION__ + 0 < 201112
#define typeof(x) __typeof(x)
#endif
@ -123,7 +124,7 @@ typedef _Bool bool;
#endif
#endif
#if !defined(__cplusplus) && !defined(__STRICT_ANSI__)
#ifndef __cplusplus
typedef __WCHAR_TYPE__ wchar_t;
typedef __CHAR16_TYPE__ char16_t;
typedef __CHAR32_TYPE__ char32_t;
@ -159,7 +160,7 @@ typedef __UINT64_TYPE__ uint64_t;
* @see LISP primitives CONS[CAR,CDR] w/ IBM 704 naming
* @see int128_t
*/
typedef struct axdx_t {
typedef struct {
intptr_t ax, dx;
} axdx_t;
@ -194,11 +195,15 @@ typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
#endif
#ifdef __GNUC__
#define va_list __builtin_va_list
#define va_arg(ap, type) __builtin_va_arg(ap, type)
#define va_copy(dest, src) __builtin_va_copy(dest, src)
#define va_end(ap) __builtin_va_end(ap)
#define va_start(ap, last) __builtin_va_start(ap, last)
#else
#include "libc/integral/lp64arg.inc"
#endif
#define libcesque nothrow nocallback
#define memcpyesque libcesque
@ -366,7 +371,7 @@ typedef uint64_t uintmax_t;
#elif defined(_MSC_VER)
#define forceinline __forceinline
#else
#define forceinline static
#define forceinline static inline
#endif /* !ANSI && GCC >= 3.2 */
#endif /* __cplusplus */
#endif /* forceinline */
@ -1046,7 +1051,7 @@ typedef uint64_t uintmax_t;
* Pulls source file into ZIP portion of binary.
* @see build/rules.mk which defines the wildcard build rule %.zip.o
*/
#ifndef IM_FEELING_NAUGHTY
#if !defined(IM_FEELING_NAUGHTY) && !defined(__STRICT_ANSI__)
#define STATIC_YOINK_SOURCE(PATH) STATIC_YOINK(PATH)
#else
#define STATIC_YOINK_SOURCE(PATH)

View File

@ -46,6 +46,9 @@
#define __CHAR16_TYPE__ short unsigned int
#define __CHAR32_TYPE__ unsigned int
#define __WINT_TYPE__ unsigned int
#define __CHAR16_TYPE__ short unsigned int
#define __WCHAR_TYPE__ int
#define __CHAR32_TYPE__ unsigned int
#define __INT_LEAST8_TYPE__ __INT8_TYPE__
#define __UINT_LEAST8_TYPE__ __UINT8_TYPE__

View File

@ -0,0 +1,50 @@
typedef struct {
unsigned int gp_offset;
unsigned int fp_offset;
void *overflow_arg_area;
void *reg_save_area;
} __va_elem;
typedef __va_elem va_list[1];
#define va_start(ap, last) \
do { \
*(ap) = *(__va_elem *)__va_area__; \
} while (0)
#define va_end(ap)
static inline void *__va_arg_mem(__va_elem *ap, int sz, int align) {
void *p = ap->overflow_arg_area;
if (align > 8) p = (void *)(((unsigned long)p + 15) / 16 * 16);
ap->overflow_arg_area = (void *)(((unsigned long)p + sz + 7) / 8 * 8);
return p;
}
static inline void *__va_arg_gp(__va_elem *ap, int sz, int align) {
if (ap->gp_offset >= 48) return __va_arg_mem(ap, sz, align);
void *r = ap->reg_save_area + ap->gp_offset;
ap->gp_offset += 8;
return r;
}
static inline void *__va_arg_fp(__va_elem *ap, int sz, int align) {
if (ap->fp_offset >= 112) return __va_arg_mem(ap, sz, align);
void *r = ap->reg_save_area + ap->fp_offset;
ap->fp_offset += 8;
return r;
}
#define va_arg(ap, ty) \
({ \
int klass = __builtin_reg_class(ty); \
*(ty *)(klass == 0 \
? __va_arg_gp(ap, sizeof(ty), _Alignof(ty)) \
: klass == 1 ? __va_arg_fp(ap, sizeof(ty), _Alignof(ty)) \
: __va_arg_mem(ap, sizeof(ty), _Alignof(ty))); \
})
#define va_copy(dest, src) ((dest)[0] = (src)[0])
#define __GNUC_VA_LIST 1
typedef va_list __gnuc_va_list;

View File

@ -1,4 +1,4 @@
/*-*- mode:c; indent-tabs-mode:nil; tab-width:2; coding:utf-8 -*-│
/*-*- 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
@ -17,17 +17,18 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/str/str.h"
#include "libc/intrin/pdep.h"
int getkvlin(const char *name, const char *const unsorted[]) {
unsigned i, n;
if (unsorted) {
n = strlen(name);
for (i = 0; unsorted[i]; ++i) {
if (strncmp(unsorted[i], name, n) == 0 && unsorted[i][n] == '=') {
return i;
}
/**
* Parallel bit deposit.
*/
uint64_t(pdep)(uint64_t x, uint64_t mask) {
uint64_t r, b;
for (r = 0, b = 1; mask; mask >>= 1, b <<= 1) {
if (mask & 1) {
if (x & 1) r |= b;
x >>= 1;
}
}
return -1;
return r;
}

View File

@ -1,16 +1,21 @@
#ifndef COSMOPOLITAN_LIBC_INTRIN_PDEP_H_
#define COSMOPOLITAN_LIBC_INTRIN_PDEP_H_
#include "libc/nexgen32e/x86feature.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/* TODO(jart): Implement polyfill. */
#define pdep(NUMBER, BITMASK) \
uint64_t pdep(uint64_t, uint64_t) pureconst;
#define PDEP(NUMBER, BITMASK) \
({ \
typeof(BITMASK) ShuffledBits, Number = (NUMBER); \
asm("pdep\t%2,%1,%0" : "=r"(ShuffledBits) : "r"(Number), "rm"(BITMASK)); \
ShuffledBits; \
})
#define pdep(NUMBER, BITMASK) \
(!X86_HAVE(BMI2) ? pdep(NUMBER, BITMASK) : PDEP(NUMBER, BITMASK))
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_INTRIN_PDEP_H_ */

View File

@ -1,5 +1,5 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
@ -17,16 +17,18 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
#include "libc/intrin/pext.h"
towlower:
.leafprologue
.profilable
movslq %edi,%rax
cmpl $127,%eax
ja 1f
ezlea kToLower,cx
movzbl (%rcx,%rax),%eax
1: .leafepilogue
.endfn towlower,globl
.source __FILE__
/**
* Parallel bit extract.
*/
uint64_t(pext)(uint64_t x, uint64_t mask) {
uint64_t r, b;
for (r = 0, b = 1; mask; mask >>= 1, x >>= 1) {
if (mask & 1) {
if (x & 1) r |= b;
b <<= 1;
}
}
return r;
}

View File

@ -3,14 +3,18 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/* TODO(jart): Implement polyfill. */
#define pext(NUMBER, BITMASK) \
uint64_t pext(uint64_t, uint64_t) pureconst;
#define PEXT(NUMBER, BITMASK) \
({ \
typeof(BITMASK) ShuffledBits, Number = (NUMBER); \
asm("pext\t%2,%1,%0" : "=r"(ShuffledBits) : "r"(Number), "rm"(BITMASK)); \
ShuffledBits; \
})
#define pext(NUMBER, BITMASK) \
(!X86_HAVE(BMI2) ? pext(NUMBER, BITMASK) : PEXT(NUMBER, BITMASK))
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_INTRIN_PEXT_H_ */

View File

@ -52,6 +52,7 @@ bool isrunningundermake(void);
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § liblog » logging
*/
#ifndef __STRICT_ANSI__
extern unsigned g_loglevel; /* log level for runtime check */
@ -223,6 +224,7 @@ void vffatalf(ARGS, va_list) asm("vflogf") ATTRV relegated noreturn libcesque;
#undef ATTR
#undef ATTRV
#endif /* __STRICT_ANSI__ */
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_LOG_LOG_H_ */

View File

@ -33,7 +33,7 @@
#define __STRINGIFY(A) #A
#define __PASTE(A, B) A##B
#ifdef __ASSEMBLER__
#include "libc/macros-cpp.inc"
#include "libc/macros.inc"
#include "libc/macros-cpp.internal.inc"
#include "libc/macros.internal.inc"
#endif /* __ASSEMBLER__ */
#endif /* COSMOPOLITAN_LIBC_MACROS_H_ */

View File

@ -46,7 +46,7 @@
#define FLT_MIN_10_EXP __FLT_MIN_10_EXP__
#define FLT_MIN_EXP __FLT_MIN_EXP__
#define HLF_MAX 6.50e4f
#define HLF_MIN 3.10e5f
#define HLF_MIN 3.10e-5f
#define LDBL_DECIMAL_DIG __LDBL_DECIMAL_DIG__
#define LDBL_DIG __LDBL_DIG__
#define LDBL_EPSILON __LDBL_EPSILON__

View File

@ -1,39 +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
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Returns true if architecture guarantees atomicity.
/
/ @param rdi is byte width of type
/ @param rsi is optional pointer for alignment check
/ @see Intel's Six Thousand Page Manual V.3A §8.2.3.1
__atomic_is_lock_free:
.leafprologue
.profilable
xor %ecx,%ecx
pushpop 1,%rax
cmp $7,%rdi
cmova %ecx,%eax
dec %edi
and %edi,%esi
cmovnz %ecx,%eax
.leafepilogue
.endfn __atomic_is_lock_free,globl,hidden
.source __FILE__

View File

@ -1,33 +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
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Compares memory.
/
/ This API was thought to be nearly extinct until recent versions
/ of Clang (c. 2019) started generating synthetic calls to it.
/
/ @param edi first string
/ @param esi second string
/ @param edx byte size
/ @return 0 if equal or nonzero
bcmp: jmp *__memcmp(%rip)
.endfn bcmp,globl
.source __FILE__

View File

@ -1,31 +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
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Copies memory.
/
/ DEST and SRC may overlap.
/
/ @param rdi is dest
/ @param rsi is src
/ @param rdx is number of bytes
bcopy: jmp memmove
.endfn bcopy,globl
.source __FILE__

View File

@ -1,35 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.initbss 300,_init_kToUpper
kToUpper:
.zero 256
.endobj kToUpper,globl,hidden
.previous
.init.start 300,_init_kToUpper
lea 'a(%rdi),%r8
call imapxlatab
pushpop 'z-'a,%rcx
0: subb $0x20,(%r8,%rcx)
.loop 0b
.init.end 300,_init_kToUpper
.source __FILE__

View File

@ -1,7 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_MACROS_H_
#define COSMOPOLITAN_LIBC_NEXGEN32E_MACROS_H_
#ifdef __ASSEMBLER__
#include "libc/nexgen32e/macros.inc"
#include "libc/nexgen32e/macros.internal.inc"
#else
/* let's give auto-import tooling a helping hand */

View File

@ -1,65 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Compares memory bytes.
/
/ @param rdi is first uint8_t array
/ @param rsi is second uint8_t array
/ @param rdx is max bytes to consider
/ @return unsigned char subtraction at stop index
/ @note AVX2 requires Haswell (2014+) or Excavator (2015+)
/ @see libc/nexgen32e/memcmp.S (for benchmarks)
/ @asyncsignalsafe
.align 16
memcmp$avx2:
.leafprologue
.profilable
cmp %rsi,%rdi
je 7f
test %rdx,%rdx
jz 7f
mov %rdx,%r8
shr $5,%r8
add $1,%r8
mov $-32,%rcx
1: add $32,%rcx
sub $1,%r8
jz 5f
vmovdqu (%rdi,%rcx),%ymm0
vpcmpeqb (%rsi,%rcx),%ymm0,%ymm0
vpmovmskb %ymm0,%eax
sub $0xffffffff,%eax
jz 1b
tzcnt %eax,%eax
add %rax,%rcx
5: cmp %rcx,%rdx
je 7f
inc %rcx
movzbl -1(%rdi,%rcx),%eax
movzbl -1(%rsi,%rcx),%r8d
sub %r8d,%eax
jz 5b
jmp 8f
7: xor %eax,%eax
8: vpxor %ymm0,%ymm0,%ymm0
.leafepilogue
.endfn memcmp$avx2,globl,hidden
.source __FILE__

View File

@ -1,50 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/x86feature.h"
#include "libc/dce.h"
#include "libc/macros.h"
/ Dispatches to fastest memcmp() implementation.
/
/ @param edi first string
/ @param esi second string
/ @param edx byte size
/ @return unsigned char subtraction at stop index
/ @asyncsignalsafe
.initbss 300,_init_memcmp
__memcmp:
.quad 0
.endobj __memcmp,globl,hidden
.previous
.init.start 300,_init_memcmp
#if !IsTiny()
ezlea memcmp$avx2,ax
#if !X86_NEED(AVX2)
ezlea memcmp$sse2,dx
testb X86_HAVE(AVX2)+kCpuids(%rip)
cmovz %rdx,%rax
#endif /* AVX */
#else
ezlea memcmp$sse2,ax
#endif /* TINY */
stosq
.init.end 300,_init_memcmp
.source __FILE__

View File

@ -1,62 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Compares memory.
/
/ @param rdi is first uint8_t array
/ @param rsi is second uint8_t array
/ @param rdx is max bytes to consider
/ @return unsigned char subtraction at stop index
/ @asyncsignalsafe
memcmp$sse2:
.leafprologue
.profilable
cmp %rsi,%rdi
je 7f
test %rdx,%rdx
jz 7f
mov %rdx,%r8
shr $4,%r8
add $1,%r8
mov $-16,%rcx
1: add $16,%rcx
sub $1,%r8
jz 5f
movdqu (%rdi,%rcx),%xmm0
movdqu (%rsi,%rcx),%xmm1
pcmpeqb %xmm1,%xmm0
pmovmskb %xmm0,%eax
sub $0xffff,%eax
jz 1b
bsf %eax,%eax
add %rax,%rcx
5: cmp %rcx,%rdx
je 7f
inc %rcx
movzbl -1(%rdi,%rcx),%eax
movzbl -1(%rsi,%rcx),%r8d
sub %r8d,%eax
jz 5b
jmp 8f
7: xor %eax,%eax
8: .leafepilogue
.endfn memcmp$sse2,globl,hidden
.source __FILE__

View File

@ -1,206 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Compares memory.
/
/ @param edi first string
/ @param esi second string
/ @param edx byte size
/ @return unsigned char subtraction at stop index
/ @asyncsignalsafe
memcmp: jmp *__memcmp(%rip)
.endfn memcmp,globl
.source __FILE__
/* cosmo memcmp() avx2 for #c per n where c 0.273ns
N x1 x8 x64 mBps
------------------------------------------------------------
1 61.000 39.375 36.984 95
1 37.000 37.625 37.391 94
2 28.500 19.688 19.930 175
3 20.333 13.625 14.411 243
4 30.250 10.656 10.426 335
7 15.000 7.304 6.136 570
8 10.125 6.234 5.525 633
15 9.133 3.542 3.570 980
16 6.062 4.398 3.577 977
31 4.548 2.931 2.340 1494
32 2.594 1.520 1.492 2344
63 3.444 1.240 1.221 2864
64 1.328 0.736 0.742 4713
127 1.661 0.710 0.605 5778
128 0.820 0.452 0.396 8822
255 0.639 0.360 0.347 10080
256 0.434 0.250 0.220 15874
511 0.413 0.218 0.199 17612
512 0.201 0.176 0.138 25377
1023 0.216 0.142 0.125 28031
1024 0.132 0.097 0.096 36276
2047 0.125 0.091 0.091 38466
2048 0.093 0.079 0.075 46365
4095 0.084 0.081 0.078 44705
4096 0.069 0.069 0.069 50819
8191 0.070 0.068 0.067 51841
8192 0.063 0.062 0.062 56633
16383 0.066 0.063 0.061 56994
16384 0.059 0.058 0.058 60021
32767 0.131 0.104 0.100 34909
32768 0.120 0.084 0.079 44282
cosmo memcmp() sse2 (old cpu) for #c per n where c 0.273ns
N x1 x8 x64 mBps
------------------------------------------------------------
1 59.000 37.125 37.328 94
1 35.000 37.375 36.359 96
2 28.500 18.938 20.461 171
3 19.000 12.875 13.234 264
4 29.250 10.906 10.348 338
7 11.571 6.304 6.404 546
8 8.125 5.672 5.713 612
15 11.533 4.492 3.759 930
16 5.812 3.227 2.876 1216
31 5.516 2.367 1.797 1946
32 2.969 1.816 1.481 2361
63 3.413 0.990 0.929 3763
64 1.703 0.850 0.763 4580
127 1.614 0.531 0.533 6556
128 0.961 0.438 0.426 8205
255 0.922 0.378 0.325 10745
256 0.457 0.322 0.268 13035
511 0.331 0.253 0.216 16223
512 0.287 0.212 0.189 18460
1023 0.220 0.172 0.164 21378
1024 0.198 0.159 0.150 23357
2047 0.161 0.152 0.150 23271
2048 0.147 0.139 0.136 25732
4095 0.135 0.130 0.129 27157
4096 0.129 0.123 0.123 28499
8191 0.122 0.116 0.116 30110
8192 0.116 0.113 0.113 30863
16383 0.117 0.112 0.112 31311
16384 0.111 0.110 0.110 31802
32767 0.157 0.138 0.136 25653
32768 0.144 0.121 0.118 29590
glibc memcmp() for #c per n where c 0.273ns
N x1 x8 x64 mBps
------------------------------------------------------------
1 6875.000 39.125 35.141 100
1 33.000 35.375 35.078 100
2 138.500 20.312 18.570 188
3 26.333 13.958 12.536 279
4 53.250 12.094 9.512 368
7 13.571 5.554 5.708 613
8 19.625 5.328 5.057 691
15 6.867 3.075 2.801 1248
16 9.062 2.555 2.526 1384
31 4.484 1.319 1.313 2663
32 3.906 1.285 1.299 2691
63 2.143 0.863 0.719 4867
64 1.234 0.814 0.718 4873
127 2.071 0.493 0.428 8174
128 0.523 0.427 0.421 8310
255 0.882 0.302 0.250 13983
256 0.465 0.258 0.266 13143
511 0.417 0.189 0.164 21339
512 0.209 0.170 0.160 21862
1023 0.320 0.120 0.111 31391
1024 0.128 0.115 0.112 31106
2047 0.110 0.092 0.088 39803
2048 0.098 0.088 0.086 40837
4095 0.093 0.078 0.076 46281
4096 0.081 0.076 0.075 46400
8191 0.080 0.071 0.069 50984
8192 0.075 0.069 0.069 50970
16383 0.083 0.071 0.068 51591
16384 0.072 0.071 0.068 51736
32767 0.145 0.136 0.121 28805
32768 0.145 0.139 0.137 25469
musl memcmp() for #c per n where c 0.273ns
N x1 x8 x64 mBps
------------------------------------------------------------
1 55.000 37.625 34.484 101
1 35.000 33.625 34.203 102
2 37.500 24.562 18.648 188
3 20.333 13.625 12.766 274
4 32.750 11.531 9.527 367
7 12.714 8.482 5.828 600
8 13.125 6.234 5.330 656
15 9.000 4.892 3.391 1031
16 5.188 4.102 3.335 1048
31 4.806 2.899 2.295 1524
32 4.406 2.801 2.208 1584
63 3.794 1.808 1.689 2070
64 2.672 1.994 1.675 2088
127 1.961 1.739 1.648 2122
128 2.055 1.610 1.614 2167
255 1.463 1.381 1.401 2496
256 1.457 1.362 1.385 2525
511 1.286 1.351 1.226 2853
512 1.256 1.255 1.253 2791
1023 1.207 1.184 1.180 2964
1024 1.204 1.146 1.174 2978
2047 1.134 1.126 1.152 3036
2048 1.134 1.123 1.149 3044
4095 1.124 1.108 1.138 3074
4096 1.117 1.107 1.136 3077
8191 1.106 1.103 1.102 3174
8192 1.105 1.102 1.267 2760
16383 1.110 1.103 1.099 3182
16384 1.108 1.100 1.098 3184
32767 1.101 1.097 1.126 3105
32768 1.128 1.130 1.126 3105
newlib memcmp() for #c per n where c 0.273ns
N x1 x8 x64 mBps
------------------------------------------------------------
1 73.000 39.625 36.297 96
1 35.000 35.375 35.328 99
2 41.500 19.438 18.508 189
3 29.667 13.542 13.005 269
4 22.750 10.656 10.332 338
7 14.714 6.875 6.248 560
8 18.125 6.453 5.846 598
15 11.533 3.575 3.547 986
16 8.062 3.461 2.880 1214
31 3.839 2.931 2.689 1300
32 5.594 1.848 1.589 2200
63 3.667 2.387 2.242 1560
64 2.078 1.170 0.842 4153
127 2.228 2.111 2.126 1644
128 1.617 0.669 0.510 6858
255 2.059 1.960 1.964 1781
256 0.590 0.398 0.335 10452
511 1.841 1.814 1.811 1931
512 0.373 0.275 0.252 13860
1023 1.788 1.748 2.426 1441
1024 0.261 0.230 0.226 15474
2047 1.745 1.731 1.774 1971
2048 0.218 0.199 0.197 17741
4095 1.771 1.764 1.763 1983
4096 0.187 0.177 0.181 19353
8191 1.722 1.714 1.714 2040
8192 0.173 0.174 0.173 20252
16383 1.754 1.754 1.845 1895
16384 0.175 0.171 0.169 20692
32767 1.753 1.753 1.753 1995
32768 0.186 0.173 0.170 20510 */

View File

@ -1,49 +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
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "ape/macros.h"
#include "libc/nexgen32e/uart.internal.h"
#include "libc/notice.inc"
.real
.code16 # .code32 .code64
/ Receives byte over serial line.
/
/ This is both blocking and asynchronous.
/
/ @param di serial port
/ @return ax character received
/ @mode long,legacy,real
/ @see ttytxr
sgetc: push %bp
mov %sp,%bp
mov %di,%dx
add $UART_LSR,%dx
mov $UART_TTYDA,%ah
1: in %dx,%al
and %ah,%al
rep nop # todo(jart): interrupts are better
jz 1b
mov %di,%dx
xor %ax,%ax
in %dx,%al
pop %bp
ret
.endfn sgetc,globl
.source __FILE__

View File

@ -1,66 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Compares NUL-terminated strings, ignoring ASCII case.
/
/ @param rdi first string
/ @param rsi second string
/ @return 0 if equal, etc.
/ @note char is treated as unsigned
strcasecmp:
or $-1,%rdx
/ fallthrough
.endfn strcasecmp,globl
/ Compares NUL-terminated strings w/ limit ignoring ASCII case.
/
/ @param rdi first string
/ @param rsi second string
/ @param rdx max bytes
/ @return 0 if equal, etc.
/ @note char is treated as unsigned
strncasecmp:
.leafprologue
.profilable
push %rbx
cmp %rdi,%rsi
je 3f
ezlea kToLower,bx
or $-1,%rcx
1: add $1,%rcx
cmp %rcx,%rdx
je 3f
movzbl (%rdi,%rcx),%r8d
movzbl (%rsi,%rcx),%eax
xlat
xchg %r8d,%eax
xlat
cmp %r8b,%al
jne 2f
test %al,%al
jnz 1b
2: sub %r8d,%eax
jmp 4f
3: xor %eax,%eax
4: pop %rbx
.leafepilogue
.endfn strncasecmp,globl
.source __FILE__

View File

@ -1,72 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Compares NUL-terminated char16_t strings, ignoring ASCII case.
/
/ @param rdi first string
/ @param rsi second string
/ @return 0 if equal, etc.
/ @note char16_t is an unsigned type
strcasecmp16:
or $-1,%rdx
/ fallthrough
.endfn strcasecmp16,globl
/ Compares NUL-terminated char16_t strings w/ limit ignoring ASCII case.
/
/ @param rdi first string
/ @param rsi second string
/ @param rdx max shorts
/ @return 0 if equal, etc.
/ @note char16_t is an unsigned type
strncasecmp16:
.leafprologue
.profilable
push %rbx
cmp %rdi,%rsi
je 3f
or $-1,%rcx
1: add $1,%rcx
cmp %rcx,%rdx
je 3f
movzwl (%rsi,%rcx,2),%eax
mov %eax,%ebx
and $0x7f,%ebx
cmp %eax,%ebx
cmove kToLower16(,%rbx,2),%ax
push %rax
movzwl (%rdi,%rcx,2),%eax
mov %eax,%ebx
and $0x7f,%ebx
cmp %eax,%ebx
cmove kToLower16(,%rbx,2),%ax
pop %rbx
cmp %ebx,%eax
jne 2f
test %eax,%eax
jnz 1b
2: sub %ebx,%eax
jmp 4f
3: xor %eax,%eax
4: pop %rbx
.leafepilogue
.endfn strncasecmp16,globl
.source __FILE__

View File

@ -1,90 +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
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Compares NUL-terminated strings w/ AVX (2011+)
/
/ @param rdi first string
/ @param rsi second string
/ @return 0 if equal, etc.
/ @asyncsignalsafe
strcmp$avx:
or $-1,%rdx
/ fallthrough
.endfn strcmp$avx,globl,hidden
/ Compares NUL-terminated strings, with byte limit.
/
/ @param rdi first string
/ @param rsi second string
/ @param rdx maximum number of bytes to compare
/ @return 0 if equal, etc.
/ @asyncsignalsafe
strncmp$avx:
.leafprologue
.profilable
cmp %rsi,%rdi
je 1f
mov $-16,%rcx
vpxor %xmm0,%xmm0,%xmm0
vpcmpeqd %xmm1,%xmm1,%xmm1
3: add $16,%rcx
4: lea 16(%rcx),%rax
cmp %rdx,%rax
ja 9f
lea (%rdi,%rcx),%eax
and $0xfff,%eax
cmp $0xff0,%eax
ja 9f
lea (%rsi,%rcx),%eax
and $0xfff,%eax
cmp $0xff0,%eax
jbe 7f
9: cmpq %rcx,%rdx
je 1f
movzbl (%rdi,%rcx),%r8d
movzbl (%rsi,%rcx),%r9d
mov %r8d,%eax
sub %r9d,%eax
testl %r8d,%r8d
je 5f
incq %rcx
testl %eax,%eax
je 4b
jmp 5f
1: xor %eax,%eax
5: .leafepilogue
7: vmovdqu (%rsi,%rcx),%xmm3
vpcmpeqb (%rdi,%rcx),%xmm3,%xmm2
vpcmpeqb %xmm0,%xmm3,%xmm3
vpandn %xmm1,%xmm2,%xmm2
vpor %xmm3,%xmm2,%xmm2
vpmovmskb %xmm2,%eax
bsf %eax,%eax
jz 3b
mov %eax,%edx
add %rdx,%rdi
movzbl (%rcx,%rdi),%eax
add %rdx,%rsi
movzbl (%rcx,%rsi),%ecx
sub %ecx,%eax
jmp 5b
.endfn strncmp$avx,globl,hidden
.source __FILE__

View File

@ -1,49 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/x86feature.h"
#include "libc/dce.h"
#include "libc/macros.h"
/ Dispatches to fastest strcmp() implementation.
/
/ @param rdi is first non-null NUL-terminated string pointer
/ @param rsi is second non-null NUL-terminated string pointer
/ @return rax is <0, 0, or >0 based on uint8_t comparison
/ @asyncsignalsafe
.initbss 300,_init_strcmp
hook$strcmp:
.quad 0
.endobj hook$strcmp,globl,hidden
.previous
.init.start 300,_init_strcmp
#if !IsTiny()
ezlea strcmp$avx,ax
#if !X86_NEED(AVX)
ezlea tinystrcmp,dx
testb X86_HAVE(AVX)+kCpuids(%rip)
cmovz %rdx,%rax
#endif /* AVX */
#else
ezlea tinystrcmp,ax
#endif /* TINY */
stosq
.init.end 300,_init_strcmp
.source __FILE__

View File

@ -1,31 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Compares NUL-terminated strings.
/
/ @param rdi is first non-null NUL-terminated string pointer
/ @param rsi is second non-null NUL-terminated string pointer
/ @return rax is <0, 0, or >0 based on uint8_t comparison
/ @note cosmopolitan headers optimize away this indirection
/ @asyncsignalsafe
strcmp: jmp *hook$strcmp(%rip)
.endfn strcmp,globl
.source __FILE__

View File

@ -1,39 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
#include "libc/notice.inc"
/ Dispatches to fastest strcmp16() implementation.
/
/ @param rdi is first non-null NUL-terminated char16_t string
/ @param rsi is second non-null NUL-terminated char16_t string
/ @return rax is <0, 0, or >0 based on uint16_t comparison
/ @asyncsignalsafe
.initbss 300,_init_strcmp16
hook$strcmp16:
.quad 0
.endobj hook$strcmp16,globl,hidden
.previous
.init.start 300,_init_strcmp16
ezlea strcmp16$k8,ax
stosq
.init.end 300,_init_strcmp16
.source __FILE__

View File

@ -1,66 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Compares NUL-terminated char16_t strings.
/
/ @param rdi first string
/ @param rsi second string
/ @return 0 if equal, etc.
/ @note char16_t is an unsigned type
/ @asyncsignalsafe
strcmp16$k8:
or $-1,%rdx
/ fallthrough
.endfn strcmp16$k8,globl,hidden
/ Compares NUL-terminated char16_t strings w/ limit.
/
/ @param rdi first string
/ @param rsi second string
/ @param rdx max shorts
/ @return 0 if equal, etc.
/ @note char16_t is an unsigned type
/ @asyncsignalsafe
strncmp16$k8:
.leafprologue
.profilable
push %rbx
xor %eax,%eax
xor %ebx,%ebx
xor %ecx,%ecx
cmp %rdi,%rsi
je 1f
test %rdx,%rdx
jz 1f
0: inc %rcx
movzwl -2(%rdi,%rcx,2),%eax
movzwl -2(%rsi,%rcx,2),%ebx
cmp %rcx,%rdx
je 1f
cmp %ebx,%eax
jne 1f
test %eax,%eax
jne 0b
1: sub %ebx,%eax
pop %rbx
.leafepilogue
.endfn strncmp16$k8,globl,hidden
.source __FILE__

View File

@ -1,33 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Compares NUL-terminated char16_t strings.
/
/ @param rdi is first non-null NUL-terminated char16_t string
/ @param rsi is second non-null NUL-terminated char16_t string
/ @param rdx is maximum shorts to consider
/ @return rax is <0, 0, or >0 based on uint16_t comparison
/ @note cosmopolitan headers optimize away this indirection
/ @asyncsignalsafe
strcmp16:
jmp *hook$strcmp16(%rip)
.endfn strcmp16,globl
.source __FILE__

View File

@ -1,49 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/x86feature.h"
#include "libc/dce.h"
#include "libc/macros.h"
/ Dispatches to fastest strncmp() implementation.
/
/ @param rdi is first non-null NUL-terminated string pointer
/ @param rsi is second non-null NUL-terminated string pointer
/ @param rdx is maximum bytes to consider
/ @return rax is <0, 0, or >0 based on uint8_t comparison
.initbss 300,_init_strncmp
hook$strncmp:
.quad 0
.endobj hook$strncmp,globl,hidden
.previous
.init.start 300,_init_strncmp
#if !IsTiny()
ezlea strncmp$avx,ax
#if !X86_NEED(AVX)
ezlea tinystrncmp,dx
testb X86_HAVE(AVX)+kCpuids(%rip)
cmovz %rdx,%rax
#endif /* AVX */
#else
ezlea tinystrncmp,ax
#endif /* TINY */
stosq
.init.end 300,_init_strncmp
.source __FILE__

View File

@ -1,31 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Compares NUL-terminated strings, with btye limit.
/
/ @param rdi is first non-null NUL-terminated string pointer
/ @param rsi is second non-null NUL-terminated string pointer
/ @return rax is <0, 0, or >0 based on uint8_t comparison
/ @note cosmopolitan headers optimize away this indirection
/ @asyncsignalsafe
strncmp:jmp *hook$strncmp(%rip)
.endfn strncmp,globl
.source __FILE__

View File

@ -1,39 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
#include "libc/notice.inc"
/ Dispatches to fastest strncmp16() implementation.
/
/ @param rdi is first non-null NUL-terminated char16_t string
/ @param rsi is second non-null NUL-terminated char16_t string
/ @param rdx is maximum shorts to consider
/ @return rax is <0, 0, or >0 based on uint16_t comparison
.initbss 300,_init_strncmp16
hook$strncmp16:
.quad 0
.endobj hook$strncmp16,globl,hidden
.previous
.init.start 300,_init_strncmp16
ezlea strncmp16$k8,ax
stosq
.init.end 300,_init_strncmp16
.source __FILE__

View File

@ -1,32 +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
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Compares NUL-terminated char16_t strings w/ limit.
/
/ @param rdi is first non-null NUL-terminated char16_t string
/ @param rsi is second non-null NUL-terminated char16_t string
/ @param rdx is maximum shorts to consider
/ @return rax is <0, 0, or >0 based on uint16_t comparison
/ @note cosmopolitan headers optimize away this indirection
strncmp16:
jmp *hook$strncmp16(%rip)
.endfn strncmp16,globl
.source __FILE__

View File

@ -1,51 +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
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Compares strings w/ no-clobber greg abi.
/
/ @param rdi is first non-null NUL-terminated string pointer
/ @param rsi is second non-null NUL-terminated string pointer
/ @return rax is <0, 0, or >0 based on uint8_t comparison
/ @clob flags only
/ @asyncsignalsafe
tinystrcmp:
.leafprologue
push %rcx
push %rdx
xor %eax,%eax
xor %edx,%edx
xor %ecx,%ecx
cmp %rdi,%rsi
je 1f
0: movzbl (%rdi,%rcx,1),%eax
movzbl (%rsi,%rcx,1),%edx
test %al,%al
jz 1f
cmp %dl,%al
jne 1f
inc %rcx
jmp 0b
1: sub %edx,%eax
pop %rdx
pop %rcx
.leafepilogue
.endfn tinystrcmp,globl
.source __FILE__

View File

@ -1,33 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_TINYSTRCMP_H_
#define COSMOPOLITAN_LIBC_NEXGEN32E_TINYSTRCMP_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
int tinystrcmp(const char *, const char *) nothrow nocallback
paramsnonnull() nosideeffect;
int tinystrncmp(const char *, const char *, size_t) nothrow nocallback
paramsnonnull() nosideeffect;
#define tinystrcmp(s1, s2) \
({ \
int Res; \
asm("call\ttinystrcmp" \
: "=a"(Res) \
: "D"(&(s1)[0]), "S"(&(s2)[0]), "m"(*(s1)), "m"(*(s2)) \
: "cc"); \
Res; \
})
#define tinystrncmp(s1, s2, n) \
({ \
int Res; \
asm("call\ttinystrncmp" \
: "=a"(Res) \
: "D"(&(s1)[0]), "S"(&(s2)[0]), "d"(n), "m"(*(s1)), "m"(*(s2)) \
: "cc"); \
Res; \
})
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_TINYSTRCMP_H_ */

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