]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/strsignal.c
gcj.texi: Fixed gcj invocation example so that it compiles.
[thirdparty/gcc.git] / libiberty / strsignal.c
CommitLineData
6599da04
JM
1/* Extended support for using signal values.
2 Written by Fred Fish. fnf@cygnus.com
3 This file is in the public domain. */
4
5#include "ansidecl.h"
6#include "libiberty.h"
7
8#include "config.h"
9
10/* We need to declare sys_siglist, because even if the system provides
11 it we can't assume that it is declared in <signal.h> (for example,
12 SunOS provides sys_siglist, but it does not declare it in any
13 header file). fHowever, we can't declare sys_siglist portably,
14 because on some systems it is declared with const and on some
15 systems it is declared without const. If we were using autoconf,
16 we could work out the right declaration. Until, then we just
17 ignore any declaration in the system header files, and always
18 declare it ourselves. With luck, this will always work. */
19#define sys_siglist no_such_symbol
473c2d0b 20#define sys_nsig sys_nsig__no_such_symbol
6599da04
JM
21
22#include <stdio.h>
23#include <signal.h>
24
25/* Routines imported from standard C runtime libraries. */
26
d11ec6f0
ZW
27#ifdef HAVE_STDLIB_H
28#include <stdlib.h>
29#else
30extern PTR malloc ();
31#endif
32
33#ifdef HAVE_STRING_H
34#include <string.h>
35#else
36extern PTR memset ();
37#endif
6599da04
JM
38
39/* Undefine the macro we used to hide the definition of sys_siglist
40 found in the system header files. */
41#undef sys_siglist
473c2d0b 42#undef sys_nsig
6599da04
JM
43
44#ifndef NULL
45# ifdef __STDC__
46# define NULL (void *) 0
47# else
48# define NULL 0
49# endif
50#endif
51
52#ifndef MAX
53# define MAX(a,b) ((a) > (b) ? (a) : (b))
54#endif
55
56static void init_signal_tables PARAMS ((void));
57
58/* Translation table for signal values.
59
60 Note that this table is generally only accessed when it is used at runtime
61 to initialize signal name and message tables that are indexed by signal
62 value.
63
64 Not all of these signals will exist on all systems. This table is the only
65 thing that should have to be updated as new signal numbers are introduced.
66 It's sort of ugly, but at least its portable. */
67
68struct signal_info
69{
0be6abca
KG
70 const int value; /* The numeric value from <signal.h> */
71 const char *const name; /* The equivalent symbolic value */
3affd5f0 72#ifndef HAVE_SYS_SIGLIST
0be6abca 73 const char *const msg; /* Short message about this value */
6599da04
JM
74#endif
75};
76
3affd5f0 77#ifndef HAVE_SYS_SIGLIST
6599da04
JM
78# define ENTRY(value, name, msg) {value, name, msg}
79#else
80# define ENTRY(value, name, msg) {value, name}
81#endif
82
83static const struct signal_info signal_table[] =
84{
85#if defined (SIGHUP)
86 ENTRY(SIGHUP, "SIGHUP", "Hangup"),
87#endif
88#if defined (SIGINT)
89 ENTRY(SIGINT, "SIGINT", "Interrupt"),
90#endif
91#if defined (SIGQUIT)
92 ENTRY(SIGQUIT, "SIGQUIT", "Quit"),
93#endif
94#if defined (SIGILL)
95 ENTRY(SIGILL, "SIGILL", "Illegal instruction"),
96#endif
97#if defined (SIGTRAP)
98 ENTRY(SIGTRAP, "SIGTRAP", "Trace/breakpoint trap"),
99#endif
100/* Put SIGIOT before SIGABRT, so that if SIGIOT==SIGABRT then SIGABRT
101 overrides SIGIOT. SIGABRT is in ANSI and POSIX.1, and SIGIOT isn't. */
102#if defined (SIGIOT)
103 ENTRY(SIGIOT, "SIGIOT", "IOT trap"),
104#endif
105#if defined (SIGABRT)
106 ENTRY(SIGABRT, "SIGABRT", "Aborted"),
107#endif
108#if defined (SIGEMT)
109 ENTRY(SIGEMT, "SIGEMT", "Emulation trap"),
110#endif
111#if defined (SIGFPE)
112 ENTRY(SIGFPE, "SIGFPE", "Arithmetic exception"),
113#endif
114#if defined (SIGKILL)
115 ENTRY(SIGKILL, "SIGKILL", "Killed"),
116#endif
117#if defined (SIGBUS)
118 ENTRY(SIGBUS, "SIGBUS", "Bus error"),
119#endif
120#if defined (SIGSEGV)
121 ENTRY(SIGSEGV, "SIGSEGV", "Segmentation fault"),
122#endif
123#if defined (SIGSYS)
124 ENTRY(SIGSYS, "SIGSYS", "Bad system call"),
125#endif
126#if defined (SIGPIPE)
127 ENTRY(SIGPIPE, "SIGPIPE", "Broken pipe"),
128#endif
129#if defined (SIGALRM)
130 ENTRY(SIGALRM, "SIGALRM", "Alarm clock"),
131#endif
132#if defined (SIGTERM)
133 ENTRY(SIGTERM, "SIGTERM", "Terminated"),
134#endif
135#if defined (SIGUSR1)
136 ENTRY(SIGUSR1, "SIGUSR1", "User defined signal 1"),
137#endif
138#if defined (SIGUSR2)
139 ENTRY(SIGUSR2, "SIGUSR2", "User defined signal 2"),
140#endif
141/* Put SIGCLD before SIGCHLD, so that if SIGCLD==SIGCHLD then SIGCHLD
142 overrides SIGCLD. SIGCHLD is in POXIX.1 */
143#if defined (SIGCLD)
144 ENTRY(SIGCLD, "SIGCLD", "Child status changed"),
145#endif
146#if defined (SIGCHLD)
147 ENTRY(SIGCHLD, "SIGCHLD", "Child status changed"),
148#endif
149#if defined (SIGPWR)
150 ENTRY(SIGPWR, "SIGPWR", "Power fail/restart"),
151#endif
152#if defined (SIGWINCH)
153 ENTRY(SIGWINCH, "SIGWINCH", "Window size changed"),
154#endif
155#if defined (SIGURG)
156 ENTRY(SIGURG, "SIGURG", "Urgent I/O condition"),
157#endif
158#if defined (SIGIO)
159 /* "I/O pending" has also been suggested, but is misleading since the
160 signal only happens when the process has asked for it, not everytime
161 I/O is pending. */
162 ENTRY(SIGIO, "SIGIO", "I/O possible"),
163#endif
164#if defined (SIGPOLL)
165 ENTRY(SIGPOLL, "SIGPOLL", "Pollable event occurred"),
166#endif
167#if defined (SIGSTOP)
168 ENTRY(SIGSTOP, "SIGSTOP", "Stopped (signal)"),
169#endif
170#if defined (SIGTSTP)
171 ENTRY(SIGTSTP, "SIGTSTP", "Stopped (user)"),
172#endif
173#if defined (SIGCONT)
174 ENTRY(SIGCONT, "SIGCONT", "Continued"),
175#endif
176#if defined (SIGTTIN)
177 ENTRY(SIGTTIN, "SIGTTIN", "Stopped (tty input)"),
178#endif
179#if defined (SIGTTOU)
180 ENTRY(SIGTTOU, "SIGTTOU", "Stopped (tty output)"),
181#endif
182#if defined (SIGVTALRM)
183 ENTRY(SIGVTALRM, "SIGVTALRM", "Virtual timer expired"),
184#endif
185#if defined (SIGPROF)
186 ENTRY(SIGPROF, "SIGPROF", "Profiling timer expired"),
187#endif
188#if defined (SIGXCPU)
189 ENTRY(SIGXCPU, "SIGXCPU", "CPU time limit exceeded"),
190#endif
191#if defined (SIGXFSZ)
192 ENTRY(SIGXFSZ, "SIGXFSZ", "File size limit exceeded"),
193#endif
194#if defined (SIGWIND)
195 ENTRY(SIGWIND, "SIGWIND", "SIGWIND"),
196#endif
197#if defined (SIGPHONE)
198 ENTRY(SIGPHONE, "SIGPHONE", "SIGPHONE"),
199#endif
200#if defined (SIGLOST)
201 ENTRY(SIGLOST, "SIGLOST", "Resource lost"),
202#endif
203#if defined (SIGWAITING)
204 ENTRY(SIGWAITING, "SIGWAITING", "Process's LWPs are blocked"),
205#endif
206#if defined (SIGLWP)
207 ENTRY(SIGLWP, "SIGLWP", "Signal LWP"),
208#endif
209#if defined (SIGDANGER)
210 ENTRY(SIGDANGER, "SIGDANGER", "Swap space dangerously low"),
211#endif
212#if defined (SIGGRANT)
213 ENTRY(SIGGRANT, "SIGGRANT", "Monitor mode granted"),
214#endif
215#if defined (SIGRETRACT)
216 ENTRY(SIGRETRACT, "SIGRETRACT", "Need to relinguish monitor mode"),
217#endif
218#if defined (SIGMSG)
219 ENTRY(SIGMSG, "SIGMSG", "Monitor mode data available"),
220#endif
221#if defined (SIGSOUND)
222 ENTRY(SIGSOUND, "SIGSOUND", "Sound completed"),
223#endif
224#if defined (SIGSAK)
225 ENTRY(SIGSAK, "SIGSAK", "Secure attention"),
226#endif
227 ENTRY(0, NULL, NULL)
228};
229
230/* Translation table allocated and initialized at runtime. Indexed by the
231 signal value to find the equivalent symbolic value. */
232
233static const char **signal_names;
234static int num_signal_names = 0;
235
236/* Translation table allocated and initialized at runtime, if it does not
237 already exist in the host environment. Indexed by the signal value to find
238 the descriptive string.
239
240 We don't export it for use in other modules because even though it has the
241 same name, it differs from other implementations in that it is dynamically
242 initialized rather than statically initialized. */
243
3affd5f0 244#ifndef HAVE_SYS_SIGLIST
6599da04
JM
245
246static int sys_nsig;
247static const char **sys_siglist;
248
249#else
250
e7757d69 251#ifdef NSIG
6599da04 252static int sys_nsig = NSIG;
e7757d69
JL
253#else
254#ifdef _NSIG
435bba3a 255static int sys_nsig = _NSIG;
e7757d69
JL
256#endif
257#endif
6599da04
JM
258extern const char * const sys_siglist[];
259
260#endif
261
262
263/*
264
265NAME
266
267 init_signal_tables -- initialize the name and message tables
268
269SYNOPSIS
270
271 static void init_signal_tables ();
272
273DESCRIPTION
274
275 Using the signal_table, which is initialized at compile time, generate
276 the signal_names and the sys_siglist (if needed) tables, which are
277 indexed at runtime by a specific signal value.
278
279BUGS
280
281 The initialization of the tables may fail under low memory conditions,
282 in which case we don't do anything particularly useful, but we don't
283 bomb either. Who knows, it might succeed at a later point if we free
284 some memory in the meantime. In any case, the other routines know
285 how to deal with lack of a table after trying to initialize it. This
286 may or may not be considered to be a bug, that we don't specifically
287 warn about this particular failure mode.
288
289*/
290
291static void
292init_signal_tables ()
293{
294 const struct signal_info *eip;
295 int nbytes;
296
297 /* If we haven't already scanned the signal_table once to find the maximum
298 signal value, then go find it now. */
299
300 if (num_signal_names == 0)
301 {
302 for (eip = signal_table; eip -> name != NULL; eip++)
303 {
304 if (eip -> value >= num_signal_names)
305 {
306 num_signal_names = eip -> value + 1;
307 }
308 }
309 }
310
311 /* Now attempt to allocate the signal_names table, zero it out, and then
312 initialize it from the statically initialized signal_table. */
313
314 if (signal_names == NULL)
315 {
316 nbytes = num_signal_names * sizeof (char *);
317 if ((signal_names = (const char **) malloc (nbytes)) != NULL)
318 {
319 memset (signal_names, 0, nbytes);
320 for (eip = signal_table; eip -> name != NULL; eip++)
321 {
322 signal_names[eip -> value] = eip -> name;
323 }
324 }
325 }
326
3affd5f0 327#ifndef HAVE_SYS_SIGLIST
6599da04
JM
328
329 /* Now attempt to allocate the sys_siglist table, zero it out, and then
330 initialize it from the statically initialized signal_table. */
331
332 if (sys_siglist == NULL)
333 {
334 nbytes = num_signal_names * sizeof (char *);
335 if ((sys_siglist = (const char **) malloc (nbytes)) != NULL)
336 {
337 memset (sys_siglist, 0, nbytes);
338 sys_nsig = num_signal_names;
339 for (eip = signal_table; eip -> name != NULL; eip++)
340 {
341 sys_siglist[eip -> value] = eip -> msg;
342 }
343 }
344 }
345
346#endif
347
348}
349
350
351/*
352
5bed56d9 353@deftypefn Extension int signo_max (void)
6599da04 354
aac04c15
DD
355Returns the maximum signal value for which a corresponding symbolic
356name or message is available. Note that in the case where we use the
357@code{sys_siglist} supplied by the system, it is possible for there to
358be more symbolic names than messages, or vice versa. In fact, the
359manual page for @code{psignal(3b)} explicitly warns that one should
360check the size of the table (@code{NSIG}) before indexing it, since
361new signal codes may be added to the system before they are added to
362the table. Thus @code{NSIG} might be smaller than value implied by
363the largest signo value defined in @code{<signal.h>}.
6599da04 364
aac04c15
DD
365We return the maximum value that can be used to obtain a meaningful
366symbolic name or message.
6599da04 367
aac04c15 368@end deftypefn
6599da04
JM
369
370*/
371
372int
373signo_max ()
374{
375 int maxsize;
376
377 if (signal_names == NULL)
378 {
379 init_signal_tables ();
380 }
381 maxsize = MAX (sys_nsig, num_signal_names);
382 return (maxsize - 1);
383}
384
385
386/*
387
aac04c15 388@deftypefn Supplemental {const char *} strsignal (int @var{signo})
6599da04 389
aac04c15
DD
390Maps an signal number to an signal message string, the contents of
391which are implementation defined. On systems which have the external
392variable @code{sys_siglist}, these strings will be the same as the
393ones used by @code{psignal()}.
6599da04 394
aac04c15
DD
395If the supplied signal number is within the valid range of indices for
396the @code{sys_siglist}, but no message is available for the particular
397signal number, then returns the string @samp{Signal @var{num}}, where
398@var{num} is the signal number.
6599da04 399
aac04c15
DD
400If the supplied signal number is not a valid index into
401@code{sys_siglist}, returns @code{NULL}.
6599da04 402
aac04c15
DD
403The returned string is only guaranteed to be valid only until the next
404call to @code{strsignal}.
6599da04 405
aac04c15 406@end deftypefn
6599da04
JM
407
408*/
409
3affd5f0 410#ifndef HAVE_STRSIGNAL
6599da04
JM
411
412const char *
413strsignal (signo)
414 int signo;
415{
416 const char *msg;
417 static char buf[32];
418
3affd5f0 419#ifndef HAVE_SYS_SIGLIST
6599da04
JM
420
421 if (signal_names == NULL)
422 {
423 init_signal_tables ();
424 }
425
426#endif
427
428 if ((signo < 0) || (signo >= sys_nsig))
429 {
430 /* Out of range, just return NULL */
431 msg = NULL;
432 }
433 else if ((sys_siglist == NULL) || (sys_siglist[signo] == NULL))
434 {
435 /* In range, but no sys_siglist or no entry at this index. */
436 sprintf (buf, "Signal %d", signo);
437 msg = (const char *) buf;
438 }
439 else
440 {
441 /* In range, and a valid message. Just return the message. */
442 msg = (const char *) sys_siglist[signo];
443 }
444
445 return (msg);
446}
447
3affd5f0 448#endif /* ! HAVE_STRSIGNAL */
6599da04
JM
449
450/*
451
aac04c15 452@deftypefn Extension {const char*} strsigno (int @var{signo})
6599da04 453
aac04c15
DD
454Given an signal number, returns a pointer to a string containing the
455symbolic name of that signal number, as found in @code{<signal.h>}.
6599da04 456
aac04c15
DD
457If the supplied signal number is within the valid range of indices for
458symbolic names, but no name is available for the particular signal
459number, then returns the string @samp{Signal @var{num}}, where
460@var{num} is the signal number.
6599da04 461
aac04c15
DD
462If the supplied signal number is not within the range of valid
463indices, then returns @code{NULL}.
6599da04 464
aac04c15
DD
465The contents of the location pointed to are only guaranteed to be
466valid until the next call to @code{strsigno}.
6599da04 467
aac04c15 468@end deftypefn
6599da04
JM
469
470*/
471
472const char *
473strsigno (signo)
474 int signo;
475{
476 const char *name;
477 static char buf[32];
478
479 if (signal_names == NULL)
480 {
481 init_signal_tables ();
482 }
483
484 if ((signo < 0) || (signo >= num_signal_names))
485 {
486 /* Out of range, just return NULL */
487 name = NULL;
488 }
489 else if ((signal_names == NULL) || (signal_names[signo] == NULL))
490 {
491 /* In range, but no signal_names or no entry at this index. */
492 sprintf (buf, "Signal %d", signo);
493 name = (const char *) buf;
494 }
495 else
496 {
497 /* In range, and a valid name. Just return the name. */
498 name = signal_names[signo];
499 }
500
501 return (name);
502}
503
504
505/*
506
aac04c15 507@deftypefn Extension int strtosigno (const char *@var{name})
6599da04 508
aac04c15
DD
509Given the symbolic name of a signal, map it to a signal number. If no
510translation is found, returns 0.
6599da04 511
aac04c15 512@end deftypefn
6599da04
JM
513
514*/
515
516int
517strtosigno (name)
518 const char *name;
519{
520 int signo = 0;
521
522 if (name != NULL)
523 {
524 if (signal_names == NULL)
525 {
526 init_signal_tables ();
527 }
528 for (signo = 0; signo < num_signal_names; signo++)
529 {
530 if ((signal_names[signo] != NULL) &&
531 (strcmp (name, signal_names[signo]) == 0))
532 {
533 break;
534 }
535 }
536 if (signo == num_signal_names)
537 {
538 signo = 0;
539 }
540 }
541 return (signo);
542}
543
544
545/*
546
aac04c15 547@deftypefn Supplemental void psignal (unsigned @var{signo}, char *@var{message})
6599da04 548
aac04c15
DD
549Print @var{message} to the standard error, followed by a colon,
550followed by the description of the signal specified by @var{signo},
551followed by a newline.
6599da04 552
aac04c15 553@end deftypefn
6599da04 554
6599da04
JM
555*/
556
3affd5f0 557#ifndef HAVE_PSIGNAL
6599da04
JM
558
559void
560psignal (signo, message)
561 unsigned signo;
562 char *message;
563{
564 if (signal_names == NULL)
565 {
566 init_signal_tables ();
567 }
568 if ((signo <= 0) || (signo >= sys_nsig))
569 {
570 fprintf (stderr, "%s: unknown signal\n", message);
571 }
572 else
573 {
574 fprintf (stderr, "%s: %s\n", message, sys_siglist[signo]);
575 }
576}
577
3affd5f0 578#endif /* ! HAVE_PSIGNAL */
6599da04
JM
579
580
581/* A simple little main that does nothing but print all the signal translations
582 if MAIN is defined and this file is compiled and linked. */
583
584#ifdef MAIN
585
586#include <stdio.h>
587
588int
589main ()
590{
591 int signo;
592 int maxsigno;
593 const char *name;
594 const char *msg;
595
596 maxsigno = signo_max ();
597 printf ("%d entries in names table.\n", num_signal_names);
598 printf ("%d entries in messages table.\n", sys_nsig);
599 printf ("%d is max useful index.\n", maxsigno);
600
601 /* Keep printing values until we get to the end of *both* tables, not
602 *either* table. Note that knowing the maximum useful index does *not*
603 relieve us of the responsibility of testing the return pointer for
604 NULL. */
605
606 for (signo = 0; signo <= maxsigno; signo++)
607 {
608 name = strsigno (signo);
609 name = (name == NULL) ? "<NULL>" : name;
610 msg = strsignal (signo);
611 msg = (msg == NULL) ? "<NULL>" : msg;
612 printf ("%-4d%-18s%s\n", signo, name, msg);
613 }
614
615 return 0;
616}
617
618#endif