mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-24 03:20:30 +00:00
Make numerous improvements
- Python static hello world now 1.8mb - Python static fully loaded now 10mb - Python HTTPS client now uses MbedTLS - Python REPL now completes import stmts - Increase stack size for Python for now - Begin synthesizing posixpath and ntpath - Restore Python \N{UNICODE NAME} support - Restore Python NFKD symbol normalization - Add optimized code path for Intel SHA-NI - Get more Python unit tests passing faster - Get Python help() pagination working on NT - Python hashlib now supports MbedTLS PBKDF2 - Make memcpy/memmove/memcmp/bcmp/etc. faster - Add Mersenne Twister and Vigna to LIBC_RAND - Provide privileged __printf() for error code - Fix zipos opendir() so that it reports ENOTDIR - Add basic chmod() implementation for Windows NT - Add Cosmo's best functions to Python cosmo module - Pin function trace indent depth to that of caller - Show memory diagram on invalid access in MODE=dbg - Differentiate stack overflow on crash in MODE=dbg - Add stb_truetype and tools for analyzing font files - Upgrade to UNICODE 13 and reduce its binary footprint - COMPILE.COM now logs resource usage of build commands - Start implementing basic poll() support on bare metal - Set getauxval(AT_EXECFN) to GetModuleFileName() on NT - Add descriptions to strerror() in non-TINY build modes - Add COUNTBRANCH() macro to help with micro-optimizations - Make error / backtrace / asan / memory code more unbreakable - Add fast perfect C implementation of μ-Law and a-Law audio codecs - Make strtol() functions consistent with other libc implementations - Improve Linenoise implementation (see also github.com/jart/bestline) - COMPILE.COM now suppresses stdout/stderr of successful build commands
This commit is contained in:
parent
fa7b4f5bd1
commit
39bf41f4eb
806 changed files with 77494 additions and 63859 deletions
|
@ -24,6 +24,16 @@
|
|||
/**
|
||||
* Decodes decimal integer from ASCII string.
|
||||
*
|
||||
* atoi 10⁸ 22𝑐 7𝑛𝑠
|
||||
* strtol 10⁸ 37𝑐 12𝑛𝑠
|
||||
* strtoul 10⁸ 35𝑐 11𝑛𝑠
|
||||
* wcstol 10⁸ 30𝑐 10𝑛𝑠
|
||||
* wcstoul 10⁸ 30𝑐 10𝑛𝑠
|
||||
* strtoimax 10⁸ 80𝑐 26𝑛𝑠
|
||||
* strtoumax 10⁸ 78𝑐 25𝑛𝑠
|
||||
* wcstoimax 10⁸ 77𝑐 25𝑛𝑠
|
||||
* wcstoumax 10⁸ 76𝑐 25𝑛𝑠
|
||||
*
|
||||
* @param s is a non-null nul-terminated string
|
||||
* @return the decoded signed saturated integer
|
||||
*/
|
||||
|
|
|
@ -69,6 +69,7 @@ char *dirname(char *);
|
|||
char *basename(const char *) nosideeffect;
|
||||
char *basename_n(const char *, size_t) nosideeffect;
|
||||
bool isabspath(const char *) paramsnonnull() nosideeffect;
|
||||
char *stripext(char *);
|
||||
char *stripexts(char *);
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
|
|
|
@ -391,7 +391,8 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
s = weaken(__fmt_dtoa)(pun.d, 3, prec, &decpt, &sgn, &se);
|
||||
if (decpt == 9999) {
|
||||
Format9999:
|
||||
p = q = memset(special, 0, sizeof(special));
|
||||
bzero(special, sizeof(special));
|
||||
p = q = special;
|
||||
if (sgn) {
|
||||
*q++ = '-';
|
||||
} else if (flags & FLAGS_PLUS) {
|
||||
|
@ -423,12 +424,10 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
if (flags & FLAGS_ZEROPAD) {
|
||||
if (sign) PUT(sign);
|
||||
sign = 0;
|
||||
do
|
||||
PUT('0');
|
||||
do PUT('0');
|
||||
while (--width > 0);
|
||||
} else {
|
||||
do
|
||||
PUT(' ');
|
||||
do PUT(' ');
|
||||
while (--width > 0);
|
||||
}
|
||||
}
|
||||
|
@ -530,12 +529,10 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
if (flags & FLAGS_ZEROPAD) {
|
||||
if (sign) PUT(sign);
|
||||
sign = 0;
|
||||
do
|
||||
PUT('0');
|
||||
do PUT('0');
|
||||
while (--width > 0);
|
||||
} else {
|
||||
do
|
||||
PUT(' ');
|
||||
do PUT(' ');
|
||||
while (--width > 0);
|
||||
}
|
||||
}
|
||||
|
@ -682,12 +679,10 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
PUT(sign);
|
||||
sign = 0;
|
||||
}
|
||||
do
|
||||
PUT('0');
|
||||
do PUT('0');
|
||||
while (--width > 0);
|
||||
} else {
|
||||
do
|
||||
PUT(' ');
|
||||
do PUT(' ');
|
||||
while (--width > 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,6 +58,8 @@ $(LIBC_FMT_A_OBJS): \
|
|||
OVERRIDE_CFLAGS += \
|
||||
-fno-jump-tables
|
||||
|
||||
o/$(MODE)/libc/fmt/formatint64.o \
|
||||
o/$(MODE)/libc/fmt/formatint64thousands.o \
|
||||
o/$(MODE)/libc/fmt/dosdatetimetounix.o \
|
||||
o/$(MODE)/libc/fmt/itoa64radix10.greg.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
|
|
55
libc/fmt/formatint64.c
Normal file
55
libc/fmt/formatint64.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*-*- 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 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/itoa.h"
|
||||
|
||||
/**
|
||||
* Converts unsigned 64-bit integer to string.
|
||||
*
|
||||
* @param p needs at least 21 bytes
|
||||
* @return pointer to nul byte
|
||||
*/
|
||||
noinline char *FormatUint64(char p[static 21], uint64_t x) {
|
||||
char t;
|
||||
size_t i, a, b;
|
||||
i = 0;
|
||||
do {
|
||||
p[i++] = x % 10 + '0';
|
||||
x = x / 10;
|
||||
} while (x > 0);
|
||||
p[i] = '\0';
|
||||
if (i) {
|
||||
for (a = 0, b = i - 1; a < b; ++a, --b) {
|
||||
t = p[a];
|
||||
p[a] = p[b];
|
||||
p[b] = t;
|
||||
}
|
||||
}
|
||||
return p + i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts signed 64-bit integer to string.
|
||||
*
|
||||
* @param p needs at least 21 bytes
|
||||
* @return pointer to nul byte
|
||||
*/
|
||||
char *FormatInt64(char p[static 21], int64_t x) {
|
||||
if (x < 0) *p++ = '-', x = -(uint64_t)x;
|
||||
return FormatUint64(p, x);
|
||||
}
|
53
libc/fmt/formatint64thousands.c
Normal file
53
libc/fmt/formatint64thousands.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/itoa.h"
|
||||
|
||||
/**
|
||||
* Converts unsigned 64-bit integer to string w/ commas.
|
||||
*
|
||||
* @param p needs at least 21 bytes
|
||||
* @return pointer to nul byte
|
||||
*/
|
||||
noinline char *FormatUint64Thousands(char p[static 27], uint64_t x) {
|
||||
size_t i;
|
||||
char m[26];
|
||||
i = 0;
|
||||
do {
|
||||
m[i++] = x % 10 + '0';
|
||||
x = x / 10;
|
||||
} while (x);
|
||||
for (;;) {
|
||||
*p++ = m[--i];
|
||||
if (!i) break;
|
||||
if (!(i % 3)) *p++ = ',';
|
||||
}
|
||||
*p = '\0';
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts 64-bit integer to string w/ commas.
|
||||
*
|
||||
* @param p needs at least 21 bytes
|
||||
* @return pointer to nul byte
|
||||
*/
|
||||
char *FormatInt64Thousands(char p[static 27], int64_t x) {
|
||||
if (x < 0) *p++ = '-', x = -(uint64_t)x;
|
||||
return FormatUint64Thousands(p, x);
|
||||
}
|
|
@ -16,6 +16,10 @@ COSMOPOLITAN_C_START_
|
|||
- uint128toarray_radix10(0x31337, a) l: 93 (27ns) m: 141 (41ns)
|
||||
- int128toarray_radix10(0x31337, a) l: 96 (28ns) m: 173 (51ns) */
|
||||
|
||||
char *FormatInt64(char[hasatleast 21], int64_t);
|
||||
char *FormatUint64(char[hasatleast 21], uint64_t);
|
||||
char *FormatInt64Thousands(char[hasatleast 27], int64_t);
|
||||
char *FormatUint64Thousands(char[hasatleast 27], uint64_t);
|
||||
size_t int64toarray_radix10(int64_t, char[hasatleast 21]);
|
||||
size_t uint64toarray_radix10(uint64_t, char[hasatleast 21]);
|
||||
size_t uint64toarray_radix16(uint64_t, char[hasatleast 17]);
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "libc/fmt/itoa.h"
|
||||
|
||||
size_t uint64toarray_fixed16(uint64_t x, char b[hasatleast 17], uint8_t k) {
|
||||
int i;
|
||||
char *p;
|
||||
assert(k <= 64 && !(k & 3));
|
||||
for (p = b; k > 0;) *p++ = "0123456789abcdef"[(x >> (k -= 4)) & 15];
|
||||
|
|
183
libc/fmt/kerrornameslong.S
Normal file
183
libc/fmt/kerrornameslong.S
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
.macro .e e s
|
||||
.long \e - kErrorNamesLong
|
||||
.long 1f - kErrorNamesLong
|
||||
.rodata.str1.1
|
||||
1: .asciz "\s"
|
||||
.previous
|
||||
.endm
|
||||
|
||||
.section .rodata
|
||||
.align 4
|
||||
kErrorNamesLong:
|
||||
.e EPIPE,"EPIPE[Broken pipe]"
|
||||
.e ENODEV,"ENODEV[No such device]"
|
||||
.e EINVAL,"EINVAL[Invalid argument]"
|
||||
.e EINTR,"EINTR[Interrupted system call]"
|
||||
.e ENOTBLK,"ENOTBLK[Block device required]"
|
||||
.e ENOSYS,"ENOSYS[Function not implemented]"
|
||||
.e EHOSTUNREACH,"EHOSTUNREACH[No route to host]"
|
||||
.e ESRCH,"ESRCH[No such process]"
|
||||
.e EUSERS,"EUSERS[Too many users]"
|
||||
.e EXDEV,"EXDEV[Cross-device link]"
|
||||
.e E2BIG,"E2BIG[Arg list too long]"
|
||||
.e EREMOTE,"EREMOTE[Object is remote]"
|
||||
.e ECHILD,"ECHILD[No child processes]"
|
||||
.e EMSGSIZE,"EMSGSIZE[Message too long]"
|
||||
.e ENOTEMPTY,"ENOTEMPTY[Directory not empty]"
|
||||
.e ENOBUFS,"ENOBUFS[No buffer space available]"
|
||||
.e ELOOP,"ELOOP[Too many symbolic links encountered]"
|
||||
.e EAFNOSUPPORT,"EAFNOSUPPORT[Address family not supported by protocol]"
|
||||
.e EHOSTDOWN,"EHOSTDOWN[Host is down]"
|
||||
.e EPFNOSUPPORT,"EPFNOSUPPORT[Protocol family not supported]"
|
||||
.e ENOPROTOOPT,"ENOPROTOOPT[Protocol not available]"
|
||||
.e EBUSY,"EBUSY[Device or resource busy]"
|
||||
.e EWOULDBLOCK,"EWOULDBLOCK[Operation would block]"
|
||||
.e EBADFD,"EBADFD[File descriptor in bad state]"
|
||||
.e EISCONN,"EISCONN[Transport endpoint is already connected]"
|
||||
.e ESHUTDOWN,"ESHUTDOWN[Cannot send after transport endpoint shutdown]"
|
||||
.e ENONET,"ENONET[Machine is not on the network]"
|
||||
.e EBADE,"EBADE[Invalid exchange]"
|
||||
.e EBADF,"EBADF[Bad file number]"
|
||||
.e EMULTIHOP,"EMULTIHOP[Multihop attempted]"
|
||||
.e EIO,"EIO[I/O error]"
|
||||
.e EUNATCH,"EUNATCH[Protocol driver not attached]"
|
||||
.e EPROTOTYPE,"EPROTOTYPE[Protocol wrong type for socket]"
|
||||
.e ENOSPC,"ENOSPC[No space left on device]"
|
||||
.e ENOEXEC,"ENOEXEC[Exec format error]"
|
||||
.e EALREADY,"EALREADY[Operation already in progress]"
|
||||
.e ENETDOWN,"ENETDOWN[Network is down]"
|
||||
.e ENOTNAM,"ENOTNAM[Not a XENIX named type file]"
|
||||
.e EACCES,"EACCES[Permission denied]"
|
||||
.e ELNRNG,"ELNRNG[Link number out of range]"
|
||||
.e EILSEQ,"EILSEQ[Illegal byte sequence]"
|
||||
.e ENOTDIR,"ENOTDIR[Not a directory]"
|
||||
.e ENOTUNIQ,"ENOTUNIQ[Name not unique on network]"
|
||||
.e EPERM,"EPERM[Operation not permitted]"
|
||||
.e EDOM,"EDOM[Math argument out of domain of func]"
|
||||
.e EXFULL,"EXFULL[Exchange full]"
|
||||
.e ECONNREFUSED,"ECONNREFUSED[Connection refused]"
|
||||
.e EISDIR,"EISDIR[Is a directory]"
|
||||
.e EPROTONOSUPPORT,"EPROTONOSUPPORT[Protocol not supported]"
|
||||
.e EROFS,"EROFS[Read-only file system]"
|
||||
.e EADDRNOTAVAIL,"EADDRNOTAVAIL[Cannot assign requested address]"
|
||||
.e EIDRM,"EIDRM[Identifier removed]"
|
||||
.e ECOMM,"ECOMM[Communication error on send]"
|
||||
.e ESRMNT,"ESRMNT[Srmount error]"
|
||||
.e EREMOTEIO,"EREMOTEIO[Remote I/O error]"
|
||||
.e EL3RST,"EL3RST[Level 3 reset]"
|
||||
.e EBADMSG,"EBADMSG[Not a data message]"
|
||||
.e ENFILE,"ENFILE[File table overflow]"
|
||||
.e ELIBMAX,"ELIBMAX[Attempting to link in too many shared libraries]"
|
||||
.e ESPIPE,"ESPIPE[Illegal seek]"
|
||||
.e ENOLINK,"ENOLINK[Link has been severed]"
|
||||
.e ENETRESET,"ENETRESET[Network dropped connection because of reset]"
|
||||
.e ETIMEDOUT,"ETIMEDOUT[Connection timed out]"
|
||||
.e ENOENT,"ENOENT[No such file or directory]"
|
||||
.e EEXIST,"EEXIST[File exists]"
|
||||
.e EDQUOT,"EDQUOT[Quota exceeded]"
|
||||
.e ENOSTR,"ENOSTR[Device not a stream]"
|
||||
.e EBADSLT,"EBADSLT[Invalid slot]"
|
||||
.e EBADRQC,"EBADRQC[Invalid request code]"
|
||||
.e ELIBACC,"ELIBACC[Can not access a needed shared library]"
|
||||
.e EFAULT,"EFAULT[Bad address]"
|
||||
.e EFBIG,"EFBIG[File too large]"
|
||||
.e EDEADLK,"EDEADLK[Resource deadlock would occur]"
|
||||
.e ENOTCONN,"ENOTCONN[Transport endpoint is not connected]"
|
||||
.e EDESTADDRREQ,"EDESTADDRREQ[Destination address required]"
|
||||
.e ELIBSCN,"ELIBSCN[.lib section in a.out corrupted]"
|
||||
.e ENOLCK,"ENOLCK[No record locks available]"
|
||||
.e EISNAM,"EISNAM[Is a named type file]"
|
||||
.e ECONNABORTED,"ECONNABORTED[Software caused connection abort]"
|
||||
.e ENETUNREACH,"ENETUNREACH[Network is unreachable]"
|
||||
.e ESTALE,"ESTALE[Stale NFS file handle]"
|
||||
.e ENOSR,"ENOSR[Out of streams resources]"
|
||||
.e ENOMEM,"ENOMEM[Out of memory]"
|
||||
.e ENOTSOCK,"ENOTSOCK[Socket operation on non-socket]"
|
||||
.e ESTRPIPE,"ESTRPIPE[Streams pipe error]"
|
||||
.e EMLINK,"EMLINK[Too many links]"
|
||||
.e ERANGE,"ERANGE[Math result not representable]"
|
||||
.e ELIBEXEC,"ELIBEXEC[Cannot exec a shared library directly]"
|
||||
.e EL3HLT,"EL3HLT[Level 3 halted]"
|
||||
.e ECONNRESET,"ECONNRESET[Connection reset by peer]"
|
||||
.e EADDRINUSE,"EADDRINUSE[Address already in use]"
|
||||
.e EOPNOTSUPP,"EOPNOTSUPP[Operation not supported on transport endpoint]"
|
||||
.e EREMCHG,"EREMCHG[Remote address changed]"
|
||||
.e EAGAIN,"EAGAIN[Try again]"
|
||||
.e ENAMETOOLONG,"ENAMETOOLONG[File name too long]"
|
||||
.e ENOTTY,"ENOTTY[Not a typewriter]"
|
||||
.e ERESTART,"ERESTART[Interrupted system call should be restarted]"
|
||||
.e ESOCKTNOSUPPORT,"ESOCKTNOSUPPORT[Socket type not supported]"
|
||||
.e ETIME,"ETIME[Timer expired]"
|
||||
.e ETOOMANYREFS,"ETOOMANYREFS[Too many references: cannot splice]"
|
||||
.e EMFILE,"EMFILE[Too many open files]"
|
||||
.e ETXTBSY,"ETXTBSY[Text file busy]"
|
||||
.e EINPROGRESS,"EINPROGRESS[Operation now in progress]"
|
||||
.e ENXIO,"ENXIO[No such device or address]"
|
||||
.e ENOTSUP,"ENOTSUP[Operation not supported]"
|
||||
.e EPROTO,"EPROTO[Protocol error]"
|
||||
.e ENOMSG,"ENOMSG[No message of desired type]"
|
||||
.e ENODATA,"ENODATA[No data available]"
|
||||
.e EOVERFLOW,"EOVERFLOW[Value too large for defined data type]"
|
||||
.e ENOMEDIUM,"ENOMEDIUM[No medium found]"
|
||||
.e EMEDIUMTYPE,"EMEDIUMTYPE[Wrong medium type]"
|
||||
.e ECANCELED,"ECANCELED[Operation Canceled]"
|
||||
.e EOWNERDEAD,"EOWNERDEAD[Owner died]"
|
||||
.e ENOTRECOVERABLE,"ENOTRECOVERABLE[State not recoverable]"
|
||||
.e EOWNERDEAD,"EOWNERDEAD[Process died with the lock]"
|
||||
.e ENOTRECOVERABLE,"ENOTRECOVERABLE[Lock is not recoverable]"
|
||||
.e EFTYPE,"EFTYPE[Inappropriate file type or format]"
|
||||
.e EAUTH,"EAUTH[Authentication error]"
|
||||
.e EBADRPC,"EBADRPC[RPC struct is bad]"
|
||||
.e ENEEDAUTH,"ENEEDAUTH[Need authenticator]"
|
||||
.e ENOATTR,"ENOATTR[Attribute not found]"
|
||||
.e EPROCUNAVAIL,"EPROCUNAVAIL[Bad procedure for program]"
|
||||
.e EPROGMISMATCH,"EPROGMISMATCH[Program version wrong]"
|
||||
.e EPROGUNAVAIL,"EPROGUNAVAIL[RPC prog. not avail]"
|
||||
.e ERPCMISMATCH,"ERPCMISMATCH[RPC version wrong]"
|
||||
.e EPROCLIM,"EPROCLIM[Too many processes]"
|
||||
.e EBADARCH,"EBADARCH[Bad CPU type in executable]"
|
||||
.e EBADEXEC,"EBADEXEC[Bad executable (or shared library)]"
|
||||
.e EBADMACHO,"EBADMACHO[Malformed Mach-o file]"
|
||||
.e EDEVERR,"EDEVERR[Device error]"
|
||||
.e ENOPOLICY,"ENOPOLICY[Policy not found]"
|
||||
.e EPWROFF,"EPWROFF[Device power is off]"
|
||||
.e ESHLIBVERS,"ESHLIBVERS[Shared library version mismatch]"
|
||||
.e ENOANO,"ENOANO[No anode]"
|
||||
.e EADV,"EADV[Advertise error]"
|
||||
.e EL2HLT,"EL2HLT[Level 2 halted]"
|
||||
.e EDOTDOT,"EDOTDOT[RFS specific error]"
|
||||
.e ENOPKG,"ENOPKG[Package not installed]"
|
||||
.e EBADR,"EBADR[Invalid request descriptor]"
|
||||
.e ENOCSI,"ENOCSI[No CSI structure available]"
|
||||
.e ENOKEY,"ENOKEY[Required key not available]"
|
||||
.e EUCLEAN,"EUCLEAN[Structure needs cleaning]"
|
||||
.e ECHRNG,"ECHRNG[Channel number out of range]"
|
||||
.e EL2NSYNC,"EL2NSYNC[Level 2 not synchronized]"
|
||||
.e EKEYEXPIRED,"EKEYEXPIRED[Key has expired]"
|
||||
.e ENAVAIL,"ENAVAIL[No XENIX semaphores available]"
|
||||
.e EKEYREVOKED,"EKEYREVOKED[Key has been revoked]"
|
||||
.e ELIBBAD,"ELIBBAD[Accessing a corrupted shared library]"
|
||||
.e EKEYREJECTED,"EKEYREJECTED[Key was rejected by service]"
|
||||
.e ERFKILL,"ERFKILL[Operation not possible due to RF-kill]"
|
||||
.long 0
|
||||
.endobj kErrorNamesLong,globl,hidden
|
|
@ -27,10 +27,13 @@
|
|||
#include "libc/nt/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
extern const struct Error {
|
||||
struct Error {
|
||||
int x;
|
||||
int s;
|
||||
} kErrorNames[];
|
||||
};
|
||||
|
||||
extern const struct Error kErrorNames[];
|
||||
extern const struct Error kErrorNamesLong[];
|
||||
|
||||
static const char *GetErrorName(long x) {
|
||||
int i;
|
||||
|
@ -44,6 +47,20 @@ static const char *GetErrorName(long x) {
|
|||
return "EUNKNOWN";
|
||||
}
|
||||
|
||||
static const char *GetErrorNameLong(long x) {
|
||||
int i;
|
||||
if (x) {
|
||||
for (i = 0; kErrorNamesLong[i].x; ++i) {
|
||||
if (x ==
|
||||
*(const long *)((uintptr_t)kErrorNamesLong + kErrorNamesLong[i].x)) {
|
||||
return (const char *)((uintptr_t)kErrorNamesLong +
|
||||
kErrorNamesLong[i].s);
|
||||
}
|
||||
}
|
||||
}
|
||||
return "EUNKNOWN[No error information]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts errno value to string.
|
||||
* @return 0 on success, or error code
|
||||
|
@ -52,7 +69,11 @@ int strerror_r(int err, char *buf, size_t size) {
|
|||
char *p;
|
||||
const char *s;
|
||||
err &= 0xFFFF;
|
||||
s = GetErrorName(err);
|
||||
if (IsTiny()) {
|
||||
s = GetErrorName(err);
|
||||
} else {
|
||||
s = GetErrorNameLong(err);
|
||||
}
|
||||
p = buf;
|
||||
if (strlen(s) + 1 + 5 + 1 + 1 <= size) {
|
||||
p = stpcpy(p, s);
|
||||
|
|
42
libc/fmt/stripext.c
Normal file
42
libc/fmt/stripext.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Removes file extension.
|
||||
*
|
||||
* @param s is mutated
|
||||
* @return s
|
||||
*/
|
||||
char *stripext(char *s) {
|
||||
size_t i;
|
||||
for (i = strlen(s); i--;) {
|
||||
switch (s[i]) {
|
||||
case '.':
|
||||
s[i] = 0;
|
||||
return s;
|
||||
case '/':
|
||||
return s;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
|
@ -37,21 +37,24 @@
|
|||
* @see strtoumax()
|
||||
*/
|
||||
intmax_t strtoimax(const char *s, char **endptr, int base) {
|
||||
char t = 0;
|
||||
int d, c = *s;
|
||||
intmax_t x = 0;
|
||||
CONSUME_SPACES(s, c);
|
||||
GET_SIGN(s, c, d);
|
||||
GET_RADIX(s, c, base);
|
||||
if ((c = kBase36[c & 255]) && --c < base) {
|
||||
do {
|
||||
if (__builtin_mul_overflow(x, base, &x) ||
|
||||
__builtin_add_overflow(x, c * d, &x)) {
|
||||
x = d > 0 ? INTMAX_MAX : INTMAX_MIN;
|
||||
errno = ERANGE;
|
||||
break;
|
||||
}
|
||||
} while ((c = kBase36[*++s & 255]) && --c < base);
|
||||
if (!((t |= 1) & 2)) {
|
||||
do {
|
||||
if (__builtin_mul_overflow(x, base, &x) ||
|
||||
__builtin_add_overflow(x, c * d, &x)) {
|
||||
x = d > 0 ? INTMAX_MAX : INTMAX_MIN;
|
||||
errno = ERANGE;
|
||||
t |= 2;
|
||||
}
|
||||
} while ((c = kBase36[*++s & 255]) && --c < base);
|
||||
}
|
||||
}
|
||||
if (endptr) *endptr = s;
|
||||
if (t && endptr) *endptr = s;
|
||||
return x;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,16 @@
|
|||
/**
|
||||
* Decodes signed integer from ASCII string.
|
||||
*
|
||||
* atoi 10⁸ 22𝑐 7𝑛𝑠
|
||||
* strtol 10⁸ 37𝑐 12𝑛𝑠
|
||||
* strtoul 10⁸ 35𝑐 11𝑛𝑠
|
||||
* wcstol 10⁸ 30𝑐 10𝑛𝑠
|
||||
* wcstoul 10⁸ 30𝑐 10𝑛𝑠
|
||||
* strtoimax 10⁸ 80𝑐 26𝑛𝑠
|
||||
* strtoumax 10⁸ 78𝑐 25𝑛𝑠
|
||||
* wcstoimax 10⁸ 77𝑐 25𝑛𝑠
|
||||
* wcstoumax 10⁸ 76𝑐 25𝑛𝑠
|
||||
*
|
||||
* @param s is a non-null nul-terminated string
|
||||
* @param endptr if non-null will always receive a pointer to the char
|
||||
* following the last one this function processed, which is usually
|
||||
|
@ -36,21 +46,24 @@
|
|||
* @return the decoded signed saturated number
|
||||
*/
|
||||
long strtol(const char *s, char **endptr, int base) {
|
||||
char t = 0;
|
||||
long x = 0;
|
||||
int d, c = *s;
|
||||
CONSUME_SPACES(s, c);
|
||||
GET_SIGN(s, c, d);
|
||||
GET_RADIX(s, c, base);
|
||||
if ((c = kBase36[c & 255]) && --c < base) {
|
||||
do {
|
||||
if (__builtin_mul_overflow(x, base, &x) ||
|
||||
__builtin_add_overflow(x, c * d, &x)) {
|
||||
x = d > 0 ? LONG_MAX : LONG_MIN;
|
||||
errno = ERANGE;
|
||||
break;
|
||||
}
|
||||
} while ((c = kBase36[*++s & 255]) && --c < base);
|
||||
if (!((t |= 1) & 2)) {
|
||||
do {
|
||||
if (__builtin_mul_overflow(x, base, &x) ||
|
||||
__builtin_add_overflow(x, c * d, &x)) {
|
||||
x = d > 0 ? LONG_MAX : LONG_MIN;
|
||||
errno = ERANGE;
|
||||
t |= 2;
|
||||
}
|
||||
} while ((c = kBase36[*++s & 255]) && --c < base);
|
||||
}
|
||||
}
|
||||
if (endptr) *endptr = s;
|
||||
if (t && endptr) *endptr = s;
|
||||
return x;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define COSMOPOLITAN_LIBC_FMT_STRTOL_H_
|
||||
|
||||
#define CONSUME_SPACES(s, c) \
|
||||
if (endptr) *endptr = s; \
|
||||
while (c == ' ' || c == '\t') c = *++s
|
||||
|
||||
#define GET_SIGN(s, c, d) \
|
||||
|
@ -11,6 +12,7 @@
|
|||
#define GET_RADIX(s, c, r) \
|
||||
if (!(2 <= r && r <= 36)) { \
|
||||
if (c == '0') { \
|
||||
t |= 1; \
|
||||
c = *++s; \
|
||||
if (c == 'x' || c == 'X') { \
|
||||
c = *++s; \
|
||||
|
@ -25,6 +27,7 @@
|
|||
r = 10; \
|
||||
} \
|
||||
} else if (c == '0') { \
|
||||
t |= 1; \
|
||||
c = *++s; \
|
||||
if ((r == 2 && (c == 'b' || c == 'B')) || \
|
||||
(r == 16 && (c == 'x' || c == 'X'))) { \
|
||||
|
|
|
@ -35,17 +35,19 @@
|
|||
* @return decoded integer mod 2⁶⁴ negated if leading `-`
|
||||
*/
|
||||
unsigned long strtoul(const char *s, char **endptr, int base) {
|
||||
char t = 0;
|
||||
int d, c = *s;
|
||||
unsigned long x = 0;
|
||||
CONSUME_SPACES(s, c);
|
||||
GET_SIGN(s, c, d);
|
||||
GET_RADIX(s, c, base);
|
||||
if ((c = kBase36[c & 255]) && --c < base) {
|
||||
t |= 1;
|
||||
do {
|
||||
x *= base;
|
||||
x += c;
|
||||
} while ((c = kBase36[*++s & 255]) && --c < base);
|
||||
}
|
||||
if (endptr) *endptr = s;
|
||||
if (t && endptr) *endptr = s;
|
||||
return d > 0 ? x : -x;
|
||||
}
|
||||
|
|
|
@ -35,17 +35,19 @@
|
|||
* @see strtoimax()
|
||||
*/
|
||||
uintmax_t strtoumax(const char *s, char **endptr, int base) {
|
||||
char t = 0;
|
||||
int d, c = *s;
|
||||
uintmax_t x = 0;
|
||||
CONSUME_SPACES(s, c);
|
||||
GET_SIGN(s, c, d);
|
||||
GET_RADIX(s, c, base);
|
||||
if ((c = kBase36[c & 255]) && --c < base) {
|
||||
t |= 1;
|
||||
do {
|
||||
x *= base;
|
||||
x += c;
|
||||
} while ((c = kBase36[*++s & 255]) && --c < base);
|
||||
}
|
||||
if (endptr) *endptr = s;
|
||||
if (t && endptr) *endptr = s;
|
||||
return d > 0 ? x : -x;
|
||||
}
|
||||
|
|
|
@ -37,25 +37,24 @@
|
|||
* @see strtoumax()
|
||||
*/
|
||||
intmax_t wcstoimax(const wchar_t *s, wchar_t **endptr, int base) {
|
||||
int c, d;
|
||||
intmax_t x;
|
||||
c = *s;
|
||||
char t = 0;
|
||||
intmax_t x = 0;
|
||||
int d, c = *s;
|
||||
CONSUME_SPACES(s, c);
|
||||
GET_SIGN(s, c, d);
|
||||
GET_RADIX(s, c, base);
|
||||
x = 0;
|
||||
if ((c = kBase36[c & 255]) && --c < base) {
|
||||
do {
|
||||
if (__builtin_mul_overflow(x, base, &x) ||
|
||||
__builtin_add_overflow(x, c * d, &x)) {
|
||||
x = d > 0 ? INTMAX_MAX : INTMAX_MIN;
|
||||
errno = ERANGE;
|
||||
break;
|
||||
}
|
||||
} while ((c = kBase36[*++s & 255]) && --c < base);
|
||||
}
|
||||
if (endptr) {
|
||||
*endptr = s;
|
||||
if (!((t |= 1) & 2)) {
|
||||
do {
|
||||
if (__builtin_mul_overflow(x, base, &x) ||
|
||||
__builtin_add_overflow(x, c * d, &x)) {
|
||||
x = d > 0 ? INTMAX_MAX : INTMAX_MIN;
|
||||
errno = ERANGE;
|
||||
t |= 2;
|
||||
}
|
||||
} while ((c = kBase36[*++s & 255]) && --c < base);
|
||||
}
|
||||
}
|
||||
if (t && endptr) *endptr = s;
|
||||
return x;
|
||||
}
|
||||
|
|
|
@ -36,21 +36,24 @@
|
|||
* @return the decoded signed saturated number
|
||||
*/
|
||||
long wcstol(const wchar_t *s, wchar_t **endptr, int base) {
|
||||
char t = 0;
|
||||
long x = 0;
|
||||
int d, c = *s;
|
||||
CONSUME_SPACES(s, c);
|
||||
GET_SIGN(s, c, d);
|
||||
GET_RADIX(s, c, base);
|
||||
if ((c = kBase36[c & 255]) && --c < base) {
|
||||
do {
|
||||
if (__builtin_mul_overflow(x, base, &x) ||
|
||||
__builtin_add_overflow(x, c * d, &x)) {
|
||||
x = d > 0 ? LONG_MAX : LONG_MIN;
|
||||
errno = ERANGE;
|
||||
break;
|
||||
}
|
||||
} while ((c = kBase36[*++s & 255]) && --c < base);
|
||||
if (!((t |= 1) & 2)) {
|
||||
do {
|
||||
if (__builtin_mul_overflow(x, base, &x) ||
|
||||
__builtin_add_overflow(x, c * d, &x)) {
|
||||
x = d > 0 ? LONG_MAX : LONG_MIN;
|
||||
errno = ERANGE;
|
||||
t |= 2;
|
||||
}
|
||||
} while ((c = kBase36[*++s & 255]) && --c < base);
|
||||
}
|
||||
}
|
||||
if (endptr) *endptr = s;
|
||||
if (t && endptr) *endptr = s;
|
||||
return x;
|
||||
}
|
||||
|
|
|
@ -35,17 +35,19 @@
|
|||
* @return decoded integer mod 2⁶⁴ negated if leading `-`
|
||||
*/
|
||||
unsigned long wcstoul(const wchar_t *s, wchar_t **endptr, int base) {
|
||||
char t = 0;
|
||||
int d, c = *s;
|
||||
unsigned long x = 0;
|
||||
CONSUME_SPACES(s, c);
|
||||
GET_SIGN(s, c, d);
|
||||
GET_RADIX(s, c, base);
|
||||
if ((c = kBase36[c & 255]) && --c < base) {
|
||||
t |= 1;
|
||||
do {
|
||||
x *= base;
|
||||
x += c;
|
||||
} while ((c = kBase36[*++s & 255]) && --c < base);
|
||||
}
|
||||
if (endptr) *endptr = s;
|
||||
if (t && endptr) *endptr = s;
|
||||
return d > 0 ? x : -x;
|
||||
}
|
||||
|
|
|
@ -35,21 +35,19 @@
|
|||
* @see strtoimax()
|
||||
*/
|
||||
uintmax_t wcstoumax(const wchar_t *s, wchar_t **endptr, int base) {
|
||||
int c, d;
|
||||
uintmax_t x;
|
||||
c = *s;
|
||||
char t = 0;
|
||||
int d, c = *s;
|
||||
uintmax_t x = 0;
|
||||
CONSUME_SPACES(s, c);
|
||||
GET_SIGN(s, c, d);
|
||||
GET_RADIX(s, c, base);
|
||||
x = 0;
|
||||
if ((c = kBase36[c & 255]) && --c < base) {
|
||||
t |= 1;
|
||||
do {
|
||||
x *= base;
|
||||
x += c;
|
||||
} while ((c = kBase36[*++s & 255]) && --c < base);
|
||||
}
|
||||
if (endptr) {
|
||||
*endptr = s;
|
||||
}
|
||||
if (t && endptr) *endptr = s;
|
||||
return d > 0 ? x : -x;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue