133965Sjdp/* xstrerror.c -- jacket routine for more robust strerror() usage.
233965Sjdp   Fri Jun 16 18:30:00 1995  Pat Rankin  <rankin@eql.caltech.edu>
333965Sjdp   This code is in the public domain.  */
433965Sjdp
589857Sobrien/*
689857Sobrien
789857Sobrien@deftypefn Replacement char* xstrerror (int @var{errnum})
889857Sobrien
989857SobrienBehaves exactly like the standard @code{strerror} function, but
1089857Sobrienwill never return a @code{NULL} pointer.
1189857Sobrien
1289857Sobrien@end deftypefn
1389857Sobrien
1489857Sobrien*/
1589857Sobrien
1633965Sjdp#include <stdio.h>
1733965Sjdp
18218822Sdim#include "config.h"
1933965Sjdp#include "libiberty.h"
2033965Sjdp
2133965Sjdp#ifdef VMS
22218822Sdim#  include <errno.h>
23218822Sdim#  if !defined (__STRICT_ANSI__) && !defined (__HIDE_FORBIDDEN_NAMES)
24218822Sdim#    ifdef __cplusplus
25218822Sdimextern "C" {
26218822Sdim#    endif /* __cplusplus */
27218822Sdimextern char *strerror (int,...);
28218822Sdim#    define DONT_DECLARE_STRERROR
29218822Sdim#    ifdef __cplusplus
30218822Sdim}
31218822Sdim#    endif /* __cplusplus */
32218822Sdim#  endif
33218822Sdim#endif  /* VMS */
3433965Sjdp
35218822Sdim
3633965Sjdp#ifndef DONT_DECLARE_STRERROR
37218822Sdim#  ifdef __cplusplus
38218822Sdimextern "C" {
39218822Sdim#  endif /* __cplusplus */
40218822Sdimextern char *strerror (int);
41218822Sdim#  ifdef __cplusplus
42218822Sdim}
43218822Sdim#  endif /* __cplusplus */
4433965Sjdp#endif
4533965Sjdp
4633965Sjdp/* If strerror returns NULL, we'll format the number into a static buffer.  */
4733965Sjdp
4833965Sjdp#define ERRSTR_FMT "undocumented error #%d"
4933965Sjdpstatic char xstrerror_buf[sizeof ERRSTR_FMT + 20];
5033965Sjdp
5133965Sjdp/* Like strerror, but result is never a null pointer.  */
5233965Sjdp
5333965Sjdpchar *
54218822Sdimxstrerror (int errnum)
5533965Sjdp{
5633965Sjdp  char *errstr;
5733965Sjdp#ifdef VMS
58218822Sdim  char *(*vmslib_strerror) (int,...);
5933965Sjdp
6033965Sjdp  /* Override any possibly-conflicting declaration from system header.  */
61218822Sdim  vmslib_strerror = (char *(*) (int,...)) strerror;
6233965Sjdp  /* Second argument matters iff first is EVMSERR, but it's simpler to
6333965Sjdp     pass it unconditionally.  `vaxc$errno' is declared in <errno.h>
6433965Sjdp     and maintained by the run-time library in parallel to `errno'.
6533965Sjdp     We assume that `errnum' corresponds to the last value assigned to
6633965Sjdp     errno by the run-time library, hence vaxc$errno will be relevant.  */
6733965Sjdp  errstr = (*vmslib_strerror) (errnum, vaxc$errno);
6833965Sjdp#else
6933965Sjdp  errstr = strerror (errnum);
7033965Sjdp#endif
7133965Sjdp
7233965Sjdp  /* If `errnum' is out of range, result might be NULL.  We'll fix that.  */
7333965Sjdp  if (!errstr)
7433965Sjdp    {
7533965Sjdp      sprintf (xstrerror_buf, ERRSTR_FMT, errnum);
7633965Sjdp      errstr = xstrerror_buf;
7733965Sjdp    }
7833965Sjdp  return errstr;
7933965Sjdp}
80