mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-28 07:18:30 +00:00
Make minor improvements
- Work towards simplifying ape.S startup process - Rewrote ar because it took minutes to build cosmopolitan.a
This commit is contained in:
parent
95bc650be8
commit
aea89fe832
70 changed files with 1037 additions and 456 deletions
|
@ -148,6 +148,36 @@ unsigned long hamming(unsigned long, unsigned long) pureconst;
|
|||
Ple[7] = (uint8_t)(Vle >> 070); \
|
||||
} while (0)
|
||||
|
||||
#define WRITE16BE(P, V) \
|
||||
do { \
|
||||
uint8_t *Ple = (uint8_t *)(P); \
|
||||
uint16_t Vle = (V); \
|
||||
Ple[1] = (uint8_t)(Vle >> 000); \
|
||||
Ple[0] = (uint8_t)(Vle >> 010); \
|
||||
} while (0)
|
||||
#define WRITE32BE(P, V) \
|
||||
do { \
|
||||
uint8_t *Ple = (uint8_t *)(P); \
|
||||
uint32_t Vle = (V); \
|
||||
Ple[3] = (uint8_t)(Vle >> 000); \
|
||||
Ple[2] = (uint8_t)(Vle >> 010); \
|
||||
Ple[1] = (uint8_t)(Vle >> 020); \
|
||||
Ple[0] = (uint8_t)(Vle >> 030); \
|
||||
} while (0)
|
||||
#define WRITE64BE(P, V) \
|
||||
do { \
|
||||
uint8_t *Ple = (uint8_t *)(P); \
|
||||
uint64_t Vle = (V); \
|
||||
Ple[7] = (uint8_t)(Vle >> 000); \
|
||||
Ple[6] = (uint8_t)(Vle >> 010); \
|
||||
Ple[5] = (uint8_t)(Vle >> 020); \
|
||||
Ple[4] = (uint8_t)(Vle >> 030); \
|
||||
Ple[3] = (uint8_t)(Vle >> 040); \
|
||||
Ple[2] = (uint8_t)(Vle >> 050); \
|
||||
Ple[1] = (uint8_t)(Vle >> 060); \
|
||||
Ple[0] = (uint8_t)(Vle >> 070); \
|
||||
} while (0)
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § bits » some assembly required ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
|
|
@ -79,12 +79,12 @@ bool isexecutable(const char *);
|
|||
bool isregularfile(const char *);
|
||||
bool32 isatty(int) nosideeffect;
|
||||
bool32 ischardev(int) nosideeffect;
|
||||
char *commandv(const char *, char[hasatleast PATH_MAX]);
|
||||
char *get_current_dir_name(void) nodiscard;
|
||||
char *getcwd(char *, size_t);
|
||||
char *realpath(const char *, char *);
|
||||
char *replaceuser(const char *) nodiscard;
|
||||
char *ttyname(int);
|
||||
char *commandv(const char *, char[hasatleast PATH_MAX]);
|
||||
int access(const char *, int) nothrow;
|
||||
int arch_prctl();
|
||||
int chdir(const char *);
|
||||
|
@ -120,6 +120,8 @@ int fstat(int, struct stat *);
|
|||
int fstatat(int, const char *, struct stat *, uint32_t);
|
||||
int fsync(int);
|
||||
int ftruncate(int, int64_t);
|
||||
int getdomainname(char *, size_t);
|
||||
int gethostname(char *, size_t);
|
||||
int getppid(void);
|
||||
int getpriority(int, unsigned);
|
||||
int getrlimit(int, struct rlimit *);
|
||||
|
@ -161,18 +163,18 @@ int rmdir(const char *);
|
|||
int sched_getaffinity(int, uint64_t, void *);
|
||||
int sched_setaffinity(int, uint64_t, const void *);
|
||||
int sched_yield(void);
|
||||
int setegid(uint32_t);
|
||||
int seteuid(uint32_t);
|
||||
int setgid(uint32_t);
|
||||
int setpgid(int, int);
|
||||
int setpriority(int, unsigned, int);
|
||||
int setregid(uint32_t, uint32_t);
|
||||
int setresgid(uint32_t, uint32_t, uint32_t);
|
||||
int setresuid(uint32_t, uint32_t, uint32_t);
|
||||
int setreuid(uint32_t, uint32_t);
|
||||
int setrlimit(int, const struct rlimit *);
|
||||
int setsid(void);
|
||||
int setuid(uint32_t);
|
||||
int setgid(uint32_t);
|
||||
int seteuid(uint32_t);
|
||||
int setegid(uint32_t);
|
||||
int setreuid(uint32_t, uint32_t);
|
||||
int setregid(uint32_t, uint32_t);
|
||||
int setresuid(uint32_t, uint32_t, uint32_t);
|
||||
int setresgid(uint32_t, uint32_t, uint32_t);
|
||||
int sigaction(int, const struct sigaction *, struct sigaction *);
|
||||
int sigignore(int);
|
||||
int sigprocmask(int, const struct sigset *, struct sigset *);
|
||||
|
@ -200,6 +202,7 @@ int64_t preadv(int, struct iovec *, int, int64_t);
|
|||
int64_t pwrite(int, const void *, size_t, int64_t);
|
||||
int64_t pwritev(int, const struct iovec *, int, int64_t);
|
||||
int64_t syscall();
|
||||
void sync(void);
|
||||
long telldir(DIR *);
|
||||
int getpid(void);
|
||||
long times(struct tms *);
|
||||
|
|
|
@ -16,10 +16,10 @@ LIBC_CALLS_ARTIFACTS += LIBC_CALLS_A
|
|||
LIBC_CALLS = $(LIBC_CALLS_A_DEPS) $(LIBC_CALLS_A)
|
||||
LIBC_CALLS_A = o/$(MODE)/libc/calls/syscalls.a
|
||||
LIBC_CALLS_A_FILES := \
|
||||
$(wildcard libc/calls/*) \
|
||||
$(wildcard libc/calls/typedef/*) \
|
||||
$(wildcard libc/calls/thunks/*) \
|
||||
$(wildcard libc/calls/struct/*) \
|
||||
$(wildcard libc/calls/*)
|
||||
$(wildcard libc/calls/struct/*)
|
||||
LIBC_CALLS_A_HDRS = $(filter %.h,$(LIBC_CALLS_A_FILES))
|
||||
LIBC_CALLS_A_SRCS_S = $(filter %.S,$(LIBC_CALLS_A_FILES))
|
||||
LIBC_CALLS_A_SRCS_C = $(filter %.c,$(LIBC_CALLS_A_FILES))
|
||||
|
|
53
libc/calls/getdomainname.c
Normal file
53
libc/calls/getdomainname.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 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/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/utsname.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nt/enum/computernameformat.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/systeminfo.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int getdomainname(char *name, size_t len) {
|
||||
uint32_t nSize;
|
||||
char16_t name16[256];
|
||||
struct utsname u;
|
||||
if (len < 1) return einval();
|
||||
if (!name) return efault();
|
||||
if (!IsWindows()) {
|
||||
if (uname(&u) == -1) return -1;
|
||||
if (!memccpy(name, u.domainname[0] ? u.domainname : u.nodename, '\0',
|
||||
len)) {
|
||||
name[len - 1] = '\0';
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
nSize = ARRAYLEN(name16);
|
||||
if (!GetComputerNameEx(kNtComputerNameDnsFullyQualified, name16, &nSize)) {
|
||||
return winerr();
|
||||
}
|
||||
tprecode16to8(name, MIN(MIN(ARRAYLEN(name16), nSize + 1), len), name16);
|
||||
return 0;
|
||||
}
|
||||
}
|
58
libc/calls/gethostname.c
Normal file
58
libc/calls/gethostname.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*-*- 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/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/utsname.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nt/enum/computernameformat.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/systeminfo.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Returns name of host system, e.g.
|
||||
*
|
||||
* pheidippides.domain.example
|
||||
* ^^^^^^^^^^^^
|
||||
*/
|
||||
int gethostname(char *name, size_t len) {
|
||||
uint32_t nSize;
|
||||
char16_t name16[256];
|
||||
struct utsname u;
|
||||
if (len < 1) return einval();
|
||||
if (!name) return efault();
|
||||
if (!IsWindows()) {
|
||||
if (uname(&u) == -1) return -1;
|
||||
if (!memccpy(name, u.nodename, '\0', len)) {
|
||||
name[len - 1] = '\0';
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
nSize = ARRAYLEN(name16);
|
||||
if (!GetComputerNameEx(kNtComputerNameDnsHostname, name16, &nSize)) {
|
||||
return winerr();
|
||||
}
|
||||
tprecode16to8(name, MIN(MIN(ARRAYLEN(name16), nSize + 1), len), name16);
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -49,7 +49,7 @@ __getntsyspath:
|
|||
cmpb $'\\,-1(%rdi)
|
||||
jne 2f
|
||||
movb $'/,-1(%rdi)
|
||||
2: loop 1b
|
||||
2: .loop 1b
|
||||
leave
|
||||
ret
|
||||
.endfn __getntsyspath,globl,hidden
|
||||
|
|
|
@ -161,6 +161,7 @@ i32 sigaction$sysv(i32, const void *, void *, i64) hidden;
|
|||
i32 sigprocmask$sysv(i32, const sigset *, sigset *, u64) hidden;
|
||||
i32 sigsuspend$sysv(const sigset *, u64) hidden;
|
||||
i32 symlinkat$sysv(const char *, i32, const char *) hidden;
|
||||
i32 sync$sysv(void) hidden;
|
||||
i32 sync_file_range$sysv(i32, i64, i64, u32) hidden;
|
||||
i32 sysinfo$sysv(struct sysinfo *) hidden;
|
||||
i32 truncate$sysv(const char *, u64) hidden;
|
||||
|
@ -239,6 +240,7 @@ int rename$nt(const char *, const char *) hidden;
|
|||
int rmdir$nt(const char *) hidden;
|
||||
int sched_yield$nt(void) hidden;
|
||||
int stat$nt(const char *, struct stat *) hidden;
|
||||
int sync$nt(void) hidden;
|
||||
int symlink$nt(const char *, const char *) hidden;
|
||||
int sysinfo$nt(struct sysinfo *) hidden;
|
||||
int truncate$nt(const char *, u64) hidden;
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
|
||||
/**
|
||||
* Renames files relative to directories.
|
||||
*/
|
||||
int renameat(int olddirfd, const char *oldpath, int newdirfd,
|
||||
const char *newpath) {
|
||||
unsigned mode;
|
||||
|
|
54
libc/calls/sync-nt.c
Normal file
54
libc/calls/sync-nt.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*-*- 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/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/sysv/consts/ok.h"
|
||||
|
||||
/**
|
||||
* Flushes all open file handles and, if possible, all disk drives.
|
||||
*/
|
||||
int sync$nt(void) {
|
||||
unsigned i;
|
||||
int64_t volume;
|
||||
uint32_t drives;
|
||||
char16_t path[] = u"\\\\.\\C:";
|
||||
for (i = 0; i < g_fds.n; ++i) {
|
||||
if (g_fds.p[i].kind == kFdFile) {
|
||||
FlushFileBuffers(g_fds.p[i].handle);
|
||||
}
|
||||
}
|
||||
for (drives = GetLogicalDrives(), i = 0; i <= 'Z' - 'A'; ++i) {
|
||||
if (!(drives & (1 << i))) continue;
|
||||
path[4] = 'A' + i;
|
||||
if (ntaccesscheck(path, R_OK | W_OK) != -1) {
|
||||
if ((volume = CreateFile(
|
||||
path, kNtFileReadAttributes,
|
||||
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, 0,
|
||||
kNtOpenExisting, 0, 0)) != -1) {
|
||||
FlushFileBuffers(volume);
|
||||
CloseHandle(volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -18,19 +18,16 @@
|
|||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
|
||||
/**
|
||||
* Allocates deterministic stack for process.
|
||||
* @see _executive()
|
||||
* Flushes file system changes to disk to the greatest extent possible.
|
||||
*/
|
||||
void *_getstack(void) {
|
||||
char *p;
|
||||
p = mmap((char *)0x700000000000 /* IMAGE_BASE_VIRTUAL */ - STACKSIZE,
|
||||
STACKSIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (p == MAP_FAILED) abort();
|
||||
return p + STACKSIZE;
|
||||
void sync(void) {
|
||||
if (!IsWindows()) {
|
||||
sync$sysv();
|
||||
} else {
|
||||
sync$nt();
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ size_t int64toarray_radix10(int64_t, char[hasatleast 21]);
|
|||
size_t uint64toarray_radix10(uint64_t, char[hasatleast 21]);
|
||||
size_t uint64toarray_radix16(uint64_t, char[hasatleast 17]);
|
||||
size_t uint64toarray_fixed16(uint64_t, char[hasatleast 17], uint8_t);
|
||||
size_t uint64toarray_radix8(uint64_t, char[hasatleast 24]);
|
||||
|
||||
#ifndef __STRICT_ANSI__
|
||||
size_t int128toarray_radix10(int128_t, char *);
|
||||
|
|
|
@ -17,21 +17,24 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/elf/def.h"
|
||||
#include "libc/elf/elf.h"
|
||||
#include "libc/alg/reverse.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/conv/itoa.h"
|
||||
#include "libc/limits.h"
|
||||
|
||||
Elf64_Shdr *getelfsectionbyaddress(const Elf64_Ehdr *elf, size_t mapsize,
|
||||
void *addr) {
|
||||
Elf64_Half i;
|
||||
Elf64_Shdr *shdr;
|
||||
if (elf) {
|
||||
for (i = elf->e_shnum; i > 0; --i) {
|
||||
shdr = getelfsectionheaderaddress(elf, mapsize, i - 1);
|
||||
if ((intptr_t)addr >= shdr->sh_addr &&
|
||||
(intptr_t)addr < shdr->sh_addr + shdr->sh_size) {
|
||||
return shdr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
/**
|
||||
* Converts unsigned 64-bit integer to octal string.
|
||||
* @param a needs at least 24 bytes
|
||||
* @return bytes written w/o nul
|
||||
*/
|
||||
noinline size_t uint64toarray_radix8(uint64_t i, char a[hasatleast 24]) {
|
||||
size_t j;
|
||||
j = 0;
|
||||
do {
|
||||
a[j++] = i % 8 + '0';
|
||||
i /= 8;
|
||||
} while (i > 0);
|
||||
a[j] = '\0';
|
||||
reverse(a, j);
|
||||
return j;
|
||||
}
|
|
@ -20,10 +20,9 @@ COSMOPOLITAN_C_START_
|
|||
struct MappedFile;
|
||||
|
||||
Elf64_Ehdr *mapelfread(const char *, struct MappedFile *);
|
||||
char *getelfstringtable(const Elf64_Ehdr *, size_t);
|
||||
Elf64_Sym *getelfsymboltable(const Elf64_Ehdr *, size_t, Elf64_Xword *);
|
||||
Elf64_Shdr *getelfsectionbyaddress(const Elf64_Ehdr *, size_t, void *);
|
||||
bool iself64binary(const Elf64_Ehdr *, size_t);
|
||||
char *GetElfStringTable(const Elf64_Ehdr *, size_t);
|
||||
Elf64_Sym *GetElfSymbolTable(const Elf64_Ehdr *, size_t, Elf64_Xword *);
|
||||
bool IsElf64Binary(const Elf64_Ehdr *, size_t);
|
||||
|
||||
forceinline void checkelfaddress(const Elf64_Ehdr *elf, size_t mapsize,
|
||||
intptr_t addr, size_t addrsize) {
|
||||
|
@ -94,7 +93,7 @@ static inline void getelfvirtualaddressrange(const Elf64_Ehdr *elf,
|
|||
if (out_end) *out_end = end;
|
||||
}
|
||||
|
||||
static inline char *getelfstring(const Elf64_Ehdr *elf, size_t mapsize,
|
||||
static inline char *GetElfString(const Elf64_Ehdr *elf, size_t mapsize,
|
||||
const char *strtab, Elf64_Word rva) {
|
||||
intptr_t addr = (intptr_t)strtab + rva;
|
||||
#if !(TRUSTWORTHY + ELF_TRUSTWORTHY + 0)
|
||||
|
@ -105,10 +104,10 @@ static inline char *getelfstring(const Elf64_Ehdr *elf, size_t mapsize,
|
|||
return (char *)addr;
|
||||
}
|
||||
|
||||
static inline const char *getelfsectionname(const Elf64_Ehdr *elf,
|
||||
static inline const char *GetElfSectionName(const Elf64_Ehdr *elf,
|
||||
size_t mapsize, Elf64_Shdr *shdr) {
|
||||
if (!elf || !shdr) return NULL;
|
||||
return getelfstring(elf, mapsize, getelfsectionnamestringtable(elf, mapsize),
|
||||
return GetElfString(elf, mapsize, getelfsectionnamestringtable(elf, mapsize),
|
||||
shdr->sh_name);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/elf/def.h"
|
||||
#include "libc/elf/elf.h"
|
||||
|
||||
char *getelfstringtable(const Elf64_Ehdr *elf, size_t mapsize) {
|
||||
char *GetElfStringTable(const Elf64_Ehdr *elf, size_t mapsize) {
|
||||
Elf64_Half i;
|
||||
Elf64_Shdr *shdr;
|
||||
for (i = elf->e_shnum; i > 0; --i) {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/elf/def.h"
|
||||
#include "libc/elf/elf.h"
|
||||
|
||||
Elf64_Sym *getelfsymboltable(const Elf64_Ehdr *elf, size_t mapsize,
|
||||
Elf64_Sym *GetElfSymbolTable(const Elf64_Ehdr *elf, size_t mapsize,
|
||||
Elf64_Xword *out_count) {
|
||||
Elf64_Half i;
|
||||
Elf64_Shdr *shdr;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/elf/elf.h"
|
||||
|
||||
bool iself64binary(const Elf64_Ehdr *elf, size_t mapsize) {
|
||||
bool IsElf64Binary(const Elf64_Ehdr *elf, size_t mapsize) {
|
||||
if (mapsize < sizeof(Elf64_Ehdr)) return false;
|
||||
if (memcmp(elf->e_ident, ELFMAG, 4)) return false;
|
||||
return (elf->e_ident[EI_CLASS] == ELFCLASSNONE ||
|
||||
|
|
|
@ -10,6 +10,7 @@ typedef struct Elf64_Sym {
|
|||
uint8_t st_info;
|
||||
/* STV_{DEFAULT,INTERNAL,HIDDEN,PROTECTED} */
|
||||
uint8_t st_other;
|
||||
/* SHN_UNDEF, <section index>, SHN_ABS, SHN_COMMON, etc. */
|
||||
Elf64_Section st_shndx;
|
||||
Elf64_Addr st_value;
|
||||
Elf64_Xword st_size;
|
||||
|
|
|
@ -63,7 +63,7 @@ int strerror_r(int err, char *buf, size_t size) {
|
|||
if (FormatMessage(
|
||||
kNtFormatMessageFromSystem | kNtFormatMessageIgnoreInserts, NULL,
|
||||
err, 0, buf16, ARRAYLEN(buf16) - 1, 0) > 0) {
|
||||
chomp(buf16);
|
||||
chomp16(buf16);
|
||||
} else {
|
||||
buf16[0] = u'\0';
|
||||
}
|
||||
|
|
|
@ -152,6 +152,7 @@ relegated static void ShowMemoryMappings(int outfd) {
|
|||
|
||||
relegated static void ShowCrashReport(int err, int fd, int sig,
|
||||
ucontext_t *ctx) {
|
||||
int i;
|
||||
struct utsname names;
|
||||
(dprintf)(fd, VEIL("r", "\r\n%serror%s: Uncaught SIG%s\r\n %s\r\n %s\r\n"),
|
||||
RED2, RESET, TinyStrSignal(sig), getauxval(AT_EXECFN),
|
||||
|
@ -167,6 +168,11 @@ relegated static void ShowCrashReport(int err, int fd, int sig,
|
|||
}
|
||||
write(fd, "\r\n", 2);
|
||||
ShowMemoryMappings(fd);
|
||||
write(fd, "\r\n", 2);
|
||||
for (i = 0; i < g_argc; ++i) {
|
||||
write(fd, g_argv[i], strlen(g_argv[i]));
|
||||
write(fd, "\r\n", 2);
|
||||
}
|
||||
}
|
||||
|
||||
relegated static void RestoreDefaultCrashSignalHandlers(void) {
|
||||
|
|
|
@ -186,10 +186,10 @@
|
|||
.endif
|
||||
.endm
|
||||
|
||||
/ Overrides LOOP instruction.
|
||||
/ LOOP Instruction Replacement.
|
||||
/ With its mop-Fusion Mexican equivalent.
|
||||
/ Thus avoiding 3x legacy pipeline slowdown.
|
||||
.macro loop label:req
|
||||
.macro .loop label:req
|
||||
.byte 0x83,0xe9,0x01 # sub $1,%ecx
|
||||
jnz \label
|
||||
.endm
|
||||
|
|
|
@ -59,7 +59,7 @@ crc32init:
|
|||
pand %xmm0,%xmm3
|
||||
pxor %xmm4,%xmm3
|
||||
movdqa %xmm3,%xmm4
|
||||
loop 2b
|
||||
.loop 2b
|
||||
movdqu %xmm3,(%rdi)
|
||||
add $16,%rdi
|
||||
paddd %xmm2,%xmm1
|
||||
|
|
|
@ -35,7 +35,7 @@ imapxlatab:
|
|||
.align 8
|
||||
1: stosq
|
||||
add %rdx,%rax
|
||||
loop 1b
|
||||
.loop 1b
|
||||
.leafepilogue
|
||||
.endfn imapxlatab,globl,hidden
|
||||
.source __FILE__
|
||||
|
|
|
@ -35,13 +35,13 @@ kBase36:.zero 256
|
|||
pushpop 10,%rcx
|
||||
0: inc %eax
|
||||
stosb
|
||||
loop 0b
|
||||
.loop 0b
|
||||
add $'A-1-'9,%rdi
|
||||
pushpop 'Z+1-'A,%rcx
|
||||
0: inc %eax
|
||||
mov %al,0x20(%rdi)
|
||||
stosb
|
||||
loop 0b
|
||||
.loop 0b
|
||||
add $255-'Z,%rdi
|
||||
.init.end 300,_init_kBase36
|
||||
.source __FILE__
|
||||
|
|
|
@ -51,7 +51,7 @@ kToLower16:
|
|||
mov $256,%ecx
|
||||
0: lodsb
|
||||
stosw
|
||||
loop 0b
|
||||
.loop 0b
|
||||
pop %rsi
|
||||
.init.end 300,_init_kToLower
|
||||
|
||||
|
|
|
@ -30,6 +30,6 @@ kToUpper:
|
|||
call imapxlatab
|
||||
pushpop 'z-'a,%rcx
|
||||
0: subb $0x20,(%r8,%rcx)
|
||||
loop 0b
|
||||
.loop 0b
|
||||
.init.end 300,_init_kToUpper
|
||||
.source __FILE__
|
||||
|
|
|
@ -36,7 +36,7 @@ memjmpinit:
|
|||
lodsb
|
||||
add %rdx,%rax
|
||||
stosq
|
||||
loop 0b
|
||||
.loop 0b
|
||||
xor %eax,%eax
|
||||
testb X86_HAVE(ERMS)+kCpuids(%rip)
|
||||
setnz %al
|
||||
|
|
|
@ -34,7 +34,7 @@ rldecode:
|
|||
lodsb
|
||||
jrcxz 2f
|
||||
1: stosb
|
||||
loop 1b
|
||||
.loop 1b
|
||||
jmp 0b
|
||||
2: .leafepilogue
|
||||
.endfn rldecode,globl
|
||||
|
|
|
@ -1,2 +1,12 @@
|
|||
.include "o/libc/nt/codegen.inc"
|
||||
.imp KernelBase,__imp_GetComputerNameExW,GetComputerNameExW,449
|
||||
|
||||
.text.windows
|
||||
GetComputerNameEx:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov __imp_GetComputerNameExW(%rip),%rax
|
||||
jmp __sysv2nt
|
||||
.endfn GetComputerNameEx,globl
|
||||
.previous
|
||||
|
|
16
libc/nt/enum/computernameformat.h
Normal file
16
libc/nt/enum/computernameformat.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_COMPUTERNAMEFORMAT_H_
|
||||
#define COSMOPOLITAN_LIBC_NT_ENUM_COMPUTERNAMEFORMAT_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
#define kNtComputerNameNetBios 0
|
||||
#define kNtComputerNameDnsHostname 1
|
||||
#define kNtComputerNameDnsDomain 2
|
||||
#define kNtComputerNameDnsFullyQualified 3
|
||||
#define kNtComputerNamePhysicalNetBios 4
|
||||
#define kNtComputerNamePhysicalDnsHostname 5
|
||||
#define kNtComputerNamePhysicalDnsDomain 6
|
||||
#define kNtComputerNamePhysicalDnsFullyQualified 7
|
||||
#define kNtComputerName_MAX 8
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_COMPUTERNAMEFORMAT_H_ */
|
|
@ -1979,7 +1979,7 @@ imp 'GetCompressedFileSizeTransactedA' GetCompressedFileSizeTransactedA kern
|
|||
imp 'GetCompressedFileSizeTransacted' GetCompressedFileSizeTransactedW kernel32 479
|
||||
imp 'GetComputerNameA' GetComputerNameA kernel32 481
|
||||
imp 'GetComputerNameExA' GetComputerNameExA KernelBase 448
|
||||
imp 'GetComputerNameEx' GetComputerNameExW KernelBase 449
|
||||
imp 'GetComputerNameEx' GetComputerNameExW KernelBase 449 3
|
||||
imp 'GetComputerName' GetComputerNameW kernel32 484
|
||||
imp 'GetConsoleAliasA' GetConsoleAliasA KernelBase 450
|
||||
imp 'GetConsoleAliasExesA' GetConsoleAliasExesA KernelBase 451
|
||||
|
|
|
@ -46,12 +46,14 @@ int64_t CreateFileMappingNuma(
|
|||
const struct NtSecurityAttributes *opt_lpFileMappingAttributes,
|
||||
uint32_t flProtect, uint32_t dwMaximumSizeHigh, uint32_t dwMaximumSizeLow,
|
||||
const char16_t *opt_lpName, uint32_t nndDesiredNumaNode);
|
||||
|
||||
void *MapViewOfFileExNuma(
|
||||
int64_t hFileMappingObject, /* @see CreateFileMapping() */
|
||||
uint32_t dwDesiredAccess, uint32_t dwFileOffsetHigh, /* high order bits */
|
||||
uint32_t dwFileOffsetLow, /* low order bits */
|
||||
size_t dwNumberOfBytesToMap, void *opt_lpDesiredBaseAddress,
|
||||
uint32_t nndDesiredNumaNode);
|
||||
|
||||
bool32 UnmapViewOfFile(const void *lpBaseAddress);
|
||||
bool32 FlushViewOfFile(const void *lpBaseAddress,
|
||||
size_t dwNumberOfBytesToFlush);
|
||||
|
|
|
@ -152,6 +152,8 @@ $(LIBC_NT_NTDLL_A): \
|
|||
libc/nt/ntdll/ \
|
||||
$(LIBC_NT_NTDLL_A).pkg \
|
||||
$(LIBC_NT_NTDLL_A_OBJS)
|
||||
@$(file >$@.cmd) $(file >>$@.cmd,$(ARCHIVE) $@ $^ >$(LIBC_NT_NTDLL_A).cmd)
|
||||
@$(ARCHIVE) $@ $^
|
||||
|
||||
$(LIBC_NT_NTDLL_A).pkg: \
|
||||
$(LIBC_NT_NTDLL_A_OBJS) \
|
||||
|
|
|
@ -13,6 +13,9 @@ uint32_t GetSystemDirectoryA(char *lpBuffer, uint32_t uSize);
|
|||
uint32_t GetWindowsDirectory(char16_t *lpBuffer, uint32_t uSize);
|
||||
uint32_t GetTempPath(uint32_t uSize, char16_t *lpBuffer);
|
||||
|
||||
bool32 GetComputerNameEx(/* enum/computernameformat.h */ int NameType,
|
||||
char16_t *opt_lpBuffer, uint32_t *nSize);
|
||||
|
||||
#if ShouldUseMsabiAttribute()
|
||||
#include "libc/nt/thunk/systeminfo.inc"
|
||||
#endif /* ShouldUseMsabiAttribute() */
|
||||
|
|
|
@ -38,8 +38,8 @@ static textwindows struct DirectMap DirectMapNt(void *addr, size_t size,
|
|||
protect = prot2nt(prot, flags);
|
||||
access = fprot2nt(prot, flags);
|
||||
if ((res.maphandle =
|
||||
CreateFileMappingNuma(handle, &kNtIsInheritable, protect, size >> 32,
|
||||
size, NULL, kNtNumaNoPreferredNode))) {
|
||||
CreateFileMappingNuma(handle, NULL, protect, size >> 32, size, NULL,
|
||||
kNtNumaNoPreferredNode))) {
|
||||
if (!(res.addr = MapViewOfFileExNuma(res.maphandle, access, off >> 32, off,
|
||||
size, addr, kNtNumaNoPreferredNode))) {
|
||||
CloseHandle(res.maphandle);
|
||||
|
|
|
@ -42,16 +42,13 @@ _executive:
|
|||
mov %rdx,%r14
|
||||
mov %rcx,%r15
|
||||
call _spawn
|
||||
call _getstack
|
||||
mov %rax,%rdi
|
||||
mov %r12d,%edi
|
||||
mov %r13,%rsi
|
||||
mov %r14,%rdx
|
||||
mov %r15,%rcx
|
||||
.weak main
|
||||
mov $main,%esi
|
||||
mov %r12,%rdx
|
||||
mov %r13,%rcx
|
||||
mov %r14,%r8
|
||||
mov %r15,%r9
|
||||
call _setstack
|
||||
mov %eax,%edi
|
||||
call main
|
||||
xchg %eax,%edi
|
||||
call exit
|
||||
.endfn _executive,weak,hidden
|
||||
ud2
|
||||
|
|
|
@ -25,6 +25,7 @@ void *__cxa_finalize(void *) hidden;
|
|||
void _executive(int, char **, char **, long (*)[2]) hidden noreturn;
|
||||
void __stack_chk_fail(void) noreturn relegated;
|
||||
void __stack_chk_fail_local(void) noreturn relegated hidden;
|
||||
long _setstack(void *, void *, ...) hidden;
|
||||
int GetDosArgv(const char16_t *, char *, size_t, char **, size_t) hidden;
|
||||
|
||||
forceinline void AssertNeverCalledWhileTerminating(void) {
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "libc/runtime/ezmap.h"
|
||||
|
||||
Elf64_Ehdr *mapelfread(const char *filename, struct MappedFile *mf) {
|
||||
if (mapfileread(filename, mf) != -1 && iself64binary(mf->addr, mf->size)) {
|
||||
if (mapfileread(filename, mf) != -1 && IsElf64Binary(mf->addr, mf->size)) {
|
||||
return mf->addr;
|
||||
} else {
|
||||
unmapfile(mf);
|
||||
|
|
|
@ -27,7 +27,9 @@
|
|||
/**
|
||||
* Synchronize memory mapping changes to disk.
|
||||
*
|
||||
* @param flags needs MS_SYNC or MS_ASYNC and can have MS_INVALIDATE
|
||||
* Without this, there's no guarantee memory is written back to disk.
|
||||
*
|
||||
* @param flags needs MS_ASYNC or MS_SYNC and can have MS_INVALIDATE
|
||||
* @return 0 on success or -1 w/ errno
|
||||
*/
|
||||
int msync(void *addr, size_t size, int flags) {
|
||||
|
|
|
@ -39,8 +39,8 @@ struct SymbolTable *OpenSymbolTable(const char *filename) {
|
|||
t = MAP_FAILED;
|
||||
if (filename && (t = mapanon(BIGPAGESIZE)) != MAP_FAILED &&
|
||||
mapelfread(filename, &t->mf) &&
|
||||
(t->name_base = getelfstringtable(t->elf, t->elfsize)) != NULL &&
|
||||
(symtab = getelfsymboltable(t->elf, t->elfsize, &t->count)) &&
|
||||
(t->name_base = GetElfStringTable(t->elf, t->elfsize)) != NULL &&
|
||||
(symtab = GetElfSymbolTable(t->elf, t->elfsize, &t->count)) &&
|
||||
sizeof(struct SymbolTable) + sizeof(struct Symbol) * t->count <
|
||||
(t->scratch = BIGPAGESIZE)) {
|
||||
getelfvirtualaddressrange(t->elf, t->elfsize, &t->addr_base, &t->addr_end);
|
||||
|
|
|
@ -43,7 +43,6 @@ void longjmp(jmp_buf, int) libcesque noreturn paramsnonnull();
|
|||
void exit(int) noreturn;
|
||||
void _exit(int) libcesque noreturn;
|
||||
void _Exit(int) libcesque noreturn;
|
||||
long _setstack(void *, void *, ...);
|
||||
void abort(void) noreturn noinstrument;
|
||||
void panic(void) noreturn noinstrument privileged;
|
||||
void triplf(void) noreturn noinstrument privileged;
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
/ @param rdi is new rsp, passed as malloc(size) + size
|
||||
/ @param rsi is function to call in new stack space
|
||||
/ @param rdx,rcx,r8,r9 get passed as args to rsi
|
||||
/ @return happens on original stack
|
||||
/ @return rax and happens on original stack
|
||||
_setstack:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
|
@ -43,4 +43,4 @@ _setstack:
|
|||
pop %rbx
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn _setstack,globl
|
||||
.endfn _setstack,globl,hidden
|
||||
|
|
|
@ -25,7 +25,9 @@
|
|||
#include "libc/nt/enum/consolemodeflags.h"
|
||||
#include "libc/nt/enum/filetype.h"
|
||||
#include "libc/nt/enum/loadlibrarysearch.h"
|
||||
#include "libc/nt/enum/pageflags.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/pedef.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
|
@ -117,10 +119,10 @@ static textwindows void NormalizeCmdExe(void) {
|
|||
* 3. Environment variables are passed to us as a sorted UTF-16 double
|
||||
* NUL terminated list. We translate this to char ** using UTF-8.
|
||||
*
|
||||
* 4. NT likes to choose a stack address that's beneath the program
|
||||
* image. We want to be able to assume that stack addresses are
|
||||
* located at higher addresses than heap and program memory. So the
|
||||
* _executive() function will switch stacks appropriately.
|
||||
* 4. Allocates new stack at a high address. NT likes to choose a
|
||||
* stack address that's beneath the program image. We want to be
|
||||
* able to assume that stack addresses are located at higher
|
||||
* addresses than heap and program memory.
|
||||
*
|
||||
* 5. Windows users are afraid of "drive-by downloads" where someone
|
||||
* might accidentally an evil DLL to their Downloads folder which
|
||||
|
@ -131,21 +133,27 @@ static textwindows void NormalizeCmdExe(void) {
|
|||
*/
|
||||
textwindows int WinMain(void *hInstance, void *hPrevInstance,
|
||||
const char *lpCmdLine, int nCmdShow) {
|
||||
char *stack;
|
||||
int i, count;
|
||||
const char16_t *cmd16, *env16;
|
||||
char *argarray[512], *envarray[512];
|
||||
char *argv[512], *envp[512];
|
||||
char argblock[ARG_MAX], envblock[ENV_MAX];
|
||||
long auxarray[][2] = {{pushpop(0L), pushpop(0L)}};
|
||||
long auxv[][2] = {{pushpop(0L), pushpop(0L)}};
|
||||
MitigateDriveByDownloads();
|
||||
NormalizeCmdExe();
|
||||
*(/*unconst*/ int *)&hostos = WINDOWS;
|
||||
cmd16 = GetCommandLine();
|
||||
env16 = GetEnvironmentStrings();
|
||||
count = GetDosArgv(cmd16, argblock, ARG_MAX, argarray, 512);
|
||||
for (i = 0; argarray[0][i]; ++i) {
|
||||
if (argarray[0][i] == '\\') argarray[0][i] = '/';
|
||||
count = GetDosArgv(cmd16, argblock, ARG_MAX, argv, 512);
|
||||
for (i = 0; argv[0][i]; ++i) {
|
||||
if (argv[0][i] == '\\') argv[0][i] = '/';
|
||||
}
|
||||
GetDosEnviron(env16, envblock, ENV_MAX, envarray, 512);
|
||||
GetDosEnviron(env16, envblock, ENV_MAX, envp, 512);
|
||||
FreeEnvironmentStrings(env16);
|
||||
_executive(count, argarray, envarray, auxarray);
|
||||
stack = MapViewOfFileExNuma(
|
||||
CreateFileMappingNuma(-1, NULL, pushpop(kNtPageReadwrite), 0, STACKSIZE,
|
||||
NULL, kNtNumaNoPreferredNode),
|
||||
kNtFileMapRead | kNtFileMapWrite, 0, 0, STACKSIZE,
|
||||
(char *)0x777000000000 - STACKSIZE, kNtNumaNoPreferredNode);
|
||||
return _setstack(stack + STACKSIZE, _executive, count, argv, envp, auxv);
|
||||
}
|
||||
|
|
|
@ -256,97 +256,6 @@ bool luhn(const char *);
|
|||
|
||||
char *strsignal(int) returnsnonnull libcesque;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § strings » hooks ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
extern int (*const hook$strcmp16)(const char16_t *, const char16_t *);
|
||||
extern int (*const hook$strncmp16)(const char16_t *, const char16_t *, size_t);
|
||||
extern int (*const hook$wcscmp)(const wchar_t *, const wchar_t *);
|
||||
extern int (*const hook$wcsncmp)(const wchar_t *, const wchar_t *, size_t);
|
||||
#define __STR_HOOK(SYMBOL) hook$##SYMBOL
|
||||
#else
|
||||
#define __STR_HOOK(SYMBOL) SYMBOL
|
||||
#endif /* GNUC && !ANSI */
|
||||
|
||||
/* TODO(jart): Use @gotpcrel. */
|
||||
#undef __STR_HOOK
|
||||
#define __STR_HOOK(SYMBOL) SYMBOL
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § strings » generic typing ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#if __STDC_VERSION__ + 0 >= 201112
|
||||
|
||||
#define strnlen(s, n) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcsnlen, char16_t \
|
||||
: strnlen16, default \
|
||||
: strnlen)(s, n)
|
||||
|
||||
#define strnlen_s(s, n) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcsnlen_s, char16_t \
|
||||
: strnlen16_s, default \
|
||||
: strnlen_s)(s, n)
|
||||
|
||||
#define strpbrk(s, c) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcspbrk, char16_t \
|
||||
: strpbrk16, default \
|
||||
: strpbrk)(s, c)
|
||||
|
||||
#define strspn(s, c) \
|
||||
_Generic(*(s), wchar_t : wcsspn, char16_t : strspn16, default : strspn)(s, c)
|
||||
|
||||
#define strcspn(s, c) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcscspn, char16_t \
|
||||
: strcspn16, default \
|
||||
: strcspn)(s, c)
|
||||
|
||||
/* clang-format off */
|
||||
#define strcmp(s1, s2) \
|
||||
_Generic((s1)[0], \
|
||||
wchar_t: __STR_HOOK(wcscmp), \
|
||||
char16_t: _Generic(*(s2), \
|
||||
char: strcmp16to8, \
|
||||
default: __STR_HOOK(strcmp16)), \
|
||||
default: _Generic(*(s2), \
|
||||
char16_t: strcmp8to16, \
|
||||
default: strcmp))(s1, s2)
|
||||
/* clang-format on */
|
||||
|
||||
#define strncmp(s1, s2, n) \
|
||||
_Generic(*(s1), wchar_t \
|
||||
: __STR_HOOK(wcsncmp), char16_t \
|
||||
: _Generic(*(s2), char \
|
||||
: strncmp16to8, default \
|
||||
: __STR_HOOK(strncmp16)), \
|
||||
default \
|
||||
: _Generic(*(s2), char16_t \
|
||||
: strncmp8to16, default \
|
||||
: strncmp))(s1, s2, n)
|
||||
|
||||
#define strcasecmp(s1, s2) \
|
||||
_Generic(*(s1), wchar_t \
|
||||
: wcscasecmp, char16_t \
|
||||
: strcasecmp16, default \
|
||||
: strcasecmp)(s1, s2)
|
||||
|
||||
#define strncasecmp(s1, s2, n) \
|
||||
_Generic(*(s1), wchar_t \
|
||||
: wcsncasecmp, char16_t \
|
||||
: strncasecmp16, default \
|
||||
: strncasecmp)(s1, s2, n)
|
||||
|
||||
#define chomp(s) \
|
||||
_Generic(*(s), wchar_t : wchomp, char16_t : chomp16, default : chomp)(s)
|
||||
|
||||
#endif /* C11 */
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § strings » optimizations ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
* @see strspn(), strtok_r()
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
size_t(strcspn)(const char *s, const char *reject) {
|
||||
size_t strcspn(const char *s, const char *reject) {
|
||||
size_t i;
|
||||
for (i = 0; s[i]; ++i) {
|
||||
if (HasCharacter(s[i], reject)) {
|
||||
|
|
|
@ -20,9 +20,20 @@
|
|||
#include "libc/nexgen32e/hascharacter.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#undef strcspn
|
||||
#define char char16_t
|
||||
#define HasCharacter HasCharacter16
|
||||
#define strcspn strcspn16
|
||||
|
||||
#include "libc/str/strcspn.c"
|
||||
/**
|
||||
* Returns prefix length, consisting of chars not in reject.
|
||||
* a.k.a. Return index of first byte that's in charset.
|
||||
*
|
||||
* @param reject is nul-terminated character set
|
||||
* @see strspn(), strtok_r()
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
size_t strcspn16(const char16_t *s, const char16_t *reject) {
|
||||
size_t i;
|
||||
for (i = 0; s[i]; ++i) {
|
||||
if (HasCharacter16(s[i], reject)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
|
|
@ -20,9 +20,20 @@
|
|||
#include "libc/nexgen32e/hascharacter.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#undef strcspn
|
||||
#define char wchar_t
|
||||
#define HasCharacter HasCharacterWide
|
||||
#define strcspn wcscspn
|
||||
|
||||
#include "libc/str/strcspn.c"
|
||||
/**
|
||||
* Returns prefix length, consisting of chars not in reject.
|
||||
* a.k.a. Return index of first byte that's in charset.
|
||||
*
|
||||
* @param reject is nul-terminated character set
|
||||
* @see strspn(), strtok_r()
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
size_t wcscspn(const wchar_t *s, const wchar_t *reject) {
|
||||
size_t i;
|
||||
for (i = 0; s[i]; ++i) {
|
||||
if (HasCharacterWide(s[i], reject)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
.include "o/libc/sysv/macros.inc"
|
||||
.scall gethostname 0xffff0057ffffffff globl
|
2
libc/sysv/calls/sync-sysv.s
Normal file
2
libc/sysv/calls/sync-sysv.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "o/libc/sysv/macros.inc"
|
||||
.scall sync$sysv 0x00240024202400a2 globl hidden
|
|
@ -1,2 +0,0 @@
|
|||
.include "o/libc/sysv/macros.inc"
|
||||
.scall sync 0x00240024202400a2 globl
|
|
@ -178,7 +178,7 @@ scall mlockall 0x010f014421440097 globl
|
|||
scall munlockall 0x0110014521450098 globl
|
||||
scall 'setrlimit$sysv' 0x00c300c320c300a0 globl hidden
|
||||
scall chroot 0x003d003d203d00a1 globl
|
||||
scall sync 0x00240024202400a2 globl
|
||||
scall 'sync$sysv' 0x00240024202400a2 globl hidden
|
||||
scall acct 0x00330033203300a3 globl
|
||||
scall settimeofday 0x0044007a207a00a4 globl
|
||||
scall mount 0x0015001520a700a5 globl
|
||||
|
@ -649,10 +649,10 @@ scall fhlinkat 0xffff0236ffffffff globl
|
|||
scall fhreadlink 0xffff0237ffffffff globl
|
||||
scall getaudit 0xffff01c1ffffffff globl
|
||||
scall getcontext 0xffff01a5ffffffff globl
|
||||
scall getdomainname 0xffff00a2ffffffff globl
|
||||
#scall getdomainname 0xffff00a2ffffffff globl
|
||||
scall getfhat 0xffff0234ffffffff globl
|
||||
scall gethostid 0xffff008effffffff globl
|
||||
scall gethostname 0xffff0057ffffffff globl
|
||||
#scall gethostname 0xffff0057ffffffff globl
|
||||
scall getkerninfo 0xffff003fffffffff globl
|
||||
scall getloginclass 0xffff020bffffffff globl
|
||||
scall 'getpagesize$freebsd' 0xffff0040ffffffff globl hidden
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue