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