Add fixes performance and static web server

This commit is contained in:
Justine Tunney
2020-10-05 23:11:49 -07:00
parent b6793d42d5
commit c45e46f871
108 changed files with 2927 additions and 819 deletions

View File

@ -71,27 +71,25 @@ static size_t KnuthMorrisPratt(m, T, W, n, S)
* @param needlelen is its character count
* @return pointer to first result or NULL if not found
*/
void *(memmem)(const void *haystack_, size_t haystacklen, const void *needle_,
void *(memmem)(const void *haystackp, size_t haystacklen, const void *needlep,
size_t needlelen) {
long *T;
size_t i;
const char *haystack, *needle, *h;
haystack = haystack_;
needle = needle_;
needle = needlep;
haystack = haystackp;
if (needlelen > haystacklen) return NULL;
if (!needlelen) return (/*unconst*/ void *)haystack;
if (!needlelen) return haystack;
h = memchr(haystack, *needle, haystacklen);
if (!h || needlelen == 1) return (/*unconst*/ void *)h;
if (!h || needlelen == 1) return h;
haystacklen -= h - haystack;
long stacktmp[16];
void *freeme = NULL;
long *T = (needlelen + 1 < ARRAYLEN(stacktmp))
? &stacktmp[0]
: (freeme = malloc((needlelen + 1) * sizeof(long)));
KnuthMorrisPrattInit(needlelen, T, needle);
size_t i = KnuthMorrisPratt(needlelen, T, needle, haystacklen, h);
free(freeme);
if (i < haystacklen) {
return (/*unconst*/ char *)h + i * sizeof(char);
if (needlelen < haystacklen && memcmp(h, needle, needlelen) == 0) {
return h;
} else {
return NULL;
T = malloc((needlelen + 1) * sizeof(long));
KnuthMorrisPrattInit(needlelen, T, needle);
i = KnuthMorrisPratt(needlelen, T, needle, haystacklen, h);
free(T);
return i < haystacklen ? h + i * sizeof(char) : NULL;
}
}

View File

@ -17,10 +17,7 @@
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
│ 02110-1301 USA │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/bits/bits.h"
#include "libc/calls/internal.h"
#include "libc/macros.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/errfuns.h"

View File

@ -77,7 +77,7 @@ int clock_gettime(int clockid, struct timespec *out_ts) {
} else {
struct NtFileTime ft;
GetSystemTimeAsFileTime(&ft);
*out_ts = filetimetotimespec(ft);
*out_ts = FileTimeToTimeSpec(ft);
return 0;
}
}

View File

@ -49,9 +49,9 @@ textwindows int fstat$nt(int64_t handle, struct stat *st) {
: (((filetype == kNtFileTypeDisk) ? S_IFBLK : 0) |
((filetype == kNtFileTypeChar) ? S_IFCHR : 0) |
((filetype == kNtFileTypePipe) ? S_IFIFO : 0))));
st->st_atim = filetimetotimespec(wst.ftLastAccessFileTime);
st->st_mtim = filetimetotimespec(wst.ftLastWriteFileTime);
st->st_ctim = filetimetotimespec(wst.ftCreationFileTime);
st->st_atim = FileTimeToTimeSpec(wst.ftLastAccessFileTime);
st->st_mtim = FileTimeToTimeSpec(wst.ftLastWriteFileTime);
st->st_ctim = FileTimeToTimeSpec(wst.ftCreationFileTime);
st->st_size = (uint64_t)wst.nFileSizeHigh << 32 | wst.nFileSizeLow;
st->st_blksize = PAGESIZE;
st->st_dev = wst.dwVolumeSerialNumber;

View File

@ -28,7 +28,6 @@
static int g_pid;
static void __updatepid(void) {
atfork(__updatepid, NULL);
g_pid = __getpid();
}
@ -47,8 +46,9 @@ int __getpid(void) {
int getpid(void) {
static bool once;
if (!once) {
once = true;
__updatepid();
atfork(__updatepid, NULL);
once = true;
}
return g_pid;
}

View File

@ -36,8 +36,8 @@ textwindows int getrusage$nt(int who, struct rusage *usage) {
if ((who == RUSAGE_SELF ? GetProcessTimes : GetThreadTimes)(
(who == RUSAGE_SELF ? GetCurrentProcess : GetCurrentThread)(),
&CreationFileTime, &ExitFileTime, &KernelFileTime, &UserFileTime)) {
filetimetotimeval(&usage->ru_utime, UserFileTime);
filetimetotimeval(&usage->ru_stime, KernelFileTime);
FileTimeToTimeVal(&usage->ru_utime, UserFileTime);
FileTimeToTimeVal(&usage->ru_stime, KernelFileTime);
return 0;
} else {
return winerr();

View File

@ -29,7 +29,7 @@
int gettimeofday$nt(struct timeval *tv, struct timezone *tz) {
struct NtFileTime ft;
GetSystemTimeAsFileTime(&ft);
filetimetotimeval(tv, ft);
FileTimeToTimeVal(tv, ft);
if (tz) memset(tz, 0, sizeof(*tz));
return 0;
}

View File

@ -35,7 +35,7 @@
* @param mode is an octal user/group/other permission signifier, that's
* ignored if O_CREAT or O_TMPFILE weren't passed
* @return number needing close(), or -1 w/ errno
* @asyncsignalsafe
* @note don't call open() from signal handlers
*/
nodiscard int open(const char *file, int flags, ...) {
va_list va;

View File

@ -155,7 +155,7 @@ int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) {
ap->sa_restorer = &__restore_rt;
}
}
if (rva >= 0) {
if (rva >= kSigactionMinRva) {
ap->sa_sigaction = (sigaction_f)__sigenter;
}
}

View File

@ -63,7 +63,7 @@ textwindows int utimensat$nt(int dirfd, const char *path,
} else if (ts[i].tv_nsec == UTIME_OMIT) {
ftp[i] = NULL;
} else {
ft[i] = timespectofiletime(ts[i]);
ft[i] = TimeSpecToFileTime(ts[i]);
ftp[i] = &ft[i];
}
}

View File

@ -50,8 +50,8 @@ textwindows int wait4$nt(int pid, int *opt_out_wstatus, int options,
memset(opt_out_rusage, 0, sizeof(*opt_out_rusage));
GetProcessTimes(GetCurrentProcess(), &createfiletime, &exitfiletime,
&kernelfiletime, &userfiletime);
filetimetotimeval(&opt_out_rusage->ru_utime, userfiletime);
filetimetotimeval(&opt_out_rusage->ru_stime, kernelfiletime);
FileTimeToTimeVal(&opt_out_rusage->ru_utime, userfiletime);
FileTimeToTimeVal(&opt_out_rusage->ru_stime, kernelfiletime);
}
return pid;
} else if (options & WNOHANG) {

View File

@ -15,8 +15,8 @@
* of the UNIX operation system signalled the end of modernity. Windows
* timestamps are living proof.
*/
#define MODERNITYSECONDS 11644473600
#define HECTONANOSECONDS 10000000
#define MODERNITYSECONDS 11644473600ull
#define HECTONANOSECONDS 10000000ull
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
@ -46,12 +46,13 @@ long strtol(const char *, char **, int)
│ cosmopolitan § conversion » time ─╬─│┼
╚────────────────────────────────────────────────────────────────────────────│*/
struct timespec filetimetotimespec(struct NtFileTime);
struct NtFileTime timespectofiletime(struct timespec);
struct NtFileTime timetofiletime(int64_t) nothrow pureconst;
int64_t DosDateTimeToUnix(unsigned, unsigned);
struct timespec FileTimeToTimeSpec(struct NtFileTime);
struct NtFileTime TimeSpecToFileTime(struct timespec);
struct NtFileTime TimeToFileTime(int64_t) nothrow pureconst;
int64_t filetimetotime(struct NtFileTime) nothrow pureconst;
void filetimetotimeval(struct timeval *, struct NtFileTime) nothrow;
struct NtFileTime timevaltofiletime(const struct timeval *) nosideeffect;
void FileTimeToTimeVal(struct timeval *, struct NtFileTime) nothrow;
struct NtFileTime TimeValToFileTime(const struct timeval *) nosideeffect;
long convertmicros(const struct timeval *, long) paramsnonnull() nosideeffect;
/*───────────────────────────────────────────────────────────────────────────│─╗

View File

@ -52,6 +52,7 @@ $(LIBC_CONV_A).pkg: \
$(LIBC_CONV_A_OBJS) \
$(foreach x,$(LIBC_CONV_A_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/libc/conv/dosdatetimetounix.o \
o/$(MODE)/libc/conv/itoa64radix10.greg.o \
o/$(MODE)/libc/conv/timetofiletime.o \
o/$(MODE)/libc/conv/filetimetotime.o \

View File

@ -0,0 +1,43 @@
/*-*- 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/macros.h"
#include "libc/time/time.h"
/**
* Converts MS-DOS timestamp to UNIX.
*
* @note type signature supports dates greater than 2100
* @see PKZIP, FAT
*/
int64_t DosDateTimeToUnix(unsigned date, unsigned time) {
unsigned weekday, year, month, day, hour, minute, second, yday, leap;
year = ((date & 0xfffffe00) >> 9) + 1980 - 1900;
month = MAX(1, MIN(12, (date & 0x01e0) >> 5));
day = (date & 0x001f) ? (date & 0x001f) - 1 : 0;
hour = (time & 0x0000f800) >> 11;
minute = (time & 0x000007e0) >> 5;
second = (time & 0x0000001f) << 1;
leap = year % 4 == 0 && (year % 100 || year % 400 == 0);
yday = day + kMonthYearDay[leap][month - 1];
return second + minute * 60 + hour * 3600 + yday * 86400 +
(year - 70) * 31536000ull + ((year - 69) / 4) * 86400ull -
((year - 1) / 100) * 86400ull + ((year + 299) / 400) * 86400ull;
}

View File

@ -24,11 +24,11 @@
/**
* Converts Windows COBOL timestamp to UNIX epoch in nanoseconds.
*/
struct timespec filetimetotimespec(struct NtFileTime ft) {
struct timespec FileTimeToTimeSpec(struct NtFileTime ft) {
uint64_t x;
x = ft.dwHighDateTime;
x <<= 32;
x |= ft.dwLowDateTime;
x -= MODERNITYSECONDS;
return (struct timespec){x / HECTONANOSECONDS, x % HECTONANOSECONDS * 100};
return (struct timespec){x / HECTONANOSECONDS - MODERNITYSECONDS,
x % HECTONANOSECONDS * 100};
}

View File

@ -22,9 +22,11 @@
#include "libc/conv/conv.h"
#include "libc/nt/struct/filetime.h"
void filetimetotimeval(struct timeval *tv, struct NtFileTime ft) {
uint64_t t = (uint64_t)ft.dwHighDateTime << 32 | ft.dwLowDateTime;
uint64_t x = t - MODERNITYSECONDS * HECTONANOSECONDS;
tv->tv_sec = x / HECTONANOSECONDS;
void FileTimeToTimeVal(struct timeval *tv, struct NtFileTime ft) {
uint64_t x;
x = ft.dwHighDateTime;
x <<= 32;
x |= ft.dwLowDateTime;
tv->tv_sec = x / HECTONANOSECONDS - MODERNITYSECONDS;
tv->tv_usec = x % HECTONANOSECONDS / 10;
}

25
libc/conv/kmonthyearday.c Normal file
View File

@ -0,0 +1,25 @@
/*-*- 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/time/time.h"
const unsigned short kMonthYearDay[2][12] = {
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335},
};

View File

@ -25,7 +25,7 @@
/**
* Converts UNIX nanosecond timestamp to Windows COBOL timestamp.
*/
struct NtFileTime timespectofiletime(struct timespec ts) {
struct NtFileTime TimeSpecToFileTime(struct timespec ts) {
uint64_t x;
x = MODERNITYSECONDS;
x += ts.tv_sec * HECTONANOSECONDS;

View File

@ -20,7 +20,7 @@
#include "libc/conv/conv.h"
#include "libc/nt/struct/filetime.h"
struct NtFileTime timetofiletime(int64_t t) {
struct NtFileTime TimeToFileTime(int64_t t) {
uint64_t t2 = (t + MODERNITYSECONDS) * HECTONANOSECONDS;
return (struct NtFileTime){(uint32_t)t2, (uint32_t)(t2 >> 32)};
}

View File

@ -22,7 +22,7 @@
#include "libc/nt/struct/filetime.h"
#include "libc/time/time.h"
struct NtFileTime timevaltofiletime(const struct timeval *tv) {
struct NtFileTime TimeValToFileTime(const struct timeval *tv) {
uint64_t t2 = tv->tv_sec * HECTONANOSECONDS + tv->tv_usec * 10 +
MODERNITYSECONDS * HECTONANOSECONDS;
return (struct NtFileTime){(uint32_t)t2, (uint32_t)(t2 >> 32)};

View File

@ -1,5 +1,6 @@
#ifndef COSMOPOLITAN_LIBC_DOS_H_
#define COSMOPOLITAN_LIBC_DOS_H_
#include "libc/macros.h"
/**
* @fileoverview MS-DOS Data Structures.

128
libc/fmt/fcvt.c Normal file
View File

@ -0,0 +1,128 @@
/*-*- 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 2009 Ian Piumarta │
│ │
│ Permission is hereby granted, free of charge, to any person obtaining a copy │
│ of this software and associated documentation files (the 'Software'), to │
│ deal in the Software without restriction, including without limitation the │
│ rights to use, copy, modify, merge, publish, distribute, and/or sell copies │
│ of the Software, and to permit persons to whom the Software is furnished to │
│ do so, provided that the above copyright notice(s) and this permission │
│ notice appear in all copies of the Software. Inclusion of the above │
│ copyright notice(s) and this permission notice in supporting documentation │
│ would be appreciated but is not required. │
│ │
│ THE SOFTWARE IS PROVIDED 'AS IS'. USE ENTIRELY AT YOUR OWN RISK. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
#include "libc/fmt/fmt.h"
#include "libc/macros.h"
#include "libc/math.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
asm(".ident\t\"\\n\\n\
ecvt, fcvt (MIT License)\\n\
Copyright 2009 Ian Piumarta\"");
/**
* @fileoverview Replacements for the functions ecvt() and fcvt()
*
* These functions were recently deprecated in POSIX. The interface and
* behaviour is identical to the functions that they replace and faster.
*
* For details on the use of these functions, see your ecvt(3) manual
* page. If you don't have one handy, there might still be one available
* here: http://opengroup.org/onlinepubs/007908799/xsh/ecvt.html
*
* @see https://www.piumarta.com/software/fcvt/
*/
static char *Fcvt(double value, int ndigit, int *decpt, int *sign, int fflag) {
static char buf[128];
double i;
uint64_t l, mant;
int exp2, exp10, ptr;
memcpy(&l, &value, 8);
exp2 = (0x7ff & (l >> 52)) - 1023;
mant = l & 0x000fffffffffffffULL;
if ((*sign = l >> 63)) value = -value;
if (exp2 == 0x400) {
*decpt = 0;
return mant ? "nan" : "inf";
}
exp10 = (value == 0) ? !fflag : (int)ceil(log10(value));
if (exp10 < -307) exp10 = -307; /* otherwise overflow in pow() */
value *= pow(10.0, -exp10);
if (value) {
while (value < 0.1) {
value *= 10;
--exp10;
}
while (value >= 1.0) {
value /= 10;
++exp10;
}
}
assert(value == 0 || (0.1 <= value && value < 1.0));
if (fflag) {
if (ndigit + exp10 < 0) {
*decpt = -ndigit;
return "";
}
ndigit += exp10;
}
*decpt = exp10;
if (ARRAYLEN(buf) < ndigit + 2) abort();
ptr = 1;
#if 0 /* slow and safe (and dreadfully boring) */
while (ptr <= ndigit) {
i;
value = modf(value * 10, &i);
buf[ptr++] = '0' + (int)i;
}
if (value >= 0.5) {
while (--ptr && ++buf[ptr] > '9') {
buf[ptr] = '0';
}
}
#else /* faster */
memcpy(&l, &value, 8);
exp2 = (0x7ff & (l >> 52)) - 1023;
assert(value == 0 || (-4 <= exp2 && exp2 <= -1));
mant = l & 0x000fffffffffffffULL;
if (exp2 == -1023) {
++exp2;
} else {
mant |= 0x0010000000000000ULL;
}
mant <<= (exp2 + 4); /* 56-bit denormalised signifier */
while (ptr <= ndigit) {
mant &= 0x00ffffffffffffffULL; /* mod 1.0 */
mant = (mant << 1) + (mant << 3);
buf[ptr++] = '0' + (mant >> 56);
}
if (mant & 0x0080000000000000ULL) /* 1/2 << 56 */
while (--ptr && ++buf[ptr] > '9') buf[ptr] = '0';
#endif
if (ptr) {
buf[ndigit + 1] = 0;
return buf + 1;
}
if (fflag) {
++ndigit;
++*decpt;
}
buf[0] = '1';
buf[ndigit] = 0;
return buf;
}
char *ecvt(double value, int ndigit, int *decpt, int *sign) {
return Fcvt(value, ndigit, decpt, sign, 0);
}
char *fcvt(double value, int ndigit, int *decpt, int *sign) {
return Fcvt(value, ndigit, decpt, sign, 1);
}

View File

@ -29,6 +29,8 @@ char *strerror(int) returnsnonnull nothrow nocallback;
int strerror_r(int, char *, size_t) nothrow nocallback;
int palandprintf(void *, void *, const char *, va_list) hidden;
char *itoa(int, char *, int) compatfn;
char *fcvt(double, int, int *, int *);
char *ecvt(double, int, int *, int *);
/*───────────────────────────────────────────────────────────────────────────│─╗
│ cosmopolitan § string formatting » optimizations ─╬─│┼

View File

@ -40,7 +40,7 @@
* @see xdtoa() for higher precision at the cost of bloat
* @see palandprintf() which is intended caller
*/
int ftoa(int out(int, void *), void *arg, long double value, int prec,
int ftoa(int out(long, void *), void *arg, long double value, int prec,
unsigned long width, unsigned long flags) {
long whole, frac;
long double tmp, diff;

View File

@ -31,7 +31,7 @@
uintmax_t __udivmodti4(uintmax_t, uintmax_t, uintmax_t *);
static int ntoaformat(int out(int, void *), void *arg, char *buf, unsigned len,
static int ntoaformat(int out(long, void *), void *arg, char *buf, unsigned len,
bool negative, unsigned log2base, unsigned prec,
unsigned width, unsigned char flags) {
unsigned i, idx;
@ -103,7 +103,7 @@ static int ntoaformat(int out(int, void *), void *arg, char *buf, unsigned len,
return 0;
}
int ntoa2(int out(int, void *), void *arg, uintmax_t value, bool neg,
int ntoa2(int out(long, void *), void *arg, uintmax_t value, bool neg,
unsigned log2base, unsigned prec, unsigned width, unsigned flags,
const char *alphabet) {
uintmax_t remainder;
@ -135,7 +135,7 @@ int ntoa2(int out(int, void *), void *arg, uintmax_t value, bool neg,
return ntoaformat(out, arg, buf, len, neg, log2base, prec, width, flags);
}
int ntoa(int out(int, void *), void *arg, va_list va, unsigned char signbit,
int ntoa(int out(long, void *), void *arg, va_list va, unsigned char signbit,
unsigned long log2base, unsigned long prec, unsigned long width,
unsigned char flags, const char *lang) {
bool neg;

View File

@ -75,7 +75,7 @@ static int ppatoi(const char **str) {
* - `%Lf` long double
* - `%p` pointer (48-bit hexadecimal)
*
* Length Modifiers
* Size Modifiers
*
* - `%hhd` char (8-bit)
* - `%hd` short (16-bit)
@ -89,7 +89,11 @@ static int ppatoi(const char **str) {
* - `%08d` fixed columns w/ zero leftpadding
* - `%8d` fixed columns w/ space leftpadding
* - `%*s` variable column string (thompson-pike)
* - `%.*s` variable column data (ignore nul terminator)
*
* Precision Modifiers
*
* - `%.8s` supplied character length (ignore nul terminator)
* - `%.*s` supplied character length argument (ignore nul terminator)
*
* Formatting Modifiers
*
@ -112,9 +116,9 @@ hidden int palandprintf(void *fn, void *arg, const char *format, va_list va) {
long double ldbl;
wchar_t charbuf[3];
const char *alphabet;
int (*out)(int, void *);
int (*out)(long, void *);
unsigned char signbit, log2base;
int w, rc, flags, width, lasterr, precision;
int w, flags, width, lasterr, precision;
lasterr = errno;
out = fn ? fn : (int (*)(int, void *))missingno;
@ -255,7 +259,8 @@ hidden int palandprintf(void *fn, void *arg, const char *format, va_list va) {
case 'u': {
flags &= ~FLAGS_HASH; /* no hash for dec format */
DoNumber:
if (weaken(ntoa)(out, arg, va, signbit, log2base, precision, width,
if (!weaken(ntoa) ||
weaken(ntoa)(out, arg, va, signbit, log2base, precision, width,
flags, alphabet) == -1) {
return -1;
}
@ -269,7 +274,8 @@ hidden int palandprintf(void *fn, void *arg, const char *format, va_list va) {
} else {
ldbl = va_arg(va, double);
}
if (weaken(ftoa)(out, arg, ldbl, precision, width, flags) == -1) {
if (!weaken(ftoa) ||
weaken(ftoa)(out, arg, ldbl, precision, width, flags) == -1) {
return -1;
}
break;
@ -297,8 +303,10 @@ hidden int palandprintf(void *fn, void *arg, const char *format, va_list va) {
case 's':
p = va_arg(va, void *);
showstr:
rc = weaken(stoa)(out, arg, p, flags, precision, width, signbit, qchar);
if (rc == -1) return -1;
if (!weaken(stoa) || weaken(stoa)(out, arg, p, flags, precision, width,
signbit, qchar) == -1) {
return -1;
}
break;
case '%':

View File

@ -7,12 +7,12 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
int spacepad(int(int, void *), void *, unsigned long) hidden;
int ftoa(int(int, void *), void *, long double, int, unsigned long,
int spacepad(int(long, void *), void *, unsigned long) hidden;
int ftoa(int(long, void *), void *, long double, int, unsigned long,
unsigned long) hidden;
int stoa(int(int, void *), void *, void *, unsigned long, unsigned long,
int stoa(int(long, void *), void *, void *, unsigned long, unsigned long,
unsigned long, unsigned char, unsigned char) hidden;
int ntoa(int(int, void *), void *, va_list, unsigned char, unsigned long,
int ntoa(int(long, void *), void *, va_list, unsigned char, unsigned long,
unsigned long, unsigned long, unsigned char, const char *) hidden;
COSMOPOLITAN_C_END_

View File

@ -19,7 +19,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/fmt/palandprintf.h"
int spacepad(int out(int, void *), void *arg, unsigned long n) {
int spacepad(int out(long, void *), void *arg, unsigned long n) {
int i, rc;
for (rc = i = 0; i < n; ++i) rc |= out(' ', arg);
return rc;

View File

@ -17,47 +17,54 @@
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
│ 02110-1301 USA │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.h"
#include "libc/bits/weaken.h"
#include "libc/escape/escape.h"
#include "libc/fmt/fmt.h"
#include "libc/fmt/paland.inc"
#include "libc/fmt/palandprintf.h"
#include "libc/nexgen32e/tinystrlen.h"
#include "libc/str/internal.h"
#include "libc/str/str.h"
#include "libc/str/tpdecode.h"
#include "libc/str/tpencode.h"
#include "libc/str/thompike.h"
#include "libc/str/tpenc.h"
#include "libc/str/utf16.h"
#include "libc/unicode/unicode.h"
forceinline unsigned long tpiencode(wint_t wc) {
char buf[8];
memset(buf, 0, sizeof(buf));
tpencode(buf, sizeof(buf), wc, false);
return read64le(buf);
typedef int (*emit_f)(int (*)(long, void *), void *, wint_t);
static int StoaEmitByte(int f(long, void *), void *a, wint_t c) {
return f(c, a);
}
forceinline int emitwc(int out(int, void *), void *arg, unsigned flags,
wint_t wc) {
unsigned long pending;
if (flags & FLAGS_QUOTE) {
if (wc > 127) {
pending = tpiencode(wc);
} else {
pending = cescapec(wc);
}
} else {
pending = tpiencode(wc);
}
static int StoaEmitWordEncodedString(int f(long, void *), void *a, uint64_t w) {
do {
if (out(pending & 0xff, arg) == -1) return -1;
} while ((pending >>= 8));
if (f(w & 0xff, a) == -1) {
return -1;
}
} while ((w >>= 8));
return 0;
}
forceinline int emitquote(int out(int, void *), void *arg, unsigned flags,
char ch, unsigned char signbit) {
static int StoaEmitUnicode(int f(long, void *), void *a, wint_t c) {
if (0 <= c && c <= 127) {
return f(c, a);
} else {
return StoaEmitWordEncodedString(f, a, tpenc(c));
}
}
static int StoaEmitQuoted(int f(long, void *), void *a, wint_t c) {
if (0 <= c && c <= 127) {
return StoaEmitWordEncodedString(f, a, cescapec(c));
} else {
return StoaEmitWordEncodedString(f, a, tpenc(c));
}
}
static int StoaEmitVisualized(int f(long, void *), void *a, wint_t c) {
return StoaEmitUnicode(f, a, (*weaken(kCp437))[c]);
}
static int StoaEmitQuote(int out(long, void *), void *arg, unsigned flags,
char ch, unsigned char signbit) {
if (flags & FLAGS_REPR) {
if (signbit == 63) {
if (out('L', arg) == -1) return -1;
@ -78,13 +85,15 @@ forceinline int emitquote(int out(int, void *), void *arg, unsigned flags,
*
* @see palandprintf()
*/
int stoa(int out(int, void *), void *arg, void *data, unsigned long flags,
int stoa(int out(long, void *), void *arg, void *data, unsigned long flags,
unsigned long precision, unsigned long width, unsigned char signbit,
unsigned char qchar) {
char *p;
wint_t wc;
unsigned w, c;
bool ignorenul;
unsigned n;
emit_f emit;
bool justdobytes;
unsigned w, c, pad;
p = data;
if (!p) {
@ -93,89 +102,102 @@ int stoa(int out(int, void *), void *arg, void *data, unsigned long flags,
flags |= FLAGS_NOQUOTE;
signbit = 0;
} else {
if (emitquote(out, arg, flags, qchar, signbit) == -1) return -1;
if (StoaEmitQuote(out, arg, flags, qchar, signbit) == -1) return -1;
}
w = precision ? precision : -1;
if (!(flags & FLAGS_PRECISION)) {
if (signbit == 63) {
precision = tinywcsnlen((const wchar_t *)p, -1);
} else if (signbit == 15) {
precision = tinystrnlen16((const char16_t *)p, -1);
} else {
precision = strlen(p);
}
}
pad = 0;
if (width) {
w = precision;
if (signbit == 63) {
if (weaken(wcsnwidth)) {
w = weaken(wcsnwidth)((const wchar_t *)p, w);
} else {
w = tinywcsnlen((const wchar_t *)p, w);
w = weaken(wcsnwidth)((const wchar_t *)p, precision);
}
} else if (signbit == 15) {
if (weaken(strnwidth16)) {
w = weaken(strnwidth16)((const char16_t *)p, w);
} else {
w = tinystrnlen16((const char16_t *)p, w);
w = weaken(strnwidth16)((const char16_t *)p, precision);
}
} else if (weaken(strnwidth)) {
w = weaken(strnwidth)(p, w);
} else {
w = strnlen(p, w);
w = weaken(strnwidth)(p, precision);
}
if (w < width) {
pad = width - w;
}
}
if (flags & FLAGS_PRECISION) {
w = MIN(w, precision);
if (pad && !(flags & FLAGS_LEFT)) {
if (spacepad(out, arg, pad) == -1) return -1;
}
if (w < width && !(flags & FLAGS_LEFT)) {
if (spacepad(out, arg, width - w) == -1) return -1;
justdobytes = false;
if (signbit == 15 || signbit == 63) {
if (flags & FLAGS_QUOTE) {
emit = StoaEmitQuoted;
} else {
emit = StoaEmitUnicode;
}
} else if ((flags & FLAGS_HASH) && weaken(kCp437)) {
justdobytes = true;
emit = StoaEmitVisualized;
} else if (flags & FLAGS_QUOTE) {
emit = StoaEmitQuoted;
} else {
justdobytes = true;
emit = StoaEmitByte;
}
ignorenul = (flags & FLAGS_PRECISION) && (flags & (FLAGS_HASH | FLAGS_QUOTE));
for (; !(flags & FLAGS_PRECISION) || precision; --precision) {
if (signbit == 15) {
if ((wc = *(const char16_t *)p) || ignorenul) {
if ((1 <= wc && wc <= 0xD7FF)) {
if (justdobytes) {
while (precision--) {
wc = *p++ & 0xff;
if (emit(out, arg, wc) == -1) return -1;
}
} else {
while (precision--) {
if (signbit == 15) {
wc = *(const char16_t *)p;
if (IsUcs2(wc)) {
p += sizeof(char16_t);
} else if ((wc & UTF16_MASK) == UTF16_CONT) {
} else if (IsUtf16Cont(wc)) {
p += sizeof(char16_t);
continue;
} else if (!precision) {
break;
} else {
char16_t buf[4] = {wc};
if (!(flags & FLAGS_PRECISION) || precision > 1) {
buf[1] = ((const char16_t *)p)[1];
--precision;
wc = MergeUtf16(wc, *(const char16_t *)p);
}
} else if (signbit == 63) {
wc = *(const wint_t *)p;
p += sizeof(wint_t);
if (!wc) break;
} else {
wc = *p++ & 0xff;
if (!isascii(wc)) {
if (ThomPikeCont(wc)) continue;
n = ThomPikeLen(wc) - 1;
wc = ThomPikeByte(wc);
if (n > precision) break;
precision -= n;
while (n--) {
wc = ThomPikeMerge(wc, *p++);
}
p += max(1, getutf16((const char16_t *)p, &wc)) * sizeof(char16_t);
}
} else {
break;
}
} else if (signbit == 63) {
wc = *(const wint_t *)p;
p += sizeof(wint_t);
if (!wc) break;
} else if (flags & FLAGS_HASH) {
c = *p & 0xff;
if (!c && !ignorenul) break;
wc = (*weaken(kCp437))[c];
p++;
} else {
if ((wc = *p & 0xff) || ignorenul) {
if (1 <= wc && wc <= 0x7f) {
++p;
} else if (iscont(wc & 0xff)) {
++p;
continue;
} else {
char buf[8];
memset(buf, 0, sizeof(buf));
memcpy(buf, p,
!(flags & FLAGS_PRECISION) ? 7 : MIN(7, precision - 1));
p += max(1, tpdecode(p, &wc));
}
} else {
break;
}
if (emit(out, arg, wc) == -1) return -1;
}
if (emitwc(out, arg, flags, wc) == -1) return -1;
}
if (w <= width && (flags & FLAGS_LEFT)) {
if (spacepad(out, arg, width - w) == -1) return -1;
if (pad && (flags & FLAGS_LEFT)) {
if (spacepad(out, arg, pad) == -1) return -1;
}
if (!(flags & FLAGS_NOQUOTE) && (flags & FLAGS_REPR)) {

View File

@ -25,17 +25,13 @@
struct SprintfStr {
char *p;
size_t i, n;
size_t i;
size_t n;
};
static int vsnprintfputchar(unsigned char c, struct SprintfStr *str) {
if (str->i < str->n) {
if (str->p) str->p[str->i] = c;
str->i++;
} else {
if (!IsTrustworthy() && str->i >= INT_MAX) abort();
str->i++;
}
if (str->i < str->n) str->p[str->i] = c;
str->i++;
return 0;
}
@ -48,15 +44,11 @@ static int vsnprintfputchar(unsigned char c, struct SprintfStr *str) {
* @return number of bytes written, excluding the NUL terminator; or,
* if the output buffer wasn't passed, or was too short, then the
* number of characters that *would* have been written is returned
* @throw EOVERFLOW when a formatted field exceeds its limit, which can
* be checked by setting errno to 0 before calling
* @see palandprintf() and printf() for detailed documentation
*/
int(vsnprintf)(char *buf, size_t size, const char *fmt, va_list va) {
struct SprintfStr str = {buf, 0, size};
palandprintf(vsnprintfputchar, &str, fmt, va);
if (str.p && str.n) {
str.p[min(str.i, str.n - 1)] = '\0';
}
if (str.n) str.p[min(str.i, str.n - 1)] = '\0';
return str.i;
}

View File

@ -66,7 +66,7 @@
#endif
#define BIGPAGESIZE 0x200000
#define STACKSIZE 0x80000 /* todo: zlib's fault? */
#define STACKSIZE 0x10000
#define FRAMESIZE 0x10000 /* 8086 */
#define PAGESIZE 0x1000 /* i386+ */
#define BUFSIZ 0x1000 /* best stdio default */

View File

@ -3,7 +3,7 @@
PKGS += LIBC_LINUX
LIBC_LINUX_HDRS = $(filter %.h,$(LIBC_FILES))
LIBC_LINUX_HDRS = $(filter %.h,$(LIBC_LINUX_FILES))
LIBC_LINUX_FILES := $(wildcard libc/linux/*)
LIBC_LINUX_CHECKS = $(LIBC_LINUX_HDRS:%=o/$(MODE)/%.ok)

View File

@ -41,6 +41,8 @@
#include "libc/sysv/consts/prot.h"
#include "third_party/dlmalloc/dlmalloc.h"
STATIC_YOINK("_init_asan");
/**
* @fileoverview Cosmopolitan Address Sanitizer Runtime.
*

View File

@ -31,6 +31,10 @@
#include "libc/str/str.h"
#include "libc/sysv/consts/auxv.h"
STATIC_YOINK("ntoa");
STATIC_YOINK("stoa");
STATIC_YOINK("ftoa");
/**
* Handles failure of CHECK_xx() macros.
*/
@ -47,30 +51,30 @@ relegated void __check_fail(const char *suffix, const char *opstr,
if (!memccpy(sufbuf, suffix, '\0', sizeof(sufbuf))) strcpy(sufbuf, "?");
strtoupper(sufbuf);
fprintf(stderr,
"check failed\n"
"\tCHECK_%s(%s, %s);\n"
"\t\t → %#lx (%s)\n"
"\t\t%s %#lx (%s)\n",
sufbuf, wantstr, gotstr, want, wantstr, opstr, got, gotstr);
(fprintf)(stderr,
"check failed\n"
"\tCHECK_%s(%s, %s);\n"
"\t\t → %#lx (%s)\n"
"\t\t%s %#lx (%s)\n",
sufbuf, wantstr, gotstr, want, wantstr, opstr, got, gotstr);
if (!isempty(fmt)) {
fputc('\t', stderr);
va_start(va, fmt);
vfprintf(stderr, fmt, va);
(vfprintf)(stderr, fmt, va);
va_end(va);
fputc('\n', stderr);
}
fprintf(stderr, "\t%s\n\t%s%s%s%s\n", strerror(lasterr), SUBTLE,
getauxval(AT_EXECFN), g_argc > 1 ? " \\" : "", RESET);
(fprintf)(stderr, "\t%s\n\t%s%s%s%s\n", strerror(lasterr), SUBTLE,
getauxval(AT_EXECFN), g_argc > 1 ? " \\" : "", RESET);
for (i = 1; i < g_argc; ++i) {
fprintf(stderr, "\t\t%s%s\n", g_argv[i], i < g_argc - 1 ? " \\" : "");
(fprintf)(stderr, "\t\t%s%s\n", g_argv[i], i < g_argc - 1 ? " \\" : "");
}
if (!IsTiny() && lasterr == ENOMEM) {
fprintf(stderr, "\n");
(fprintf)(stderr, "\n");
fflush(stderr);
PrintMemoryIntervals(fileno(stderr), &_mmi);
}

View File

@ -15,7 +15,7 @@
* Log level for compile-time DCE.
*/
#ifndef LOGGABLELEVEL
#ifndef NDEBUG
#ifndef TINY
#define LOGGABLELEVEL kLogDebug
/* #elif IsTiny() */
/* #define LOGGABLELEVEL kLogInfo */

View File

@ -65,6 +65,11 @@ $(LIBC_LOG_A_OBJS): \
$(NO_MAGIC) \
-fwrapv
ifeq (,$(MODE))
LIBC_LOG_ASAN = o/$(MODE)/libc/log/asan.o
endif
LIBC_LOG_ASAN_A = o/$(MODE)/libc/log/log.a
LIBC_LOG_LIBS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)))
LIBC_LOG_SRCS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)_SRCS))
LIBC_LOG_HDRS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)_HDRS))

View File

@ -37,6 +37,10 @@
#define kNontrivialSize (8 * 1000 * 1000)
STATIC_YOINK("ntoa");
STATIC_YOINK("stoa");
STATIC_YOINK("ftoa");
static int loglevel2char(unsigned level) {
switch (level) {
case kLogInfo:
@ -47,6 +51,8 @@ static int loglevel2char(unsigned level) {
return 'W';
case kLogFatal:
return 'F';
case kLogVerbose:
return 'V';
default:
return '?';
}
@ -80,8 +86,7 @@ void(vflogf)(unsigned level, const char *file, int line, FILE *f,
long double t2;
const char *prog;
int64_t secs, nsec, dots;
char zonebuf[8], *zonebufp;
char timebuf[24], *timebufp;
char timebuf[32], *timebufp;
if (!f) f = g_logfile;
if (fileno(f) == -1) return;
t2 = nowl();
@ -89,22 +94,19 @@ void(vflogf)(unsigned level, const char *file, int line, FILE *f,
nsec = rem1000000000int64(t2 * 1e9L);
if (secs > ts.tv_sec) {
localtime_r(&secs, &tm);
strftime(timebuf, sizeof(timebuf), "%Y%m%dT%H%M%S", &tm);
strftime(zonebuf, sizeof(zonebuf), "%Z", &tm);
strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%S.", &tm);
timebufp = timebuf;
zonebufp = zonebuf;
dots = nsec;
} else {
timebufp = "---------------";
zonebufp = "---";
timebufp = "--------------------";
dots = nsec - ts.tv_nsec;
}
ts.tv_sec = secs;
ts.tv_nsec = nsec;
prog = basename(program_invocation_name);
if (fprintf(f, "%c%s%s%06ld:%s:%d:%.*s:%d] ", loglevel2char(level), timebufp,
zonebufp, rem1000000int64(div1000int64(dots)), file, line,
strchrnul(prog, '.') - prog, prog, getpid()) <= 0) {
if ((fprintf)(f, "%c%s%06ld:%s:%d:%.*s:%d] ", loglevel2char(level), timebufp,
rem1000000int64(div1000int64(dots)), file, line,
strchrnul(prog, '.') - prog, prog, getpid()) <= 0) {
vflogf_onfail(f);
}
(vfprintf)(f, fmt, va);
@ -112,7 +114,7 @@ void(vflogf)(unsigned level, const char *file, int line, FILE *f,
fputc('\n', f);
if (level == kLogFatal) {
startfatal(file, line);
fprintf(stderr, "fatal error see logfile\n");
(fprintf)(stderr, "fatal error see logfile\n");
die();
unreachable;
}

View File

@ -1,6 +1,8 @@
#ifndef COSMOPOLITAN_LIBC_NT_WINSOCK_H_
#define COSMOPOLITAN_LIBC_NT_WINSOCK_H_
#include "libc/nt/struct/overlapped.h"
#include "libc/nt/struct/pollfd.h"
#include "libc/sock/sock.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#if 0
@ -55,10 +57,6 @@ COSMOPOLITAN_C_START_
#define kNtTfUseSystemThread 0x10
#define kNtTfUseKernelApc 0x20
struct sockaddr;
struct sockaddr_in;
struct pollfd$nt;
enum NtWsaEComparator { COMP_EQUAL, COMP_NOTLESS };
enum NtWsaCompletionType {

View File

@ -53,8 +53,7 @@ _executive:
call _setstack
mov %eax,%edi
call exit
9: .endfn _executive,weak,hidden
.endfn _executive,weak,hidden
ud2
#ifdef __PG__

View File

@ -28,9 +28,9 @@
*/
void *_getstack(void) {
char *p;
p = mmap((char *)0x700000000000 - STACKSIZE, STACKSIZE,
PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1,
0);
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;
}

View File

@ -28,8 +28,11 @@
*/
bool isheap(void *p) {
int x, i;
#if 1
register intptr_t rsp asm("rsp");
if ((intptr_t)p >= rsp) return false;
#endif
if ((intptr_t)p <= (intptr_t)_end) return false;
x = (intptr_t)p >> 16;
i = FindMemoryInterval(&_mmi, x);
return i < _mmi.i && x >= _mmi.p[i].x && x <= _mmi.p[i].y;

View File

@ -17,11 +17,9 @@
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
│ 02110-1301 USA │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/fmt/fmt.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
#include "libc/sysv/errfuns.h"
#include "libc/conv/itoa.h"
#include "libc/sysv/consts/af.h"
#include "libc/sysv/errfuns.h"
/**
* Formats internet address to string.
@ -33,11 +31,21 @@
* @return dst on success or NULL w/ errno
*/
const char *inet_ntop(int af, const void *src, char *dst, uint32_t size) {
char *p;
unsigned char *ip4;
if (src) {
if (af == AF_INET) {
unsigned char *p = (unsigned char *)src;
if (snprintf(dst, size, "%hhu.%hhu.%hhu.%hhu", p[0], p[1], p[2], p[3]) <
size) {
if (size >= 16) {
p = dst;
ip4 = src;
p += uint64toarray_radix10(ip4[0], p);
*p++ = '.';
p += uint64toarray_radix10(ip4[1], p);
*p++ = '.';
p += uint64toarray_radix10(ip4[2], p);
*p++ = '.';
p += uint64toarray_radix10(ip4[3], p);
*p = '\0';
return dst;
} else {
enospc();

View File

@ -37,6 +37,7 @@ int fwritebuf(FILE *f) {
unsigned bytes;
bytes = (f->beg < f->end ? f->end : f->size) - f->beg;
if ((put = write(f->fd, &f->buf[f->beg], bytes)) == -1) {
if (errno == EINTR) return 0;
return (int)fseterrno(f);
}
f->beg = (unsigned)((f->beg + put) & (f->size - 1));

View File

@ -19,6 +19,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/errno.h"
#include "libc/str/str.h"
#include "libc/str/utf16.h"
/**
* Decodes UTF-16 character.
@ -30,16 +31,15 @@
*/
forcealignargpointer unsigned(getutf16)(const char16_t *p, wint_t *wc) {
unsigned skip = 0;
while ((p[skip] & UTF16_MASK) == UTF16_CONT) skip++;
if ((p[skip] & UTF16_MASK) != UTF16_MOAR) {
while (IsUtf16Cont(p[skip])) skip++;
if (IsUcs2(p[skip])) {
*wc = p[skip];
return skip + 1;
} else if ((p[skip + 1] & UTF16_MASK) != UTF16_CONT) {
} else if (IsUtf16Cont(p[skip + 1])) {
*wc = INVALID_CODEPOINT;
return -1;
} else {
*wc = 0x10000 + ((((unsigned)p[skip + 0] - 0xd800) << 10) +
((unsigned)p[skip + 1] - 0xdc00));
*wc = MergeUtf16(p[skip], p[skip + 1]);
return skip + 2;
}
}

View File

@ -64,10 +64,6 @@ void *isnotplaintext(const void *, size_t) nothrow nocallback nosideeffect;
#define INVALID_CODEPOINT 0xfffd
#define UTF16_MASK 0b1111110000000000
#define UTF16_MOAR 0b1101100000000000 /* 0xD800..0xDBFF */
#define UTF16_CONT 0b1101110000000000 /* 0xDC00..0xDBFF */
unsigned getutf16(const char16_t *, wint_t *);
int pututf16(char16_t *, size_t, wint_t, bool);
int iswalnum(wint_t);

View File

@ -18,11 +18,14 @@
│ 02110-1301 USA │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/str/str.h"
#include "libc/str/utf16.h"
/**
* Returns number of characters in UTF-16 or UCS-2 string.
*/
size_t strclen16(const char16_t *s) { return strnclen16(s, -1ull); }
size_t strclen16(const char16_t *s) {
return strnclen16(s, -1ull);
}
noinline size_t strnclen16(const char16_t *p, size_t n) {
size_t l = 0;

View File

@ -2,9 +2,10 @@
#define COSMOPOLITAN_LIBC_STR_THOMPIKE_H_
#include "libc/nexgen32e/bsr.h"
#define ThomPikeCont(x) ((x & 0b11000000) == 0b10000000)
#define ThomPikeByte(x) (x & (((1 << ThomPikeMsb(x)) - 1) | 3))
#define ThomPikeLen(x) (7 - ThomPikeMsb(x))
#define ThomPikeMsb(x) (x < 252 ? bsr(~x & 0xff) : 1)
#define ThomPikeCont(x) (((x)&0b11000000) == 0b10000000)
#define ThomPikeByte(x) ((x) & (((1 << ThomPikeMsb(x)) - 1) | 3))
#define ThomPikeLen(x) (7 - ThomPikeMsb(x))
#define ThomPikeMsb(x) ((x) < 252 ? bsr(~(x)&0xff) : 1)
#define ThomPikeMerge(x, y) ((x) << 6 | (y)&0b00111111)
#endif /* COSMOPOLITAN_LIBC_STR_THOMPIKE_H_ */

12
libc/str/utf16.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef COSMOPOLITAN_LIBC_STR_UTF16_H_
#define COSMOPOLITAN_LIBC_STR_UTF16_H_
#define UTF16_MASK 0xfc00
#define UTF16_MOAR 0xd800 /* 0xD800..0xDBFF */
#define UTF16_CONT 0xdc00 /* 0xDC00..0xDBFF */
#define IsUcs2(wc) (((wc)&UTF16_MASK) != UTF16_MOAR)
#define IsUtf16Cont(wc) (((wc)&UTF16_MASK) != UTF16_MOAR)
#define MergeUtf16(lo, hi) ((((lo)-0xD800) << 10) + ((hi)-0xDC00) + 0x10000)
#endif /* COSMOPOLITAN_LIBC_STR_UTF16_H_ */

View File

@ -1421,11 +1421,11 @@ offtime(timep, offset)
** where, to make the math easy, the answer for year zero is defined as zero.
*/
pureconst static int
pureconst optimizespeed static int
leaps_thru_end_of(y)
register const int y;
{
return (y >= 0) ? (y / 4 - div100int64(y) + y / 400) :
return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
-(leaps_thru_end_of(-(y + 1)) + 1);
}
@ -1605,15 +1605,19 @@ timesub(timep, offset, sp, tmp)
** Simplified normalize logic courtesy Paul Eggert.
*/
static int
static inline int
increment_overflow(number, delta)
int * number;
int delta;
{
#ifdef __GNUC__
return __builtin_add_overflow(*number, delta, number);
#else
int number0;
number0 = *number;
*number += delta;
return (*number < number0) != (delta < 0);
#endif
}
static int

View File

@ -12,6 +12,7 @@ extern const char kWeekdayNameShort[7][4];
extern const char kWeekdayName[7][10];
extern const char kMonthNameShort[12][4];
extern const char kMonthName[12][10];
extern const unsigned short kMonthYearDay[2][12];
extern char *tzname[2];
extern long CLOCKS_PER_SEC;

View File

@ -47,9 +47,9 @@ static noinline long times2(struct tms *out_times, struct rusage *ru) {
&KernelTime, &UserTime)) {
return winerr();
}
filetimetotimeval(&tv, UserTime);
FileTimeToTimeVal(&tv, UserTime);
out_times->tms_utime = convertmicros(&tv, tick);
filetimetotimeval(&tv, KernelTime);
FileTimeToTimeVal(&tv, KernelTime);
out_times->tms_stime = convertmicros(&tv, tick);
out_times->tms_cutime = 0;
out_times->tms_cstime = 0;

View File

@ -57,6 +57,7 @@
#define kZipCfileOffsetLastmodifieddate 14
#define kZipCfileOffsetCrc32 16
#define kZipCfileOffsetCompressedsize 20
#define kZipCfileOffsetUncompressedsize 24
#define kZipCfileOffsetExternalattributes 38
#define kZipCfileOffsetOffset 42
@ -71,10 +72,10 @@
#define kZipGflagUtf8 0x800
#define kZipExtraHdrSize 4
#define kZipExtraZip64 0x0001
#define kZipExtraNtfs 0x000a
#define kZipExtraNtfsFiletimes 0x0001
#define kZipExtraHdrSize 4
#define kZipExtraZip64 0x0001
#define kZipExtraNtfs 0x000a
#define kZipExtraExtendedTimestamp 0x5455
#define kZipCfileMagic "PK\001\002"
@ -105,9 +106,10 @@
READ16LE((P) + kZipCfileOffsetLastmodifiedtime) /* @see DOS_TIME() */
#define ZIP_CFILE_LASTMODIFIEDDATE(P) \
READ16LE((P) + kZipCfileOffsetLastmodifieddate) /* @see DOS_DATE() */
#define ZIP_CFILE_CRC32(P) READ32LE((P) + kZipCfileOffsetCrc32)
#define ZIP_CFILE_COMPRESSEDSIZE(P) READ32LE(P + kZipCfileOffsetCompressedsize)
#define ZIP_CFILE_UNCOMPRESSEDSIZE(P) READ32LE((P) + 24)
#define ZIP_CFILE_CRC32(P) READ32LE((P) + kZipCfileOffsetCrc32)
#define ZIP_CFILE_COMPRESSEDSIZE(P) READ32LE(P + kZipCfileOffsetCompressedsize)
#define ZIP_CFILE_UNCOMPRESSEDSIZE(P) \
READ32LE((P) + kZipCfileOffsetUncompressedsize)
#define ZIP_CFILE_NAMESIZE(P) READ16LE((P) + 28)
#define ZIP_CFILE_EXTRASIZE(P) READ16LE((P) + 30)
#define ZIP_CFILE_COMMENTSIZE(P) READ16LE((P) + 32)
@ -124,7 +126,7 @@
(ZIP_CFILE_NAMESIZE(P) + ZIP_CFILE_EXTRASIZE(P) + ZIP_CFILE_COMMENTSIZE(P) + \
kZipCfileHdrMinSize)
/* central directory file header */
/* local file header */
#define ZIP_LFILE_MAGIC(P) READ32LE(P)
#define ZIP_LFILE_VERSIONNEED(P) ((P)[4])
#define ZIP_LFILE_OSNEED(P) ((P)[5])

View File

@ -29,7 +29,7 @@
*/
int __zipos_close(struct ZiposHandle *h) {
if (h) {
munmap(h->map, h->mapsize);
free(h->map);
free(h);
}
return 0;

View File

@ -27,16 +27,14 @@
ssize_t __zipos_find(struct Zipos *zipos, const struct ZiposUri *name) {
size_t i, cf;
if ((zipos = __zipos_get())) {
assert(ZIP_CDIR_MAGIC(zipos->cdir) == kZipCdirHdrMagic);
for (i = 0, cf = ZIP_CDIR_OFFSET(zipos->cdir);
i < ZIP_CDIR_RECORDS(zipos->cdir);
++i, cf += ZIP_CFILE_HDRSIZE(zipos->map + cf)) {
assert(ZIP_CFILE_MAGIC(zipos->map + cf) == kZipCfileHdrMagic);
if (name->len == ZIP_CFILE_NAMESIZE(zipos->map + cf) &&
memcmp(name->path, ZIP_CFILE_NAME(zipos->map + cf), name->len) == 0) {
return cf;
}
assert(ZIP_CDIR_MAGIC(zipos->cdir) == kZipCdirHdrMagic);
for (i = 0, cf = ZIP_CDIR_OFFSET(zipos->cdir);
i < ZIP_CDIR_RECORDS(zipos->cdir);
++i, cf += ZIP_CFILE_HDRSIZE(zipos->map + cf)) {
assert(ZIP_CFILE_MAGIC(zipos->map + cf) == kZipCfileHdrMagic);
if (name->len == ZIP_CFILE_NAMESIZE(zipos->map + cf) &&
memcmp(name->path, ZIP_CFILE_NAME(zipos->map + cf), name->len) == 0) {
return cf;
}
}
return -1;

View File

@ -99,9 +99,9 @@ static int __zipos_load(struct Zipos *zipos, size_t cf, unsigned flags,
if ((h->size = ZIP_LFILE_UNCOMPRESSEDSIZE(zipos->map + lf))) {
if (ZIP_LFILE_COMPRESSIONMETHOD(zipos->map + lf)) {
assert(ZIP_LFILE_COMPRESSEDSIZE(zipos->map + lf));
h->mapsize = ROUNDUP(h->size + FRAMESIZE, FRAMESIZE);
if ((h->map = mapanon(h->mapsize)) != MAP_FAILED) {
h->mem = h->map + FRAMESIZE / 2;
h->mapsize = h->size;
if ((h->map = malloc(h->mapsize)) != MAP_FAILED) {
h->mem = h->map;
if ((IsTiny() ? __zipos_inflate_tiny : __zipos_inflate_fast)(
h, ZIP_LFILE_CONTENT(zipos->map + lf),
ZIP_LFILE_COMPRESSEDSIZE(zipos->map + lf)) == -1) {
@ -132,7 +132,7 @@ static int __zipos_load(struct Zipos *zipos, size_t cf, unsigned flags,
* Loads compressed file from αcτµαlly pδrταblε εxεcµταblε object store.
*
* @param uri is obtained via __zipos_parseuri()
* @asyncsignalsafe
* @note don't call open() from signal handlers
*/
int __zipos_open(const struct ZiposUri *name, unsigned flags, int mode) {
int fd;
@ -140,7 +140,6 @@ int __zipos_open(const struct ZiposUri *name, unsigned flags, int mode) {
sigset_t oldmask;
struct Zipos *zipos;
assert((flags & O_ACCMODE) == O_RDONLY);
sigprocmask(SIG_BLOCK, &kSigsetFull, &oldmask);
if ((zipos = __zipos_get())) {
if ((cf = __zipos_find(zipos, name)) != -1) {
fd = __zipos_load(zipos, cf, flags, mode);
@ -150,6 +149,5 @@ int __zipos_open(const struct ZiposUri *name, unsigned flags, int mode) {
} else {
fd = enoexec();
}
sigprocmask(SIG_SETMASK, &oldmask, NULL);
return fd;
}