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;
}