home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gdb-4.16-base.tgz / gdb-4.16-base.tar / fsf / gdb / libiberty / strerror.c < prev    next >
C/C++ Source or Header  |  1995-05-20  |  21KB  |  830 lines

  1. /* Extended support for using errno values.
  2.    Written by Fred Fish.  fnf@cygnus.com
  3.    This file is in the public domain.  --Per Bothner.  */
  4.  
  5. #include "ansidecl.h"
  6. #include "libiberty.h"
  7.  
  8. #include "config.h"
  9.  
  10. #ifndef NEED_sys_errlist
  11. /* Note that errno.h (not sure what OS) or stdio.h (BSD 4.4, at least)
  12.    might declare sys_errlist in a way that the compiler might consider
  13.    incompatible with our later declaration, perhaps by using const
  14.    attributes.  So we hide the declaration in errno.h (if any) using a
  15.    macro. */
  16. #define sys_errlist sys_errlist__
  17. #endif
  18.  
  19. #include <stdio.h>
  20. #include <errno.h>
  21.  
  22. #ifndef NEED_sys_errlist
  23. #undef sys_errlist
  24. #endif
  25.  
  26. /*  Routines imported from standard C runtime libraries. */
  27.  
  28. #ifdef __STDC__
  29. #include <stddef.h>
  30. extern void *malloc (size_t size);                /* 4.10.3.3 */
  31. extern void *memset (void *s, int c, size_t n);            /* 4.11.6.1 */
  32. #else    /* !__STDC__ */
  33. extern char *malloc ();        /* Standard memory allocater */
  34. extern char *memset ();
  35. #endif    /* __STDC__ */
  36.  
  37. #ifndef MAX
  38. #  define MAX(a,b) ((a) > (b) ? (a) : (b))
  39. #endif
  40.  
  41. /* Translation table for errno values.  See intro(2) in most UNIX systems
  42.    Programmers Reference Manuals.
  43.  
  44.    Note that this table is generally only accessed when it is used at runtime
  45.    to initialize errno name and message tables that are indexed by errno
  46.    value.
  47.  
  48.    Not all of these errnos will exist on all systems.  This table is the only
  49.    thing that should have to be updated as new error numbers are introduced.
  50.    It's sort of ugly, but at least its portable. */
  51.  
  52. struct error_info
  53. {
  54.   int value;        /* The numeric value from <errno.h> */
  55.   const char *name;    /* The equivalent symbolic value */
  56. #ifdef NEED_sys_errlist
  57.   const char *msg;    /* Short message about this value */
  58. #endif
  59. };
  60.  
  61. #ifdef NEED_sys_errlist
  62. #   define ENTRY(value, name, msg)    {value, name, msg}
  63. #else
  64. #   define ENTRY(value, name, msg)    {value, name}
  65. #endif
  66.  
  67. static const struct error_info error_table[] =
  68. {
  69. #if defined (EPERM)
  70.   ENTRY(EPERM, "EPERM", "Not owner"),
  71. #endif
  72. #if defined (ENOENT)
  73.   ENTRY(ENOENT, "ENOENT", "No such file or directory"),
  74. #endif
  75. #if defined (ESRCH)
  76.   ENTRY(ESRCH, "ESRCH", "No such process"),
  77. #endif
  78. #if defined (EINTR)
  79.   ENTRY(EINTR, "EINTR", "Interrupted system call"),
  80. #endif
  81. #if defined (EIO)
  82.   ENTRY(EIO, "EIO", "I/O error"),
  83. #endif
  84. #if defined (ENXIO)
  85.   ENTRY(ENXIO, "ENXIO", "No such device or address"),
  86. #endif
  87. #if defined (E2BIG)
  88.   ENTRY(E2BIG, "E2BIG", "Arg list too long"),
  89. #endif
  90. #if defined (ENOEXEC)
  91.   ENTRY(ENOEXEC, "ENOEXEC", "Exec format error"),
  92. #endif
  93. #if defined (EBADF)
  94.   ENTRY(EBADF, "EBADF", "Bad file number"),
  95. #endif
  96. #if defined (ECHILD)
  97.   ENTRY(ECHILD, "ECHILD", "No child processes"),
  98. #endif
  99. #if defined (EWOULDBLOCK)    /* Put before EAGAIN, sometimes aliased */
  100.   ENTRY(EWOULDBLOCK, "EWOULDBLOCK", "Operation would block"),
  101. #endif
  102. #if defined (EAGAIN)
  103.   ENTRY(EAGAIN, "EAGAIN", "No more processes"),
  104. #endif
  105. #if defined (ENOMEM)
  106.   ENTRY(ENOMEM, "ENOMEM", "Not enough space"),
  107. #endif
  108. #if defined (EACCES)
  109.   ENTRY(EACCES, "EACCES", "Permission denied"),
  110. #endif
  111. #if defined (EFAULT)
  112.   ENTRY(EFAULT, "EFAULT", "Bad address"),
  113. #endif
  114. #if defined (ENOTBLK)
  115.   ENTRY(ENOTBLK, "ENOTBLK", "Block device required"),
  116. #endif
  117. #if defined (EBUSY)
  118.   ENTRY(EBUSY, "EBUSY", "Device busy"),
  119. #endif
  120. #if defined (EEXIST)
  121.   ENTRY(EEXIST, "EEXIST", "File exists"),
  122. #endif
  123. #if defined (EXDEV)
  124.   ENTRY(EXDEV, "EXDEV", "Cross-device link"),
  125. #endif
  126. #if defined (ENODEV)
  127.   ENTRY(ENODEV, "ENODEV", "No such device"),
  128. #endif
  129. #if defined (ENOTDIR)
  130.   ENTRY(ENOTDIR, "ENOTDIR", "Not a directory"),
  131. #endif
  132. #if defined (EISDIR)
  133.   ENTRY(EISDIR, "EISDIR", "Is a directory"),
  134. #endif
  135. #if defined (EINVAL)
  136.   ENTRY(EINVAL, "EINVAL", "Invalid argument"),
  137. #endif
  138. #if defined (ENFILE)
  139.   ENTRY(ENFILE, "ENFILE", "File table overflow"),
  140. #endif
  141. #if defined (EMFILE)
  142.   ENTRY(EMFILE, "EMFILE", "Too many open files"),
  143. #endif
  144. #if defined (ENOTTY)
  145.   ENTRY(ENOTTY, "ENOTTY", "Not a typewriter"),
  146. #endif
  147. #if defined (ETXTBSY)
  148.   ENTRY(ETXTBSY, "ETXTBSY", "Text file busy"),
  149. #endif
  150. #if defined (EFBIG)
  151.   ENTRY(EFBIG, "EFBIG", "File too large"),
  152. #endif
  153. #if defined (ENOSPC)
  154.   ENTRY(ENOSPC, "ENOSPC", "No space left on device"),
  155. #endif
  156. #if defined (ESPIPE)
  157.   ENTRY(ESPIPE, "ESPIPE", "Illegal seek"),
  158. #endif
  159. #if defined (EROFS)
  160.   ENTRY(EROFS, "EROFS", "Read-only file system"),
  161. #endif
  162. #if defined (EMLINK)
  163.   ENTRY(EMLINK, "EMLINK", "Too many links"),
  164. #endif
  165. #if defined (EPIPE)
  166.   ENTRY(EPIPE, "EPIPE", "Broken pipe"),
  167. #endif
  168. #if defined (EDOM)
  169.   ENTRY(EDOM, "EDOM", "Math argument out of domain of func"),
  170. #endif
  171. #if defined (ERANGE)
  172.   ENTRY(ERANGE, "ERANGE", "Math result not representable"),
  173. #endif
  174. #if defined (ENOMSG)
  175.   ENTRY(ENOMSG, "ENOMSG", "No message of desired type"),
  176. #endif
  177. #if defined (EIDRM)
  178.   ENTRY(EIDRM, "EIDRM", "Identifier removed"),
  179. #endif
  180. #if defined (ECHRNG)
  181.   ENTRY(ECHRNG, "ECHRNG", "Channel number out of range"),
  182. #endif
  183. #if defined (EL2NSYNC)
  184.   ENTRY(EL2NSYNC, "EL2NSYNC", "Level 2 not synchronized"),
  185. #endif
  186. #if defined (EL3HLT)
  187.   ENTRY(EL3HLT, "EL3HLT", "Level 3 halted"),
  188. #endif
  189. #if defined (EL3RST)
  190.   ENTRY(EL3RST, "EL3RST", "Level 3 reset"),
  191. #endif
  192. #if defined (ELNRNG)
  193.   ENTRY(ELNRNG, "ELNRNG", "Link number out of range"),
  194. #endif
  195. #if defined (EUNATCH)
  196.   ENTRY(EUNATCH, "EUNATCH", "Protocol driver not attached"),
  197. #endif
  198. #if defined (ENOCSI)
  199.   ENTRY(ENOCSI, "ENOCSI", "No CSI structure available"),
  200. #endif
  201. #if defined (EL2HLT)
  202.   ENTRY(EL2HLT, "EL2HLT", "Level 2 halted"),
  203. #endif
  204. #if defined (EDEADLK)
  205.   ENTRY(EDEADLK, "EDEADLK", "Deadlock condition"),
  206. #endif
  207. #if defined (ENOLCK)
  208.   ENTRY(ENOLCK, "ENOLCK", "No record locks available"),
  209. #endif
  210. #if defined (EBADE)
  211.   ENTRY(EBADE, "EBADE", "Invalid exchange"),
  212. #endif
  213. #if defined (EBADR)
  214.   ENTRY(EBADR, "EBADR", "Invalid request descriptor"),
  215. #endif
  216. #if defined (EXFULL)
  217.   ENTRY(EXFULL, "EXFULL", "Exchange full"),
  218. #endif
  219. #if defined (ENOANO)
  220.   ENTRY(ENOANO, "ENOANO", "No anode"),
  221. #endif
  222. #if defined (EBADRQC)
  223.   ENTRY(EBADRQC, "EBADRQC", "Invalid request code"),
  224. #endif
  225. #if defined (EBADSLT)
  226.   ENTRY(EBADSLT, "EBADSLT", "Invalid slot"),
  227. #endif
  228. #if defined (EDEADLOCK)
  229.   ENTRY(EDEADLOCK, "EDEADLOCK", "File locking deadlock error"),
  230. #endif
  231. #if defined (EBFONT)
  232.   ENTRY(EBFONT, "EBFONT", "Bad font file format"),
  233. #endif
  234. #if defined (ENOSTR)
  235.   ENTRY(ENOSTR, "ENOSTR", "Device not a stream"),
  236. #endif
  237. #if defined (ENODATA)
  238.   ENTRY(ENODATA, "ENODATA", "No data available"),
  239. #endif
  240. #if defined (ETIME)
  241.   ENTRY(ETIME, "ETIME", "Timer expired"),
  242. #endif
  243. #if defined (ENOSR)
  244.   ENTRY(ENOSR, "ENOSR", "Out of streams resources"),
  245. #endif
  246. #if defined (ENONET)
  247.   ENTRY(ENONET, "ENONET", "Machine is not on the network"),
  248. #endif
  249. #if defined (ENOPKG)
  250.   ENTRY(ENOPKG, "ENOPKG", "Package not installed"),
  251. #endif
  252. #if defined (EREMOTE)
  253.   ENTRY(EREMOTE, "EREMOTE", "Object is remote"),
  254. #endif
  255. #if defined (ENOLINK)
  256.   ENTRY(ENOLINK, "ENOLINK", "Link has been severed"),
  257. #endif
  258. #if defined (EADV)
  259.   ENTRY(EADV, "EADV", "Advertise error"),
  260. #endif
  261. #if defined (ESRMNT)
  262.   ENTRY(ESRMNT, "ESRMNT", "Srmount error"),
  263. #endif
  264. #if defined (ECOMM)
  265.   ENTRY(ECOMM, "ECOMM", "Communication error on send"),
  266. #endif
  267. #if defined (EPROTO)
  268.   ENTRY(EPROTO, "EPROTO", "Protocol error"),
  269. #endif
  270. #if defined (EMULTIHOP)
  271.   ENTRY(EMULTIHOP, "EMULTIHOP", "Multihop attempted"),
  272. #endif
  273. #if defined (EDOTDOT)
  274.   ENTRY(EDOTDOT, "EDOTDOT", "RFS specific error"),
  275. #endif
  276. #if defined (EBADMSG)
  277.   ENTRY(EBADMSG, "EBADMSG", "Not a data message"),
  278. #endif
  279. #if defined (ENAMETOOLONG)
  280.   ENTRY(ENAMETOOLONG, "ENAMETOOLONG", "File name too long"),
  281. #endif
  282. #if defined (EOVERFLOW)
  283.   ENTRY(EOVERFLOW, "EOVERFLOW", "Value too large for defined data type"),
  284. #endif
  285. #if defined (ENOTUNIQ)
  286.   ENTRY(ENOTUNIQ, "ENOTUNIQ", "Name not unique on network"),
  287. #endif
  288. #if defined (EBADFD)
  289.   ENTRY(EBADFD, "EBADFD", "File descriptor in bad state"),
  290. #endif
  291. #if defined (EREMCHG)
  292.   ENTRY(EREMCHG, "EREMCHG", "Remote address changed"),
  293. #endif
  294. #if defined (ELIBACC)
  295.   ENTRY(ELIBACC, "ELIBACC", "Can not access a needed shared library"),
  296. #endif
  297. #if defined (ELIBBAD)
  298.   ENTRY(ELIBBAD, "ELIBBAD", "Accessing a corrupted shared library"),
  299. #endif
  300. #if defined (ELIBSCN)
  301.   ENTRY(ELIBSCN, "ELIBSCN", ".lib section in a.out corrupted"),
  302. #endif
  303. #if defined (ELIBMAX)
  304.   ENTRY(ELIBMAX, "ELIBMAX", "Attempting to link in too many shared libraries"),
  305. #endif
  306. #if defined (ELIBEXEC)
  307.   ENTRY(ELIBEXEC, "ELIBEXEC", "Cannot exec a shared library directly"),
  308. #endif
  309. #if defined (EILSEQ)
  310.   ENTRY(EILSEQ, "EILSEQ", "Illegal byte sequence"),
  311. #endif
  312. #if defined (ENOSYS)
  313.   ENTRY(ENOSYS, "ENOSYS", "Operation not applicable"),
  314. #endif
  315. #if defined (ELOOP)
  316.   ENTRY(ELOOP, "ELOOP", "Too many symbolic links encountered"),
  317. #endif
  318. #if defined (ERESTART)
  319.   ENTRY(ERESTART, "ERESTART", "Interrupted system call should be restarted"),
  320. #endif
  321. #if defined (ESTRPIPE)
  322.   ENTRY(ESTRPIPE, "ESTRPIPE", "Streams pipe error"),
  323. #endif
  324. #if defined (ENOTEMPTY)
  325.   ENTRY(ENOTEMPTY, "ENOTEMPTY", "Directory not empty"),
  326. #endif
  327. #if defined (EUSERS)
  328.   ENTRY(EUSERS, "EUSERS", "Too many users"),
  329. #endif
  330. #if defined (ENOTSOCK)
  331.   ENTRY(ENOTSOCK, "ENOTSOCK", "Socket operation on non-socket"),
  332. #endif
  333. #if defined (EDESTADDRREQ)
  334.   ENTRY(EDESTADDRREQ, "EDESTADDRREQ", "Destination address required"),
  335. #endif
  336. #if defined (EMSGSIZE)
  337.   ENTRY(EMSGSIZE, "EMSGSIZE", "Message too long"),
  338. #endif
  339. #if defined (EPROTOTYPE)
  340.   ENTRY(EPROTOTYPE, "EPROTOTYPE", "Protocol wrong type for socket"),
  341. #endif
  342. #if defined (ENOPROTOOPT)
  343.   ENTRY(ENOPROTOOPT, "ENOPROTOOPT", "Protocol not available"),
  344. #endif
  345. #if defined (EPROTONOSUPPORT)
  346.   ENTRY(EPROTONOSUPPORT, "EPROTONOSUPPORT", "Protocol not supported"),
  347. #endif
  348. #if defined (ESOCKTNOSUPPORT)
  349.   ENTRY(ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT", "Socket type not supported"),
  350. #endif
  351. #if defined (EOPNOTSUPP)
  352.   ENTRY(EOPNOTSUPP, "EOPNOTSUPP", "Operation not supported on transport endpoint"),
  353. #endif
  354. #if defined (EPFNOSUPPORT)
  355.   ENTRY(EPFNOSUPPORT, "EPFNOSUPPORT", "Protocol family not supported"),
  356. #endif
  357. #if defined (EAFNOSUPPORT)
  358.   ENTRY(EAFNOSUPPORT, "EAFNOSUPPORT", "Address family not supported by protocol"),
  359. #endif
  360. #if defined (EADDRINUSE)
  361.   ENTRY(EADDRINUSE, "EADDRINUSE", "Address already in use"),
  362. #endif
  363. #if defined (EADDRNOTAVAIL)
  364.   ENTRY(EADDRNOTAVAIL, "EADDRNOTAVAIL","Cannot assign requested address"),
  365. #endif
  366. #if defined (ENETDOWN)
  367.   ENTRY(ENETDOWN, "ENETDOWN", "Network is down"),
  368. #endif
  369. #if defined (ENETUNREACH)
  370.   ENTRY(ENETUNREACH, "ENETUNREACH", "Network is unreachable"),
  371. #endif
  372. #if defined (ENETRESET)
  373.   ENTRY(ENETRESET, "ENETRESET", "Network dropped connection because of reset"),
  374. #endif
  375. #if defined (ECONNABORTED)
  376.   ENTRY(ECONNABORTED, "ECONNABORTED", "Software caused connection abort"),
  377. #endif
  378. #if defined (ECONNRESET)
  379.   ENTRY(ECONNRESET, "ECONNRESET", "Connection reset by peer"),
  380. #endif
  381. #if defined (ENOBUFS)
  382.   ENTRY(ENOBUFS, "ENOBUFS", "No buffer space available"),
  383. #endif
  384. #if defined (EISCONN)
  385.   ENTRY(EISCONN, "EISCONN", "Transport endpoint is already connected"),
  386. #endif
  387. #if defined (ENOTCONN)
  388.   ENTRY(ENOTCONN, "ENOTCONN", "Transport endpoint is not connected"),
  389. #endif
  390. #if defined (ESHUTDOWN)
  391.   ENTRY(ESHUTDOWN, "ESHUTDOWN", "Cannot send after transport endpoint shutdown"),
  392. #endif
  393. #if defined (ETOOMANYREFS)
  394.   ENTRY(ETOOMANYREFS, "ETOOMANYREFS", "Too many references: cannot splice"),
  395. #endif
  396. #if defined (ETIMEDOUT)
  397.   ENTRY(ETIMEDOUT, "ETIMEDOUT", "Connection timed out"),
  398. #endif
  399. #if defined (ECONNREFUSED)
  400.   ENTRY(ECONNREFUSED, "ECONNREFUSED", "Connection refused"),
  401. #endif
  402. #if defined (EHOSTDOWN)
  403.   ENTRY(EHOSTDOWN, "EHOSTDOWN", "Host is down"),
  404. #endif
  405. #if defined (EHOSTUNREACH)
  406.   ENTRY(EHOSTUNREACH, "EHOSTUNREACH", "No route to host"),
  407. #endif
  408. #if defined (EALREADY)
  409.   ENTRY(EALREADY, "EALREADY", "Operation already in progress"),
  410. #endif
  411. #if defined (EINPROGRESS)
  412.   ENTRY(EINPROGRESS, "EINPROGRESS", "Operation now in progress"),
  413. #endif
  414. #if defined (ESTALE)
  415.   ENTRY(ESTALE, "ESTALE", "Stale NFS file handle"),
  416. #endif
  417. #if defined (EUCLEAN)
  418.   ENTRY(EUCLEAN, "EUCLEAN", "Structure needs cleaning"),
  419. #endif
  420. #if defined (ENOTNAM)
  421.   ENTRY(ENOTNAM, "ENOTNAM", "Not a XENIX named type file"),
  422. #endif
  423. #if defined (ENAVAIL)
  424.   ENTRY(ENAVAIL, "ENAVAIL", "No XENIX semaphores available"),
  425. #endif
  426. #if defined (EISNAM)
  427.   ENTRY(EISNAM, "EISNAM", "Is a named type file"),
  428. #endif
  429. #if defined (EREMOTEIO)
  430.   ENTRY(EREMOTEIO, "EREMOTEIO", "Remote I/O error"),
  431. #endif
  432.   ENTRY(0, NULL, NULL)
  433. };
  434.  
  435. #ifdef EVMSERR
  436. /* This is not in the table, because the numeric value of EVMSERR (32767)
  437.    lies outside the range of sys_errlist[].  */
  438. static struct { int value; const char *name, *msg; }
  439.   evmserr = { EVMSERR, "EVMSERR", "VMS-specific error" };
  440. #endif
  441.  
  442. /* Translation table allocated and initialized at runtime.  Indexed by the
  443.    errno value to find the equivalent symbolic value. */
  444.  
  445. static const char **error_names;
  446. static int num_error_names = 0;
  447.  
  448. /* Translation table allocated and initialized at runtime, if it does not
  449.    already exist in the host environment.  Indexed by the errno value to find
  450.    the descriptive string.
  451.  
  452.    We don't export it for use in other modules because even though it has the
  453.    same name, it differs from other implementations in that it is dynamically
  454.    initialized rather than statically initialized. */
  455.  
  456. #ifdef NEED_sys_errlist
  457.  
  458. static int sys_nerr;
  459. static const char **sys_errlist;
  460.  
  461. #else
  462.  
  463. extern int sys_nerr;
  464. extern char *sys_errlist[];
  465.  
  466. #endif
  467.  
  468.  
  469. /*
  470.  
  471. NAME
  472.  
  473.     init_error_tables -- initialize the name and message tables
  474.  
  475. SYNOPSIS
  476.  
  477.     static void init_error_tables ();
  478.  
  479. DESCRIPTION
  480.  
  481.     Using the error_table, which is initialized at compile time, generate
  482.     the error_names and the sys_errlist (if needed) tables, which are
  483.     indexed at runtime by a specific errno value.
  484.  
  485. BUGS
  486.  
  487.     The initialization of the tables may fail under low memory conditions,
  488.     in which case we don't do anything particularly useful, but we don't
  489.     bomb either.  Who knows, it might succeed at a later point if we free
  490.     some memory in the meantime.  In any case, the other routines know
  491.     how to deal with lack of a table after trying to initialize it.  This
  492.     may or may not be considered to be a bug, that we don't specifically
  493.     warn about this particular failure mode.
  494.  
  495. */
  496.  
  497. static void
  498. init_error_tables ()
  499. {
  500.   const struct error_info *eip;
  501.   int nbytes;
  502.  
  503.   /* If we haven't already scanned the error_table once to find the maximum
  504.      errno value, then go find it now. */
  505.  
  506.   if (num_error_names == 0)
  507.     {
  508.       for (eip = error_table; eip -> name != NULL; eip++)
  509.     {
  510.       if (eip -> value >= num_error_names)
  511.         {
  512.           num_error_names = eip -> value + 1;
  513.         }
  514.     }
  515.     }
  516.  
  517.   /* Now attempt to allocate the error_names table, zero it out, and then
  518.      initialize it from the statically initialized error_table. */
  519.  
  520.   if (error_names == NULL)
  521.     {
  522.       nbytes = num_error_names * sizeof (char *);
  523.       if ((error_names = (const char **) malloc (nbytes)) != NULL)
  524.     {
  525.       memset (error_names, 0, nbytes);
  526.       for (eip = error_table; eip -> name != NULL; eip++)
  527.         {
  528.           error_names[eip -> value] = eip -> name;
  529.         }
  530.     }
  531.     }
  532.  
  533. #ifdef NEED_sys_errlist
  534.  
  535.   /* Now attempt to allocate the sys_errlist table, zero it out, and then
  536.      initialize it from the statically initialized error_table. */
  537.  
  538.   if (sys_errlist == NULL)
  539.     {
  540.       nbytes = num_error_names * sizeof (char *);
  541.       if ((sys_errlist = (const char **) malloc (nbytes)) != NULL)
  542.     {
  543.       memset (sys_errlist, 0, nbytes);
  544.       sys_nerr = num_error_names;
  545.       for (eip = error_table; eip -> name != NULL; eip++)
  546.         {
  547.           sys_errlist[eip -> value] = eip -> msg;
  548.         }
  549.     }
  550.     }
  551.  
  552. #endif
  553.  
  554. }
  555.  
  556. /*
  557.  
  558. NAME
  559.  
  560.     errno_max -- return the max errno value
  561.  
  562. SYNOPSIS
  563.  
  564.     int errno_max ();
  565.  
  566. DESCRIPTION
  567.  
  568.     Returns the maximum errno value for which a corresponding symbolic
  569.     name or message is available.  Note that in the case where
  570.     we use the sys_errlist supplied by the system, it is possible for
  571.     there to be more symbolic names than messages, or vice versa.
  572.     In fact, the manual page for perror(3C) explicitly warns that one
  573.     should check the size of the table (sys_nerr) before indexing it,
  574.     since new error codes may be added to the system before they are
  575.     added to the table.  Thus sys_nerr might be smaller than value
  576.     implied by the largest errno value defined in <errno.h>.
  577.  
  578.     We return the maximum value that can be used to obtain a meaningful
  579.     symbolic name or message.
  580.  
  581. */
  582.  
  583. int
  584. errno_max ()
  585. {
  586.   int maxsize;
  587.  
  588.   if (error_names == NULL)
  589.     {
  590.       init_error_tables ();
  591.     }
  592.   maxsize = MAX (sys_nerr, num_error_names);
  593.   return (maxsize - 1);
  594. }
  595.  
  596. #ifdef NEED_strerror
  597.  
  598. /*
  599.  
  600. NAME
  601.  
  602.     strerror -- map an error number to an error message string
  603.  
  604. SYNOPSIS
  605.  
  606.     char *strerror (int errnoval)
  607.  
  608. DESCRIPTION
  609.  
  610.     Maps an errno number to an error message string, the contents of
  611.     which are implementation defined.  On systems which have the external
  612.     variables sys_nerr and sys_errlist, these strings will be the same
  613.     as the ones used by perror().
  614.  
  615.     If the supplied error number is within the valid range of indices
  616.     for the sys_errlist, but no message is available for the particular
  617.     error number, then returns the string "Error NUM", where NUM is the
  618.     error number.
  619.  
  620.     If the supplied error number is not a valid index into sys_errlist,
  621.     returns NULL.
  622.  
  623.     The returned string is only guaranteed to be valid only until the
  624.     next call to strerror.
  625.  
  626. */
  627.  
  628. char *
  629. strerror (errnoval)
  630.   int errnoval;
  631. {
  632.   char *msg;
  633.   static char buf[32];
  634.  
  635. #ifdef NEED_sys_errlist
  636.  
  637.   if (error_names == NULL)
  638.     {
  639.       init_error_tables ();
  640.     }
  641.  
  642. #endif
  643.  
  644.   if ((errnoval < 0) || (errnoval >= sys_nerr))
  645.     {
  646. #ifdef EVMSERR
  647.       if (errnoval == evmserr.value)
  648.     msg = evmserr.msg;
  649.       else
  650. #endif
  651.       /* Out of range, just return NULL */
  652.       msg = NULL;
  653.     }
  654.   else if ((sys_errlist == NULL) || (sys_errlist[errnoval] == NULL))
  655.     {
  656.       /* In range, but no sys_errlist or no entry at this index. */
  657.       sprintf (buf, "Error %d", errnoval);
  658.       msg = buf;
  659.     }
  660.   else
  661.     {
  662.       /* In range, and a valid message.  Just return the message. */
  663.       msg = (char *) sys_errlist[errnoval];
  664.     }
  665.   
  666.   return (msg);
  667. }
  668.  
  669. #endif    /* NEED_strerror */
  670.  
  671.  
  672. /*
  673.  
  674. NAME
  675.  
  676.     strerrno -- map an error number to a symbolic name string
  677.  
  678. SYNOPSIS
  679.  
  680.     const char *strerrno (int errnoval)
  681.  
  682. DESCRIPTION
  683.  
  684.     Given an error number returned from a system call (typically
  685.     returned in errno), returns a pointer to a string containing the
  686.     symbolic name of that error number, as found in <errno.h>.
  687.  
  688.     If the supplied error number is within the valid range of indices
  689.     for symbolic names, but no name is available for the particular
  690.     error number, then returns the string "Error NUM", where NUM is
  691.     the error number.
  692.  
  693.     If the supplied error number is not within the range of valid
  694.     indices, then returns NULL.
  695.  
  696. BUGS
  697.  
  698.     The contents of the location pointed to are only guaranteed to be
  699.     valid until the next call to strerrno.
  700.  
  701. */
  702.  
  703. const char *
  704. strerrno (errnoval)
  705.   int errnoval;
  706. {
  707.   const char *name;
  708.   static char buf[32];
  709.  
  710.   if (error_names == NULL)
  711.     {
  712.       init_error_tables ();
  713.     }
  714.  
  715.   if ((errnoval < 0) || (errnoval >= num_error_names))
  716.     {
  717. #ifdef EVMSERR
  718.       if (errnoval == evmserr.value)
  719.     name = evmserr.name;
  720.       else
  721. #endif
  722.       /* Out of range, just return NULL */
  723.       name = NULL;
  724.     }
  725.   else if ((error_names == NULL) || (error_names[errnoval] == NULL))
  726.     {
  727.       /* In range, but no error_names or no entry at this index. */
  728.       sprintf (buf, "Error %d", errnoval);
  729.       name = (const char *) buf;
  730.     }
  731.   else
  732.     {
  733.       /* In range, and a valid name.  Just return the name. */
  734.       name = error_names[errnoval];
  735.     }
  736.  
  737.   return (name);
  738. }
  739.  
  740. /*
  741.  
  742. NAME
  743.  
  744.     strtoerrno -- map a symbolic errno name to a numeric value
  745.  
  746. SYNOPSIS
  747.  
  748.     int strtoerrno (char *name)
  749.  
  750. DESCRIPTION
  751.  
  752.     Given the symbolic name of a error number, map it to an errno value.
  753.     If no translation is found, returns 0.
  754.  
  755. */
  756.  
  757. int
  758. strtoerrno (name)
  759.      const char *name;
  760. {
  761.   int errnoval = 0;
  762.  
  763.   if (name != NULL)
  764.     {
  765.       if (error_names == NULL)
  766.     {
  767.       init_error_tables ();
  768.     }
  769.       for (errnoval = 0; errnoval < num_error_names; errnoval++)
  770.     {
  771.       if ((error_names[errnoval] != NULL) &&
  772.           (strcmp (name, error_names[errnoval]) == 0))
  773.         {
  774.           break;
  775.         }
  776.     }
  777.       if (errnoval == num_error_names)
  778.     {
  779. #ifdef EVMSERR
  780.       if (strcmp (name, evmserr.name) == 0)
  781.         errnoval = evmserr.value;
  782.       else
  783. #endif
  784.       errnoval = 0;
  785.     }
  786.     }
  787.   return (errnoval);
  788. }
  789.  
  790.  
  791. /* A simple little main that does nothing but print all the errno translations
  792.    if MAIN is defined and this file is compiled and linked. */
  793.  
  794. #ifdef MAIN
  795.  
  796. #include <stdio.h>
  797.  
  798. int
  799. main ()
  800. {
  801.   int errn;
  802.   int errnmax;
  803.   const char *name;
  804.   char *msg;
  805.   char *strerror ();
  806.  
  807.   errnmax = errno_max ();
  808.   printf ("%d entries in names table.\n", num_error_names);
  809.   printf ("%d entries in messages table.\n", sys_nerr);
  810.   printf ("%d is max useful index.\n", errnmax);
  811.  
  812.   /* Keep printing values until we get to the end of *both* tables, not
  813.      *either* table.  Note that knowing the maximum useful index does *not*
  814.      relieve us of the responsibility of testing the return pointer for
  815.      NULL. */
  816.  
  817.   for (errn = 0; errn <= errnmax; errn++)
  818.     {
  819.       name = strerrno (errn);
  820.       name = (name == NULL) ? "<NULL>" : name;
  821.       msg = strerror (errn);
  822.       msg = (msg == NULL) ? "<NULL>" : msg;
  823.       printf ("%-4d%-18s%s\n", errn, name, msg);
  824.     }
  825.  
  826.   return 0;
  827. }
  828.  
  829. #endif
  830.