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