#include "error.h"
#include <errno.h>          // for E2BIG, EACCES, EADDRINUSE, EADDRNOTAVAIL
#include <stddef.h>         // for ptrdiff_t, size_t
#include "sparse.h"  // for __force
#include "simplest-defs.h"  // for NELEM

/* One is not supposed to use sys_errlist[] any longer.

   strerror() grabs locks and loads a locale to translate the error
   message.  On top of that, it's not thread safe.

   To work around the thread-safe business, one is supposed to
   allocate a buffer and call strerror_r, for the privilege of having
   locale-dependent error messages precisely when things are going
   wrong and the last thing I want to do is load a file from disk.

   Oracle policy prevents me from drawing the appropriate conclusion
   in writing.  Let's just say that returning a static string seems
   simpler than any of the above.
*/
/* as long as I am redoing strerror(), we may as well print
   ECONNABORTED instead of some translation into English, which then I
   have to mentally map back to ECONNABORTED */
#define DO(x) [x] = #x
static const char *const errlist[] = {
    DO(EPERM),
    DO(ENOENT),
    DO(ESRCH),
    DO(EINTR),
    DO(EIO),
    DO(ENXIO),
    DO(E2BIG),
    DO(ENOEXEC),
    DO(EBADF),
    DO(ECHILD),
    DO(EDEADLK),
    DO(ENOMEM),
    DO(EACCES),
    DO(EFAULT),
    DO(ENOTBLK),
    DO(EBUSY),
    DO(EEXIST),
    DO(EXDEV),
    DO(ENODEV),
    DO(ENOTDIR),
    DO(EISDIR),
    DO(EINVAL),
    DO(EMFILE),
    DO(ENFILE),
    DO(ENOTTY),
    DO(ETXTBSY),
    DO(EFBIG),
    DO(ENOSPC),
    DO(ESPIPE),
    DO(EROFS),
    DO(EMLINK),
    DO(EPIPE),
    DO(EDOM),
    DO(ERANGE),
    DO(EAGAIN),
    DO(EINPROGRESS),
    DO(EALREADY),
    DO(ENOTSOCK),
    DO(EMSGSIZE),
    DO(EPROTOTYPE),
    DO(ENOPROTOOPT),
    DO(EPROTONOSUPPORT),
    DO(ESOCKTNOSUPPORT),
    DO(EOPNOTSUPP),
    DO(EPFNOSUPPORT),
    DO(EAFNOSUPPORT),
    DO(EADDRINUSE),
    DO(EADDRNOTAVAIL),
    DO(ENETDOWN),
    DO(ENETUNREACH),
    DO(ENETRESET),
    DO(ECONNABORTED),
    DO(ECONNRESET),
    DO(ENOBUFS),
    DO(EISCONN),
    DO(ENOTCONN),
    DO(EDESTADDRREQ),
    DO(ESHUTDOWN),
    DO(ETOOMANYREFS),
    DO(ETIMEDOUT),
    DO(ECONNREFUSED),
    DO(ELOOP),
    DO(ENAMETOOLONG),
    DO(EHOSTDOWN),
    DO(EHOSTUNREACH),
    DO(ENOTEMPTY),
    DO(EUSERS),
    DO(EDQUOT),
    DO(ESTALE),
    DO(EREMOTE),
    DO(ENOLCK),
    DO(EILSEQ),
    DO(EBADMSG),
    DO(EIDRM),
    DO(EMULTIHOP),
    DO(ENODATA),
    DO(ENOLINK),
    DO(ENOMSG),
    DO(ENOSR),
    DO(ENOSTR),
    DO(EOVERFLOW),
    DO(EPROTO),
    DO(ETIME),
    DO(ECANCELED),
    DO(ECHRNG),
    DO(EL2NSYNC),
    DO(EL3HLT),
    DO(EL3RST),
    DO(ELNRNG),
    DO(EUNATCH),
    DO(ENOCSI),
    DO(EL2HLT),
    DO(EBADE),
    DO(EBADR),
    DO(EXFULL),
    DO(ENOANO),
    DO(EBADRQC),
    DO(EBADSLT),
    DO(EBFONT),
    DO(ENONET),
    DO(ENOPKG),
    DO(EADV),
    DO(ESRMNT),
    DO(ECOMM),
    DO(EDOTDOT),
    DO(ENOTUNIQ),
    DO(EBADFD),
    DO(EREMCHG),
    DO(ELIBACC),
    DO(ELIBBAD),
    DO(ELIBSCN),
    DO(ELIBMAX),
    DO(ELIBEXEC),
    DO(ESTRPIPE),
    DO(EUCLEAN),
    DO(ENOTNAM),
    DO(ENAVAIL),
    DO(EISNAM),
    DO(EREMOTEIO),
    DO(ENOMEDIUM),
    DO(EMEDIUMTYPE),
    DO(ENOKEY),
    DO(EKEYEXPIRED),
    DO(EKEYREVOKED),
    DO(EKEYREJECTED),
    DO(EOWNERDEAD),
    DO(ENOTRECOVERABLE),
    DO(ERFKILL),
    DO(EHWPOISON),
};

const char *xstrerror(int err)
{
    ptrdiff_t err1 = err;
    if (1
        && err1 >= 0
        && (__force size_t)err1 < NELEM(errlist)
        && errlist[err1]) {
        return errlist[err1];
    } else {
        return "Unknown error";
    }
}
