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