mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-22 21:32:31 +00:00
Add fixes performance and static web server
This commit is contained in:
parent
b6793d42d5
commit
c45e46f871
108 changed files with 2927 additions and 819 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
|
|
|
@ -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 \
|
||||
|
|
43
libc/conv/dosdatetimetounix.c
Normal file
43
libc/conv/dosdatetimetounix.c
Normal 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;
|
||||
}
|
|
@ -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};
|
||||
}
|
||||
|
|
|
@ -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
25
libc/conv/kmonthyearday.c
Normal 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},
|
||||
};
|
|
@ -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;
|
||||
|
|
|
@ -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)};
|
||||
}
|
||||
|
|
|
@ -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)};
|
||||
|
|
|
@ -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
128
libc/fmt/fcvt.c
Normal 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);
|
||||
}
|
|
@ -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 ─╬─│┼
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 '%':
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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;
|
||||
|
|
194
libc/fmt/stoa.c
194
libc/fmt/stoa.c
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* Log level for compile-time DCE.
|
||||
*/
|
||||
#ifndef LOGGABLELEVEL
|
||||
#ifndef NDEBUG
|
||||
#ifndef TINY
|
||||
#define LOGGABLELEVEL kLogDebug
|
||||
/* #elif IsTiny() */
|
||||
/* #define LOGGABLELEVEL kLogInfo */
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -53,8 +53,7 @@ _executive:
|
|||
call _setstack
|
||||
mov %eax,%edi
|
||||
call exit
|
||||
9: .endfn _executive,weak,hidden
|
||||
|
||||
.endfn _executive,weak,hidden
|
||||
ud2
|
||||
|
||||
#ifdef __PG__
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
12
libc/str/utf16.h
Normal 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_ */
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
18
libc/zip.h
18
libc/zip.h
|
@ -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])
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
*/
|
||||
int __zipos_close(struct ZiposHandle *h) {
|
||||
if (h) {
|
||||
munmap(h->map, h->mapsize);
|
||||
free(h->map);
|
||||
free(h);
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue