Make improvements
parent
3e4fd4b0ad
commit
e44a0cf6f8
2
Makefile
2
Makefile
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
136
examples/acid2.c
136
examples/acid2.c
|
@ -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("A");
|
||||
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;
|
||||
}
|
|
@ -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
|
||||
*/
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -96,5 +96,3 @@ error:
|
|||
free(cmdline_p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#undef APPENDCHAR
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 ─╬─│┼
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 ─╬─│┼
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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))) {
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ LIBC_ELF_A_CHECKS = \
|
|||
|
||||
LIBC_ELF_A_DIRECTDEPS = \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS
|
||||
|
||||
LIBC_ELF_A_DEPS := \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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.10e–5f
|
||||
#define HLF_MIN 3.10e-5f
|
||||
#define LDBL_DECIMAL_DIG __LDBL_DECIMAL_DIG__
|
||||
#define LDBL_DIG __LDBL_DIG__
|
||||
#define LDBL_EPSILON __LDBL_EPSILON__
|
||||
|
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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 */
|
||||
|
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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 */
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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
Loading…
Reference in New Issue