1*2a6b7db3Sskrll /* xstrerror.c -- jacket routine for more robust strerror() usage.
2*2a6b7db3Sskrll Fri Jun 16 18:30:00 1995 Pat Rankin <rankin@eql.caltech.edu>
3*2a6b7db3Sskrll This code is in the public domain. */
4*2a6b7db3Sskrll
5*2a6b7db3Sskrll /*
6*2a6b7db3Sskrll
7*2a6b7db3Sskrll @deftypefn Replacement char* xstrerror (int @var{errnum})
8*2a6b7db3Sskrll
9*2a6b7db3Sskrll Behaves exactly like the standard @code{strerror} function, but
10*2a6b7db3Sskrll will never return a @code{NULL} pointer.
11*2a6b7db3Sskrll
12*2a6b7db3Sskrll @end deftypefn
13*2a6b7db3Sskrll
14*2a6b7db3Sskrll */
15*2a6b7db3Sskrll
16*2a6b7db3Sskrll #include <stdio.h>
17*2a6b7db3Sskrll
18*2a6b7db3Sskrll #include "config.h"
19*2a6b7db3Sskrll #include "libiberty.h"
20*2a6b7db3Sskrll
21*2a6b7db3Sskrll #ifdef VMS
22*2a6b7db3Sskrll # include <errno.h>
23*2a6b7db3Sskrll # if !defined (__STRICT_ANSI__) && !defined (__HIDE_FORBIDDEN_NAMES)
24*2a6b7db3Sskrll # ifdef __cplusplus
25*2a6b7db3Sskrll extern "C" {
26*2a6b7db3Sskrll # endif /* __cplusplus */
27*2a6b7db3Sskrll extern char *strerror (int,...);
28*2a6b7db3Sskrll # define DONT_DECLARE_STRERROR
29*2a6b7db3Sskrll # ifdef __cplusplus
30*2a6b7db3Sskrll }
31*2a6b7db3Sskrll # endif /* __cplusplus */
32*2a6b7db3Sskrll # endif
33*2a6b7db3Sskrll #endif /* VMS */
34*2a6b7db3Sskrll
35*2a6b7db3Sskrll
36*2a6b7db3Sskrll #ifndef DONT_DECLARE_STRERROR
37*2a6b7db3Sskrll # ifdef __cplusplus
38*2a6b7db3Sskrll extern "C" {
39*2a6b7db3Sskrll # endif /* __cplusplus */
40*2a6b7db3Sskrll extern char *strerror (int);
41*2a6b7db3Sskrll # ifdef __cplusplus
42*2a6b7db3Sskrll }
43*2a6b7db3Sskrll # endif /* __cplusplus */
44*2a6b7db3Sskrll #endif
45*2a6b7db3Sskrll
46*2a6b7db3Sskrll /* If strerror returns NULL, we'll format the number into a static buffer. */
47*2a6b7db3Sskrll
48*2a6b7db3Sskrll #define ERRSTR_FMT "undocumented error #%d"
49*2a6b7db3Sskrll static char xstrerror_buf[sizeof ERRSTR_FMT + 20];
50*2a6b7db3Sskrll
51*2a6b7db3Sskrll /* Like strerror, but result is never a null pointer. */
52*2a6b7db3Sskrll
53*2a6b7db3Sskrll char *
xstrerror(int errnum)54*2a6b7db3Sskrll xstrerror (int errnum)
55*2a6b7db3Sskrll {
56*2a6b7db3Sskrll char *errstr;
57*2a6b7db3Sskrll #ifdef VMS
58*2a6b7db3Sskrll char *(*vmslib_strerror) (int,...);
59*2a6b7db3Sskrll
60*2a6b7db3Sskrll /* Override any possibly-conflicting declaration from system header. */
61*2a6b7db3Sskrll vmslib_strerror = (char *(*) (int,...)) strerror;
62*2a6b7db3Sskrll /* Second argument matters iff first is EVMSERR, but it's simpler to
63*2a6b7db3Sskrll pass it unconditionally. `vaxc$errno' is declared in <errno.h>
64*2a6b7db3Sskrll and maintained by the run-time library in parallel to `errno'.
65*2a6b7db3Sskrll We assume that `errnum' corresponds to the last value assigned to
66*2a6b7db3Sskrll errno by the run-time library, hence vaxc$errno will be relevant. */
67*2a6b7db3Sskrll errstr = (*vmslib_strerror) (errnum, vaxc$errno);
68*2a6b7db3Sskrll #else
69*2a6b7db3Sskrll errstr = strerror (errnum);
70*2a6b7db3Sskrll #endif
71*2a6b7db3Sskrll
72*2a6b7db3Sskrll /* If `errnum' is out of range, result might be NULL. We'll fix that. */
73*2a6b7db3Sskrll if (!errstr)
74*2a6b7db3Sskrll {
75*2a6b7db3Sskrll sprintf (xstrerror_buf, ERRSTR_FMT, errnum);
76*2a6b7db3Sskrll errstr = xstrerror_buf;
77*2a6b7db3Sskrll }
78*2a6b7db3Sskrll return errstr;
79*2a6b7db3Sskrll }
80