mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-08 04:08:32 +00:00
Make improvements
- Fix build flakes - Polyfill SIGWINCH on Windows - Fix an execve issue on Windows - Make strerror show more information - Improve cmd.exe setup/teardown on Windows - Support bracketed paste mode in Blinkenlights - Show keyboard shortcuts in Blinkenlights status bar - Fixed copy_file_range() and copyfile() w/ zip filesystem - Size optimize GetDosArgv() to keep life.com 12kb in size - Improve Blinkenlights ability to load weird ELF executables - Fix program_executable_name and add GetInterpreterExecutableName - Make Python in tiny mode fail better if docstrings are requested - Update Python test exclusions in tiny* modes such as tinylinux - Add bulletproof unbreakable kprintf() troubleshooting function - Remove "oldskool" keyword from ape.S for virus scanners - Fix issue that caused backtraces to not print sometimes - Improve Blinkenlights serial uart character i/o - Make clock_gettime() not clobber errno on xnu - Improve sha256 cpuid check for old computers - Integrate some bestline linenoise fixes - Show runit process names better in htop - Remove SIGPIPE from ShowCrashReports() - Make realpath() not clobber errno - Avoid attaching GDB on non-Linux - Improve img.com example
This commit is contained in:
parent
2a938b3eaa
commit
b45d50b690
194 changed files with 4881 additions and 2966 deletions
26
libc/fmt/divmod10.internal.h
Normal file
26
libc/fmt/divmod10.internal.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_FMT_DIVMOD10_H_
|
||||
#define COSMOPOLITAN_LIBC_FMT_DIVMOD10_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
forceinline uint64_t DivMod10(uint64_t x, unsigned *r) {
|
||||
#if defined(__STRICT_ANSI__) || !defined(__GNUC__) || \
|
||||
(defined(__OPTIMIZE__) && !defined(__OPTIMIZE_SIZE__))
|
||||
*r = x % 10;
|
||||
return x / 10;
|
||||
#else
|
||||
uint128_t dw;
|
||||
unsigned long long hi, rm;
|
||||
dw = x;
|
||||
dw *= 0xcccccccccccccccdull;
|
||||
hi = dw >> 64;
|
||||
hi >>= 3;
|
||||
rm = hi;
|
||||
rm += rm << 2;
|
||||
rm += rm;
|
||||
*r = x - rm;
|
||||
return hi;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_FMT_DIVMOD10_H_ */
|
|
@ -27,6 +27,8 @@ int vsscanf(const char *, const char *, va_list);
|
|||
int vcscanf(int (*)(void *), int (*)(int, void *), void *, const char *,
|
||||
va_list);
|
||||
int strerror_r(int, char *, size_t) nothrow nocallback;
|
||||
const char *strerror_short(int) nosideeffect;
|
||||
const char *strerror_long(int) nosideeffect;
|
||||
int __fmt(void *, void *, const char *, va_list) hidden;
|
||||
char *itoa(int, char *, int) compatfn;
|
||||
char *fcvt(double, int, int *, int *);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
.section .rodata
|
||||
.align 4
|
||||
kErrorNames:
|
||||
.e EINVAL
|
||||
.e ENOSYS
|
||||
.e EPERM
|
||||
.e ENOENT
|
||||
|
@ -51,7 +52,6 @@ kErrorNames:
|
|||
.e ENODEV
|
||||
.e ENOTDIR
|
||||
.e EISDIR
|
||||
.e EINVAL
|
||||
.e ENFILE
|
||||
.e EMFILE
|
||||
.e ENOTTY
|
||||
|
|
|
@ -29,155 +29,90 @@
|
|||
.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]"
|
||||
.e EINVAL,"Invalid argument"
|
||||
.e ENOSYS,"Function not implemented"
|
||||
.e EPERM,"Operation not permitted"
|
||||
.e ENOENT,"No such file or directory"
|
||||
.e ESRCH,"No such process"
|
||||
.e EINTR,"Interrupted system call"
|
||||
.e EIO,"I/O error"
|
||||
.e ENXIO,"No such device or address"
|
||||
.e E2BIG,"Arg list too long"
|
||||
.e ENOEXEC,"Exec format error"
|
||||
.e EBADF,"Bad file number"
|
||||
.e ECHILD,"No child processes"
|
||||
.e EAGAIN,"Try again"
|
||||
.e ENOMEM,"Out of memory"
|
||||
.e EACCES,"Permission denied"
|
||||
.e EFAULT,"Bad address"
|
||||
.e ENOTBLK,"Block device required"
|
||||
.e EBUSY,"Device or resource busy"
|
||||
.e EEXIST,"File exists"
|
||||
.e EXDEV,"Cross-device link"
|
||||
.e ENODEV,"No such device"
|
||||
.e ENOTDIR,"Not a directory"
|
||||
.e EISDIR,"Is a directory"
|
||||
.e ENFILE,"File table overflow"
|
||||
.e EMFILE,"Too many open files"
|
||||
.e ENOTTY,"Not a typewriter"
|
||||
.e ETXTBSY,"Text file busy"
|
||||
.e EFBIG,"File too large"
|
||||
.e ENOSPC,"No space left on device"
|
||||
.e EDQUOT,"Quota exceeded"
|
||||
.e ESPIPE,"Illegal seek"
|
||||
.e EROFS,"Read-only file system"
|
||||
.e EMLINK,"Too many links"
|
||||
.e EPIPE,"Broken pipe"
|
||||
.e EDOM,"Math argument out of domain of func"
|
||||
.e ERANGE,"Math result not representable"
|
||||
.e EDEADLK,"Resource deadlock would occur"
|
||||
.e ENAMETOOLONG,"File name too long"
|
||||
.e ENOLCK,"No record locks available"
|
||||
.e ENOTEMPTY,"Directory not empty"
|
||||
.e ELOOP,"Too many symbolic links encountered"
|
||||
.e ENOMSG,"No message of desired type"
|
||||
.e EIDRM,"Identifier removed"
|
||||
.e ETIME,"Timer expired"
|
||||
.e EPROTO,"Protocol error"
|
||||
.e EOVERFLOW,"Value too large for defined data type"
|
||||
.e EILSEQ,"Illegal byte sequence"
|
||||
.e EUSERS,"Too many users"
|
||||
.e ENOTSOCK,"Socket operation on non-socket"
|
||||
.e EDESTADDRREQ,"Destination address required"
|
||||
.e EMSGSIZE,"Message too long"
|
||||
.e EPROTOTYPE,"Protocol wrong type for socket"
|
||||
.e ENOPROTOOPT,"Protocol not available"
|
||||
.e EPROTONOSUPPORT,"Protocol not supported"
|
||||
.e ESOCKTNOSUPPORT,"Socket type not supported"
|
||||
.e ENOTSUP,"Operation not supported"
|
||||
.e EOPNOTSUPP,"Operation not supported on transport endpoint"
|
||||
.e EPFNOSUPPORT,"Protocol family not supported"
|
||||
.e EAFNOSUPPORT,"Address family not supported by protocol"
|
||||
.e EADDRINUSE,"Address already in use"
|
||||
.e EADDRNOTAVAIL,"Cannot assign requested address"
|
||||
.e ENETDOWN,"Network is down"
|
||||
.e ENETUNREACH,"Network is unreachable"
|
||||
.e ENETRESET,"Network dropped connection because of reset"
|
||||
.e ECONNABORTED,"Software caused connection abort"
|
||||
.e ECONNRESET,"Connection reset by peer"
|
||||
.e ENOBUFS,"No buffer space available"
|
||||
.e EISCONN,"Transport endpoint is already connected"
|
||||
.e ENOTCONN,"Transport endpoint is not connected"
|
||||
.e ESHUTDOWN,"Cannot send after transport endpoint shutdown"
|
||||
.e ETOOMANYREFS,"Too many references: cannot splice"
|
||||
.e ETIMEDOUT,"Connection timed out"
|
||||
.e ECONNREFUSED,"Connection refused"
|
||||
.e EHOSTDOWN,"Host is down"
|
||||
.e EHOSTUNREACH,"No route to host"
|
||||
.e EALREADY,"Operation already in progress"
|
||||
.e EINPROGRESS,"Operation now in progress"
|
||||
.e ESTALE,"Stale NFS file handle"
|
||||
.e EREMOTE,"Object is remote"
|
||||
.e EBADMSG,"Not a data message"
|
||||
.e ECANCELED,"Operation Canceled"
|
||||
.e EOWNERDEAD,"Owner died"
|
||||
.e ENOTRECOVERABLE,"State not recoverable"
|
||||
.e ENONET,"Machine is not on the network"
|
||||
.e ERESTART,"Interrupted system call should be restarted"
|
||||
.long 0
|
||||
.endobj kErrorNamesLong,globl,hidden
|
||||
|
|
40
libc/fmt/strerror_long.greg.c
Normal file
40
libc/fmt/strerror_long.greg.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*-*- 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"
|
||||
|
||||
extern const struct { int x, s; } kErrorNamesLong[];
|
||||
|
||||
/**
|
||||
* Converts errno value to descriptive sentence.
|
||||
* @return non-null rodata string or null if not found
|
||||
*/
|
||||
privileged const char *strerror_long(int x) {
|
||||
/* kprintf() weakly depends on this function */
|
||||
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 0;
|
||||
}
|
|
@ -16,11 +16,13 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#define ShouldUseMsabiAttribute() 1
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
|
@ -32,93 +34,48 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/str/tpenc.h"
|
||||
|
||||
#if !IsTiny()
|
||||
#if !IsTiny() && SupportsWindows()
|
||||
/*
|
||||
* If we're paying the code size costs for all the system five magnums
|
||||
* that this module pulls in then we might as well pull in support for
|
||||
* the improved accuracy windows errno conversions used by __winerr()
|
||||
*/
|
||||
STATIC_YOINK("__dos2errno");
|
||||
#endif
|
||||
|
||||
struct Error {
|
||||
int x;
|
||||
int s;
|
||||
};
|
||||
|
||||
extern const struct Error kErrorNames[];
|
||||
extern const struct Error kErrorNamesLong[];
|
||||
|
||||
noasan static inline const char *GetErrorName(long x) {
|
||||
int i;
|
||||
if (x) {
|
||||
for (i = 0; kErrorNames[i].x; ++i) {
|
||||
if (x == *(const long *)((uintptr_t)kErrorNames + kErrorNames[i].x)) {
|
||||
return (const char *)((uintptr_t)kErrorNames + kErrorNames[i].s);
|
||||
}
|
||||
}
|
||||
}
|
||||
return "EUNKNOWN";
|
||||
}
|
||||
|
||||
noasan static inline 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.
|
||||
*
|
||||
* @param err is error number or zero if unknown
|
||||
* @return 0 on success, or error code
|
||||
*/
|
||||
noasan int strerror_r(int err, char *buf, size_t size) {
|
||||
uint64_t w;
|
||||
int c, i, n;
|
||||
char *p, *e;
|
||||
const char *s;
|
||||
char16_t *ws = 0;
|
||||
p = buf;
|
||||
e = p + size;
|
||||
err &= 0xFFFF;
|
||||
s = IsTiny() ? GetErrorName(err) : GetErrorNameLong(err);
|
||||
while ((c = *s++)) {
|
||||
if (p + 1 + 1 <= e) *p++ = c;
|
||||
}
|
||||
if (!IsTiny()) {
|
||||
if (p + 1 + 5 + 1 + 1 <= e) {
|
||||
*p++ = '[';
|
||||
p = __intcpy(p, err);
|
||||
*p++ = ']';
|
||||
}
|
||||
if (IsWindows()) {
|
||||
err = GetLastError() & 0xffff;
|
||||
if ((n = FormatMessage(
|
||||
kNtFormatMessageAllocateBuffer | kNtFormatMessageFromSystem |
|
||||
kNtFormatMessageIgnoreInserts,
|
||||
0, err, MAKELANGID(kNtLangNeutral, kNtSublangDefault),
|
||||
(char16_t *)&ws, 0, 0))) {
|
||||
while (n && ws[n - 1] <= L' ' || ws[n - 1] == L'.') --n;
|
||||
if (p + 1 + 1 <= e) *p++ = '[';
|
||||
for (i = 0; i < n; ++i) {
|
||||
w = tpenc(ws[i] & 0xffff);
|
||||
if (p + (bsrll(w) >> 3) + 1 + 1 <= e) {
|
||||
do *p++ = w;
|
||||
while ((w >>= 8));
|
||||
}
|
||||
}
|
||||
if (p + 1 + 1 <= e) *p++ = ']';
|
||||
LocalFree(ws);
|
||||
}
|
||||
if (p + 1 + 5 + 1 + 1 <= e) {
|
||||
*p++ = '[';
|
||||
p = __intcpy(p, err);
|
||||
*p++ = ']';
|
||||
}
|
||||
privileged int strerror_r(int err, char *buf, size_t size) {
|
||||
/* kprintf() weakly depends on this function */
|
||||
int c, n, winerr;
|
||||
char16_t winmsg[256];
|
||||
const char *sym, *msg;
|
||||
sym = firstnonnull(strerror_short(err), "EUNKNOWN");
|
||||
msg = firstnonnull(strerror_long(err), "No error information");
|
||||
if (IsTiny()) {
|
||||
if (!sym) sym = "EUNKNOWN";
|
||||
for (; (c = *sym++); --size)
|
||||
if (size > 1) *buf++ = c;
|
||||
if (size) *buf = 0;
|
||||
} else if (!IsWindows()) {
|
||||
ksnprintf(buf, size, "%s[%d][%s]", sym, err, msg);
|
||||
} else {
|
||||
winerr = __imp_GetLastError();
|
||||
if ((n = __imp_FormatMessageW(
|
||||
kNtFormatMessageFromSystem | kNtFormatMessageIgnoreInserts, 0,
|
||||
winerr, MAKELANGID(kNtLangNeutral, kNtSublangDefault), winmsg,
|
||||
ARRAYLEN(winmsg), 0))) {
|
||||
while ((n && winmsg[n - 1] <= ' ') || winmsg[n - 1] == '.') --n;
|
||||
ksnprintf(buf, size, "%s[%d][%s][%.*hs][%d]", sym, err, msg, n, winmsg,
|
||||
winerr);
|
||||
} else {
|
||||
ksnprintf(buf, size, "%s[%d][%s][%d]", sym, err, msg, winerr);
|
||||
}
|
||||
__imp_SetLastError(winerr);
|
||||
}
|
||||
if (p + 1 <= e) *p = 0;
|
||||
return 0;
|
||||
}
|
38
libc/fmt/strerror_short.greg.c
Normal file
38
libc/fmt/strerror_short.greg.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- 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"
|
||||
|
||||
extern const struct { int x, s; } kErrorNames[];
|
||||
|
||||
/**
|
||||
* Converts errno value to symbolic name.
|
||||
* @return non-null rodata string or null if not found
|
||||
*/
|
||||
privileged const char *strerror_short(int x) {
|
||||
/* kprintf() weakly depends on this function */
|
||||
int i;
|
||||
if (x) {
|
||||
for (i = 0; kErrorNames[i].x; ++i) {
|
||||
if (x == *(const *)((uintptr_t)kErrorNames + kErrorNames[i].x)) {
|
||||
return (const char *)((uintptr_t)kErrorNames + kErrorNames[i].s);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue