186d7f5d3SJohn Marino /* xstrerror.c -- jacket routine for more robust strerror() usage.
286d7f5d3SJohn Marino Fri Jun 16 18:30:00 1995 Pat Rankin <rankin@eql.caltech.edu>
386d7f5d3SJohn Marino This code is in the public domain. */
486d7f5d3SJohn Marino
586d7f5d3SJohn Marino /*
686d7f5d3SJohn Marino
786d7f5d3SJohn Marino @deftypefn Replacement char* xstrerror (int @var{errnum})
886d7f5d3SJohn Marino
986d7f5d3SJohn Marino Behaves exactly like the standard @code{strerror} function, but
1086d7f5d3SJohn Marino will never return a @code{NULL} pointer.
1186d7f5d3SJohn Marino
1286d7f5d3SJohn Marino @end deftypefn
1386d7f5d3SJohn Marino
1486d7f5d3SJohn Marino */
1586d7f5d3SJohn Marino
1686d7f5d3SJohn Marino #include <stdio.h>
1786d7f5d3SJohn Marino
1886d7f5d3SJohn Marino #include "config.h"
1986d7f5d3SJohn Marino #include "libiberty.h"
2086d7f5d3SJohn Marino
2186d7f5d3SJohn Marino #ifdef VMS
2286d7f5d3SJohn Marino # include <errno.h>
2386d7f5d3SJohn Marino # if !defined (__STRICT_ANSI__) && !defined (__HIDE_FORBIDDEN_NAMES)
2486d7f5d3SJohn Marino # ifdef __cplusplus
2586d7f5d3SJohn Marino extern "C" {
2686d7f5d3SJohn Marino # endif /* __cplusplus */
2786d7f5d3SJohn Marino extern char *strerror (int,...);
2886d7f5d3SJohn Marino # define DONT_DECLARE_STRERROR
2986d7f5d3SJohn Marino # ifdef __cplusplus
3086d7f5d3SJohn Marino }
3186d7f5d3SJohn Marino # endif /* __cplusplus */
3286d7f5d3SJohn Marino # endif
3386d7f5d3SJohn Marino #endif /* VMS */
3486d7f5d3SJohn Marino
3586d7f5d3SJohn Marino
3686d7f5d3SJohn Marino #ifndef DONT_DECLARE_STRERROR
3786d7f5d3SJohn Marino # ifdef __cplusplus
3886d7f5d3SJohn Marino extern "C" {
3986d7f5d3SJohn Marino # endif /* __cplusplus */
4086d7f5d3SJohn Marino extern char *strerror (int);
4186d7f5d3SJohn Marino # ifdef __cplusplus
4286d7f5d3SJohn Marino }
4386d7f5d3SJohn Marino # endif /* __cplusplus */
4486d7f5d3SJohn Marino #endif
4586d7f5d3SJohn Marino
4686d7f5d3SJohn Marino /* If strerror returns NULL, we'll format the number into a static buffer. */
4786d7f5d3SJohn Marino
4886d7f5d3SJohn Marino #define ERRSTR_FMT "undocumented error #%d"
4986d7f5d3SJohn Marino static char xstrerror_buf[sizeof ERRSTR_FMT + 20];
5086d7f5d3SJohn Marino
5186d7f5d3SJohn Marino /* Like strerror, but result is never a null pointer. */
5286d7f5d3SJohn Marino
5386d7f5d3SJohn Marino char *
xstrerror(int errnum)5486d7f5d3SJohn Marino xstrerror (int errnum)
5586d7f5d3SJohn Marino {
5686d7f5d3SJohn Marino char *errstr;
5786d7f5d3SJohn Marino #ifdef VMS
5886d7f5d3SJohn Marino char *(*vmslib_strerror) (int,...);
5986d7f5d3SJohn Marino
6086d7f5d3SJohn Marino /* Override any possibly-conflicting declaration from system header. */
6186d7f5d3SJohn Marino vmslib_strerror = (char *(*) (int,...)) strerror;
6286d7f5d3SJohn Marino /* Second argument matters iff first is EVMSERR, but it's simpler to
6386d7f5d3SJohn Marino pass it unconditionally. `vaxc$errno' is declared in <errno.h>
6486d7f5d3SJohn Marino and maintained by the run-time library in parallel to `errno'.
6586d7f5d3SJohn Marino We assume that `errnum' corresponds to the last value assigned to
6686d7f5d3SJohn Marino errno by the run-time library, hence vaxc$errno will be relevant. */
6786d7f5d3SJohn Marino errstr = (*vmslib_strerror) (errnum, vaxc$errno);
6886d7f5d3SJohn Marino #else
6986d7f5d3SJohn Marino errstr = strerror (errnum);
7086d7f5d3SJohn Marino #endif
7186d7f5d3SJohn Marino
7286d7f5d3SJohn Marino /* If `errnum' is out of range, result might be NULL. We'll fix that. */
7386d7f5d3SJohn Marino if (!errstr)
7486d7f5d3SJohn Marino {
7586d7f5d3SJohn Marino sprintf (xstrerror_buf, ERRSTR_FMT, errnum);
7686d7f5d3SJohn Marino errstr = xstrerror_buf;
7786d7f5d3SJohn Marino }
7886d7f5d3SJohn Marino return errstr;
7986d7f5d3SJohn Marino }
80