aboutsummaryrefslogtreecommitdiff
path: root/gnu/lib/libg++/libiberty/strsignal.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/lib/libg++/libiberty/strsignal.c')
-rw-r--r--gnu/lib/libg++/libiberty/strsignal.c623
1 files changed, 623 insertions, 0 deletions
diff --git a/gnu/lib/libg++/libiberty/strsignal.c b/gnu/lib/libg++/libiberty/strsignal.c
new file mode 100644
index 000000000000..83d9252b9fee
--- /dev/null
+++ b/gnu/lib/libg++/libiberty/strsignal.c
@@ -0,0 +1,623 @@
+/* Extended support for using signal values.
+ Copyright (C) 1992 Free Software Foundation, Inc.
+ Written by Fred Fish. fnf@cygnus.com
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <signal.h>
+
+/* Routines imported from standard C runtime libraries. */
+
+#ifdef __STDC__
+#include <stddef.h>
+extern void *malloc (size_t size); /* 4.10.3.3 */
+extern void *memset (void *s, int c, size_t n); /* 4.11.6.1 */
+#else /* !__STDC__ */
+#ifndef const
+#define const
+#endif
+extern char *malloc (); /* Standard memory allocater */
+extern char *memset ();
+#endif /* __STDC__ */
+
+#ifndef NULL
+# ifdef __STDC__
+# define NULL (void *) 0
+# else
+# define NULL 0
+# endif
+#endif
+
+#ifndef MAX
+# define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+/* Translation table for signal values.
+
+ Note that this table is generally only accessed when it is used at runtime
+ to initialize signal name and message tables that are indexed by signal
+ value.
+
+ Not all of these signals will exist on all systems. This table is the only
+ thing that should have to be updated as new signal numbers are introduced.
+ It's sort of ugly, but at least its portable. */
+
+struct signal_info
+{
+ int value; /* The numeric value from <signal.h> */
+ char *name; /* The equivalent symbolic value */
+ char *msg; /* Short message about this value */
+};
+
+static const struct signal_info signal_table[] =
+{
+#if defined (SIGHUP)
+ SIGHUP, "SIGHUP", "Hangup",
+#endif
+#if defined (SIGINT)
+ SIGINT, "SIGINT", "Interrupt",
+#endif
+#if defined (SIGQUIT)
+ SIGQUIT, "SIGQUIT", "Quit",
+#endif
+#if defined (SIGILL)
+ SIGILL, "SIGILL", "Illegal instruction",
+#endif
+#if defined (SIGTRAP)
+ SIGTRAP, "SIGTRAP", "Trace/breakpoint trap",
+#endif
+/* Put SIGIOT before SIGABRT, so that if SIGIOT==SIGABRT then SIGABRT
+ overrides SIGIOT. SIGABRT is in ANSI and POSIX.1, and SIGIOT isn't. */
+#if defined (SIGIOT)
+ SIGIOT, "SIGIOT", "IOT trap",
+#endif
+#if defined (SIGABRT)
+ SIGABRT, "SIGABRT", "Aborted",
+#endif
+#if defined (SIGEMT)
+ SIGEMT, "SIGEMT", "Emulation trap",
+#endif
+#if defined (SIGFPE)
+ SIGFPE, "SIGFPE", "Arithmetic exception",
+#endif
+#if defined (SIGKILL)
+ SIGKILL, "SIGKILL", "Killed",
+#endif
+#if defined (SIGBUS)
+ SIGBUS, "SIGBUS", "Bus error",
+#endif
+#if defined (SIGSEGV)
+ SIGSEGV, "SIGSEGV", "Segmentation fault",
+#endif
+#if defined (SIGSYS)
+ SIGSYS, "SIGSYS", "Bad system call",
+#endif
+#if defined (SIGPIPE)
+ SIGPIPE, "SIGPIPE", "Broken pipe",
+#endif
+#if defined (SIGALRM)
+ SIGALRM, "SIGALRM", "Alarm clock",
+#endif
+#if defined (SIGTERM)
+ SIGTERM, "SIGTERM", "Terminated",
+#endif
+#if defined (SIGUSR1)
+ SIGUSR1, "SIGUSR1", "User defined signal 1",
+#endif
+#if defined (SIGUSR2)
+ SIGUSR2, "SIGUSR2", "User defined signal 2",
+#endif
+/* Put SIGCLD before SIGCHLD, so that if SIGCLD==SIGCHLD then SIGCHLD
+ overrides SIGCLD. SIGCHLD is in POXIX.1 */
+#if defined (SIGCLD)
+ SIGCLD, "SIGCLD", "Child status changed",
+#endif
+#if defined (SIGCHLD)
+ SIGCHLD, "SIGCHLD", "Child status changed",
+#endif
+#if defined (SIGPWR)
+ SIGPWR, "SIGPWR", "Power fail/restart",
+#endif
+#if defined (SIGWINCH)
+ SIGWINCH, "SIGWINCH", "Window size changed",
+#endif
+#if defined (SIGURG)
+ SIGURG, "SIGURG", "Urgent I/O condition",
+#endif
+#if defined (SIGIO)
+ /* "I/O pending has also been suggested, but is misleading since the
+ signal only happens when the process has asked for it, not everytime
+ I/O is pending. */
+ SIGIO, "SIGIO", "I/O possible",
+#endif
+#if defined (SIGPOLL)
+ SIGPOLL, "SIGPOLL", "Pollable event occurred",
+#endif
+#if defined (SIGSTOP)
+ SIGSTOP, "SIGSTOP", "Stopped (signal)",
+#endif
+#if defined (SIGTSTP)
+ SIGTSTP, "SIGTSTP", "Stopped (user)",
+#endif
+#if defined (SIGCONT)
+ SIGCONT, "SIGCONT", "Continued",
+#endif
+#if defined (SIGTTIN)
+ SIGTTIN, "SIGTTIN", "Stopped (tty input)",
+#endif
+#if defined (SIGTTOU)
+ SIGTTOU, "SIGTTOU", "Stopped (tty output)",
+#endif
+#if defined (SIGVTALRM)
+ SIGVTALRM, "SIGVTALRM", "Virtual timer expired",
+#endif
+#if defined (SIGPROF)
+ SIGPROF, "SIGPROF", "Profiling timer expired",
+#endif
+#if defined (SIGXCPU)
+ SIGXCPU, "SIGXCPU", "CPU time limit exceeded",
+#endif
+#if defined (SIGXFSZ)
+ SIGXFSZ, "SIGXFSZ", "File size limit exceeded",
+#endif
+#if defined (SIGWIND)
+ SIGWIND, "SIGWIND", "SIGWIND",
+#endif
+#if defined (SIGPHONE)
+ SIGPHONE, "SIGPHONE", "SIGPHONE",
+#endif
+#if defined (SIGLOST)
+ SIGLOST, "SIGLOST", "Resource lost",
+#endif
+#if defined (SIGWAITING)
+ SIGWAITING, "SIGWAITING", "Process's LWPs are blocked",
+#endif
+#if defined (SIGLWP)
+ SIGLWP, "SIGLWP", "Signal LWP",
+#endif
+#if defined (SIGDANGER)
+ SIGDANGER, "SIGDANGER", "Swap space dangerously low",
+#endif
+#if defined (SIGGRANT)
+ SIGGRANT, "SIGGRANT", "Monitor mode granted",
+#endif
+#if defined (SIGRETRACT)
+ SIGRETRACT, "SIGRETRACT", "Need to relinguish monitor mode",
+#endif
+#if defined (SIGMSG)
+ SIGMSG, "SIGMSG", "Monitor mode data available",
+#endif
+#if defined (SIGSOUND)
+ SIGSOUND, "SIGSOUND", "Sound completed",
+#endif
+#if defined (SIGSAK)
+ SIGSAK, "SIGSAK", "Secure attention",
+#endif
+ 0, NULL, NULL
+};
+
+/* Translation table allocated and initialized at runtime. Indexed by the
+ signal value to find the equivalent symbolic value. */
+
+static char **signal_names;
+static int num_signal_names = 0;
+
+/* Translation table allocated and initialized at runtime, if it does not
+ already exist in the host environment. Indexed by the signal value to find
+ the descriptive string.
+
+ We don't export it for use in other modules because even though it has the
+ same name, it differs from other implementations in that it is dynamically
+ initialized rather than statically initialized. */
+
+#ifdef NEED_sys_siglist
+
+static int sys_nsig;
+static char **sys_siglist;
+
+#else
+
+static int sys_nsig = NSIG;
+extern const char * const sys_siglist[];
+
+#endif
+
+
+/*
+
+NAME
+
+ init_signal_tables -- initialize the name and message tables
+
+SYNOPSIS
+
+ static void init_signal_tables ();
+
+DESCRIPTION
+
+ Using the signal_table, which is initialized at compile time, generate
+ the signal_names and the sys_siglist (if needed) tables, which are
+ indexed at runtime by a specific signal value.
+
+BUGS
+
+ The initialization of the tables may fail under low memory conditions,
+ in which case we don't do anything particularly useful, but we don't
+ bomb either. Who knows, it might succeed at a later point if we free
+ some memory in the meantime. In any case, the other routines know
+ how to deal with lack of a table after trying to initialize it. This
+ may or may not be considered to be a bug, that we don't specifically
+ warn about this particular failure mode.
+
+*/
+
+static void
+init_signal_tables ()
+{
+ const struct signal_info *eip;
+ int nbytes;
+
+ /* If we haven't already scanned the signal_table once to find the maximum
+ signal value, then go find it now. */
+
+ if (num_signal_names == 0)
+ {
+ for (eip = signal_table; eip -> name != NULL; eip++)
+ {
+ if (eip -> value >= num_signal_names)
+ {
+ num_signal_names = eip -> value + 1;
+ }
+ }
+ }
+
+ /* Now attempt to allocate the signal_names table, zero it out, and then
+ initialize it from the statically initialized signal_table. */
+
+ if (signal_names == NULL)
+ {
+ nbytes = num_signal_names * sizeof (char *);
+ if ((signal_names = (char **) malloc (nbytes)) != NULL)
+ {
+ memset (signal_names, 0, nbytes);
+ for (eip = signal_table; eip -> name != NULL; eip++)
+ {
+ signal_names[eip -> value] = eip -> name;
+ }
+ }
+ }
+
+#ifdef NEED_sys_siglist
+
+ /* Now attempt to allocate the sys_siglist table, zero it out, and then
+ initialize it from the statically initialized signal_table. */
+
+ if (sys_siglist == NULL)
+ {
+ nbytes = num_signal_names * sizeof (char *);
+ if ((sys_siglist = (char **) malloc (nbytes)) != NULL)
+ {
+ memset (sys_siglist, 0, nbytes);
+ sys_nsig = num_signal_names;
+ for (eip = signal_table; eip -> name != NULL; eip++)
+ {
+ sys_siglist[eip -> value] = eip -> msg;
+ }
+ }
+ }
+
+#endif
+
+}
+
+
+/*
+
+NAME
+
+ signo_max -- return the max signo value
+
+SYNOPSIS
+
+ int signo_max ();
+
+DESCRIPTION
+
+ Returns the maximum signo value for which a corresponding symbolic
+ name or message is available. Note that in the case where
+ we use the sys_siglist supplied by the system, it is possible for
+ there to be more symbolic names than messages, or vice versa.
+ In fact, the manual page for psignal(3b) explicitly warns that one
+ should check the size of the table (NSIG) before indexing it,
+ since new signal codes may be added to the system before they are
+ added to the table. Thus NSIG might be smaller than value
+ implied by the largest signo value defined in <signal.h>.
+
+ We return the maximum value that can be used to obtain a meaningful
+ symbolic name or message.
+
+*/
+
+int
+signo_max ()
+{
+ int maxsize;
+
+ if (signal_names == NULL)
+ {
+ init_signal_tables ();
+ }
+ maxsize = MAX (sys_nsig, num_signal_names);
+ return (maxsize - 1);
+}
+
+
+/*
+
+NAME
+
+ strsignal -- map a signal number to a signal message string
+
+SYNOPSIS
+
+ char *strsignal (int signo)
+
+DESCRIPTION
+
+ Maps an signal number to an signal message string, the contents of
+ which are implementation defined. On systems which have the external
+ variable sys_siglist, these strings will be the same as the ones used
+ by psignal().
+
+ If the supplied signal number is within the valid range of indices
+ for the sys_siglist, but no message is available for the particular
+ signal number, then returns the string "Signal NUM", where NUM is the
+ signal number.
+
+ If the supplied signal number is not a valid index into sys_siglist,
+ returns NULL.
+
+ The returned string is only guaranteed to be valid only until the
+ next call to strsignal.
+
+*/
+
+char *
+strsignal (signo)
+ int signo;
+{
+ char *msg;
+ static char buf[32];
+
+#ifdef NEED_sys_siglist
+
+ if (signal_names == NULL)
+ {
+ init_signal_tables ();
+ }
+
+#endif
+
+ if ((signo < 0) || (signo >= sys_nsig))
+ {
+ /* Out of range, just return NULL */
+ msg = NULL;
+ }
+ else if ((sys_siglist == NULL) || (sys_siglist[signo] == NULL))
+ {
+ /* In range, but no sys_siglist or no entry at this index. */
+ sprintf (buf, "Signal %d", signo);
+ msg = buf;
+ }
+ else
+ {
+ /* In range, and a valid message. Just return the message. */
+ msg = (char*)sys_siglist[signo];
+ }
+
+ return (msg);
+}
+
+
+/*
+
+NAME
+
+ strsigno -- map an signal number to a symbolic name string
+
+SYNOPSIS
+
+ char *strsigno (int signo)
+
+DESCRIPTION
+
+ Given an signal number, returns a pointer to a string containing
+ the symbolic name of that signal number, as found in <signal.h>.
+
+ If the supplied signal number is within the valid range of indices
+ for symbolic names, but no name is available for the particular
+ signal number, then returns the string "Signal NUM", where NUM is
+ the signal number.
+
+ If the supplied signal number is not within the range of valid
+ indices, then returns NULL.
+
+BUGS
+
+ The contents of the location pointed to are only guaranteed to be
+ valid until the next call to strsigno.
+
+*/
+
+char *
+strsigno (signo)
+ int signo;
+{
+ char *name;
+ static char buf[32];
+
+ if (signal_names == NULL)
+ {
+ init_signal_tables ();
+ }
+
+ if ((signo < 0) || (signo >= num_signal_names))
+ {
+ /* Out of range, just return NULL */
+ name = NULL;
+ }
+ else if ((signal_names == NULL) || (signal_names[signo] == NULL))
+ {
+ /* In range, but no signal_names or no entry at this index. */
+ sprintf (buf, "Signal %d", signo);
+ name = buf;
+ }
+ else
+ {
+ /* In range, and a valid name. Just return the name. */
+ name = signal_names[signo];
+ }
+
+ return (name);
+}
+
+
+/*
+
+NAME
+
+ strtosigno -- map a symbolic signal name to a numeric value
+
+SYNOPSIS
+
+ int strtosigno (char *name)
+
+DESCRIPTION
+
+ Given the symbolic name of a signal, map it to a signal number.
+ If no translation is found, returns 0.
+
+*/
+
+int
+strtosigno (name)
+ char *name;
+{
+ int signo = 0;
+
+ if (name != NULL)
+ {
+ if (signal_names == NULL)
+ {
+ init_signal_tables ();
+ }
+ for (signo = 0; signo < num_signal_names; signo++)
+ {
+ if ((signal_names[signo] != NULL) &&
+ (strcmp (name, signal_names[signo]) == 0))
+ {
+ break;
+ }
+ }
+ if (signo == num_signal_names)
+ {
+ signo = 0;
+ }
+ }
+ return (signo);
+}
+
+
+/*
+
+NAME
+
+ psignal -- print message about signal to stderr
+
+SYNOPSIS
+
+ void psignal (unsigned signo, char *message);
+
+DESCRIPTION
+
+ Print to the standard error the message, followed by a colon,
+ followed by the description of the signal specified by signo,
+ followed by a newline.
+*/
+
+#ifdef NEED_psignal
+
+void
+psignal (signo, message)
+ unsigned signo;
+ char *message;
+{
+ if (signal_names == NULL)
+ {
+ init_signal_tables ();
+ }
+ if ((signo <= 0) || (signo >= sys_nsig))
+ {
+ fprintf (stderr, "%s: unknown signal\n", message);
+ }
+ else
+ {
+ fprintf (stderr, "%s: %s\n", message, sys_siglist[signo]);
+ }
+}
+
+#endif /* NEED_psignal */
+
+
+/* A simple little main that does nothing but print all the signal translations
+ if MAIN is defined and this file is compiled and linked. */
+
+#ifdef MAIN
+
+main ()
+{
+ int signo;
+ int maxsigno;
+ char *name;
+ char *msg;
+ char *strsigno ();
+ char *strsignal ();
+
+ maxsigno = signo_max ();
+ printf ("%d entries in names table.\n", num_signal_names);
+ printf ("%d entries in messages table.\n", sys_nsig);
+ printf ("%d is max useful index.\n", maxsigno);
+
+ /* Keep printing values until we get to the end of *both* tables, not
+ *either* table. Note that knowing the maximum useful index does *not*
+ relieve us of the responsibility of testing the return pointer for
+ NULL. */
+
+ for (signo = 0; signo <= maxsigno; signo++)
+ {
+ name = strsigno (signo);
+ name = (name == NULL) ? "<NULL>" : name;
+ msg = strsignal (signo);
+ msg = (msg == NULL) ? "<NULL>" : msg;
+ printf ("%-4d%-18s%s\n", signo, name, msg);
+ }
+}
+
+#endif