]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/gdb/libiberty/strerror.c
This file was not part of the GDB 5.2.1 import and should have been
[FreeBSD/FreeBSD.git] / contrib / gdb / 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 #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