darling-gdb/gdb/utils.c
2012-06-03 15:36:31 +01:00

657 lines
13 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* General utility routines for GDB, the GNU debugger.
Copyright (C) 1986 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include <stdio.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include "defs.h"
#include "param.h"
#ifdef HAVE_TERMIO
#include <termio.h>
#endif
void error ();
void fatal ();
/* Chain of cleanup actions established with make_cleanup,
to be executed if an error happens. */
static struct cleanup *cleanup_chain;
/* Nonzero means a quit has been requested. */
int quit_flag;
/* Nonzero means quit immediately if Control-C is typed now,
rather than waiting until QUIT is executed. */
int immediate_quit;
/* Add a new cleanup to the cleanup_chain,
and return the previous chain pointer
to be passed later to do_cleanups or discard_cleanups.
Args are FUNCTION to clean up with, and ARG to pass to it. */
struct cleanup *
make_cleanup (function, arg)
void (*function) ();
int arg;
{
register struct cleanup *new
= (struct cleanup *) xmalloc (sizeof (struct cleanup));
register struct cleanup *old_chain = cleanup_chain;
new->next = cleanup_chain;
new->function = function;
new->arg = arg;
cleanup_chain = new;
return old_chain;
}
/* Discard cleanups and do the actions they describe
until we get back to the point OLD_CHAIN in the cleanup_chain. */
void
do_cleanups (old_chain)
register struct cleanup *old_chain;
{
register struct cleanup *ptr;
while ((ptr = cleanup_chain) != old_chain)
{
(*ptr->function) (ptr->arg);
cleanup_chain = ptr->next;
free (ptr);
}
}
/* Discard cleanups, not doing the actions they describe,
until we get back to the point OLD_CHAIN in the cleanup_chain. */
void
discard_cleanups (old_chain)
register struct cleanup *old_chain;
{
register struct cleanup *ptr;
while ((ptr = cleanup_chain) != old_chain)
{
cleanup_chain = ptr->next;
free (ptr);
}
}
/* Set the cleanup_chain to 0, and return the old cleanup chain. */
struct cleanup *
save_cleanups ()
{
struct cleanup *old_chain = cleanup_chain;
cleanup_chain = 0;
return old_chain;
}
/* Restore the cleanup chain from a previously saved chain. */
void
restore_cleanups (chain)
struct cleanup *chain;
{
cleanup_chain = chain;
}
/* This function is useful for cleanups.
Do
foo = xmalloc (...);
old_chain = make_cleanup (free_current_contents, &foo);
to arrange to free the object thus allocated. */
void
free_current_contents (location)
char **location;
{
free (*location);
}
/* Generally useful subroutines used throughout the program. */
/* Like malloc but get error if no storage available. */
char *
xmalloc (size)
long size;
{
register char *val = (char *) malloc (size);
if (!val)
fatal ("virtual memory exhausted.", 0);
return val;
}
/* Like realloc but get error if no storage available. */
char *
xrealloc (ptr, size)
char *ptr;
long size;
{
register char *val = (char *) realloc (ptr, size);
if (!val)
fatal ("virtual memory exhausted.", 0);
return val;
}
/* Print the system error message for errno, and also mention STRING
as the file name for which the error was encountered.
Then return to command level. */
void
perror_with_name (string)
char *string;
{
extern int sys_nerr;
extern char *sys_errlist[];
extern int errno;
char *err;
char *combined;
if (errno < sys_nerr)
err = sys_errlist[errno];
else
err = "unknown error";
combined = (char *) alloca (strlen (err) + strlen (string) + 3);
strcpy (combined, string);
strcat (combined, ": ");
strcat (combined, err);
error ("%s.", combined);
}
/* Print the system error message for ERRCODE, and also mention STRING
as the file name for which the error was encountered. */
void
print_sys_errmsg (string, errcode)
char *string;
int errcode;
{
extern int sys_nerr;
extern char *sys_errlist[];
char *err;
char *combined;
if (errcode < sys_nerr)
err = sys_errlist[errcode];
else
err = "unknown error";
combined = (char *) alloca (strlen (err) + strlen (string) + 3);
strcpy (combined, string);
strcat (combined, ": ");
strcat (combined, err);
printf ("%s.\n", combined);
}
void
quit ()
{
fflush (stdout);
#ifdef HAVE_TERMIO
ioctl (fileno (stdout), TCFLSH, 1);
#else /* not HAVE_TERMIO */
ioctl (fileno (stdout), TIOCFLUSH, 0);
#endif /* not HAVE_TERMIO */
#ifdef TIOCGPGRP
error ("Quit");
#else
error ("Quit (expect signal %d when inferior is resumed)", SIGINT);
#endif /* TIOCGPGRP */
}
/* Control C comes here */
void
request_quit ()
{
quit_flag = 1;
#ifdef USG
/* Restore the signal handler */
signal(SIGINT, request_quit);
#endif
if (immediate_quit)
quit ();
}
/* Print an error message and return to command level.
STRING is the error message, used as a fprintf string,
and ARG is passed as an argument to it. */
void
error (string, arg1, arg2, arg3)
char *string;
int arg1, arg2, arg3;
{
fflush (stdout);
fprintf (stderr, string, arg1, arg2, arg3);
fprintf (stderr, "\n");
return_to_top_level ();
}
/* Print an error message and exit reporting failure.
This is for a error that we cannot continue from.
STRING and ARG are passed to fprintf. */
void
fatal (string, arg)
char *string;
int arg;
{
fprintf (stderr, "gdb: ");
fprintf (stderr, string, arg);
fprintf (stderr, "\n");
exit (1);
}
/* Make a copy of the string at PTR with SIZE characters
(and add a null character at the end in the copy).
Uses malloc to get the space. Returns the address of the copy. */
char *
savestring (ptr, size)
char *ptr;
int size;
{
register char *p = (char *) xmalloc (size + 1);
bcopy (ptr, p, size);
p[size] = 0;
return p;
}
char *
concat (s1, s2, s3)
char *s1, *s2, *s3;
{
register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1;
register char *val = (char *) xmalloc (len);
strcpy (val, s1);
strcat (val, s2);
strcat (val, s3);
return val;
}
void
print_spaces (n, file)
register int n;
register FILE *file;
{
while (n-- > 0)
fputc (' ', file);
}
/* Ask user a y-or-n question and return 1 iff answer is yes.
Takes three args which are given to printf to print the question.
The first, a control string, should end in "? ".
It should not say how to answer, because we do that. */
int
query (ctlstr, arg1, arg2)
char *ctlstr;
{
register int answer;
/* Automatically answer "yes" if input is not from a terminal. */
if (!input_from_terminal_p ())
return 1;
while (1)
{
printf (ctlstr, arg1, arg2);
printf ("(y or n) ");
fflush (stdout);
answer = fgetc (stdin);
clearerr (stdin); /* in case of C-d */
if (answer != '\n')
while (fgetc (stdin) != '\n') clearerr (stdin);
if (answer >= 'a')
answer -= 040;
if (answer == 'Y')
return 1;
if (answer == 'N')
return 0;
printf ("Please answer y or n.\n");
}
}
/* Parse a C escape sequence. STRING_PTR points to a variable
containing a pointer to the string to parse. That pointer
is updated past the characters we use. The value of the
escape sequence is returned.
A negative value means the sequence \ newline was seen,
which is supposed to be equivalent to nothing at all.
If \ is followed by a null character, we return a negative
value and leave the string pointer pointing at the null character.
If \ is followed by 000, we return 0 and leave the string pointer
after the zeros. A value of 0 does not mean end of string. */
int
parse_escape (string_ptr)
char **string_ptr;
{
register int c = *(*string_ptr)++;
switch (c)
{
case 'a':
return '\a';
case 'b':
return '\b';
case 'e':
return 033;
case 'f':
return '\f';
case 'n':
return '\n';
case 'r':
return '\r';
case 't':
return '\t';
case 'v':
return '\v';
case '\n':
return -2;
case 0:
(*string_ptr)--;
return 0;
case '^':
c = *(*string_ptr)++;
if (c == '\\')
c = parse_escape (string_ptr);
if (c == '?')
return 0177;
return (c & 0200) | (c & 037);
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
{
register int i = c - '0';
register int count = 0;
while (++count < 3)
{
if ((c = *(*string_ptr)++) >= '0' && c <= '7')
{
i *= 8;
i += c - '0';
}
else
{
(*string_ptr)--;
break;
}
}
return i;
}
default:
return c;
}
}
/* Print the character CH on STREAM as part of the contents
of a literal string whose delimiter is QUOTER. */
void
printchar (ch, stream, quoter)
unsigned char ch;
FILE *stream;
int quoter;
{
register int c = ch;
if (c < 040 || c >= 0177)
{
if (c == '\n')
fprintf (stream, "\\n");
else if (c == '\b')
fprintf (stream, "\\b");
else if (c == '\t')
fprintf (stream, "\\t");
else if (c == '\f')
fprintf (stream, "\\f");
else if (c == '\r')
fprintf (stream, "\\r");
else if (c == 033)
fprintf (stream, "\\e");
else if (c == '\a')
fprintf (stream, "\\a");
else
fprintf (stream, "\\%03o", c);
}
else
{
if (c == '\\' || c == quoter)
fputc ('\\', stream);
fputc (c, stream);
}
}
#ifdef USG
bcopy (from, to, count)
char *from, *to;
{
memcpy (to, from, count);
}
bcmp (from, to, count)
{
return (memcmp (to, from, count));
}
bzero (to, count)
char *to;
{
while (count--)
*to++ = 0;
}
getwd (buf)
char *buf;
{
getcwd (buf, MAXPATHLEN);
}
char *
index (s, c)
char *s;
{
char *strchr ();
return strchr (s, c);
}
char *
rindex (s, c)
char *s;
{
char *strrchr ();
return strrchr (s, c);
}
/* Queue routines */
struct queue {
struct queue *forw;
struct queue *back;
};
insque (item, after)
struct queue *item;
struct queue *after;
{
item->forw = after->forw;
after->forw->back = item;
item->back = after;
after->forw = item;
}
remque (item)
struct queue *item;
{
item->forw->back = item->back;
item->back->forw = item->forw;
}
/*
* There is too much variation in Sys V signal numbers and names, so
* we must initialize them at runtime. If C provided a way to initialize
* an array based on subscript and value, this would not be necessary.
*/
static char undoc[] = "(undocumented)";
char *sys_siglist[NSIG];
_initialize_utils()
{
int i;
for (i = 0; i < NSIG; i++)
sys_siglist[i] = undoc;
#ifdef SIGHUP
sys_siglist[SIGHUP ] = "SIGHUP";
#endif
#ifdef SIGINT
sys_siglist[SIGINT ] = "SIGINT";
#endif
#ifdef SIGQUIT
sys_siglist[SIGQUIT ] = "SIGQUIT";
#endif
#ifdef SIGILL
sys_siglist[SIGILL ] = "SIGILL";
#endif
#ifdef SIGTRAP
sys_siglist[SIGTRAP ] = "SIGTRAP";
#endif
#ifdef SIGIOT
sys_siglist[SIGIOT ] = "SIGIOT";
#endif
#ifdef SIGEMT
sys_siglist[SIGEMT ] = "SIGEMT";
#endif
#ifdef SIGFPE
sys_siglist[SIGFPE ] = "SIGFPE";
#endif
#ifdef SIGKILL
sys_siglist[SIGKILL ] = "SIGKILL";
#endif
#ifdef SIGBUS
sys_siglist[SIGBUS ] = "SIGBUS";
#endif
#ifdef SIGSEGV
sys_siglist[SIGSEGV ] = "SIGSEGV";
#endif
#ifdef SIGSYS
sys_siglist[SIGSYS ] = "SIGSYS";
#endif
#ifdef SIGPIPE
sys_siglist[SIGPIPE ] = "SIGPIPE";
#endif
#ifdef SIGALRM
sys_siglist[SIGALRM ] = "SIGALRM";
#endif
#ifdef SIGTERM
sys_siglist[SIGTERM ] = "SIGTERM";
#endif
#ifdef SIGUSR1
sys_siglist[SIGUSR1 ] = "SIGUSR1";
#endif
#ifdef SIGUSR2
sys_siglist[SIGUSR2 ] = "SIGUSR2";
#endif
#ifdef SIGCLD
sys_siglist[SIGCLD ] = "SIGCLD";
#endif
#ifdef SIGCHLD
sys_siglist[SIGCHLD ] = "SIGCHLD";
#endif
#ifdef SIGPWR
sys_siglist[SIGPWR ] = "SIGPWR";
#endif
#ifdef SIGTSTP
sys_siglist[SIGTSTP ] = "SIGTSTP";
#endif
#ifdef SIGTTIN
sys_siglist[SIGTTIN ] = "SIGTTIN";
#endif
#ifdef SIGTTOU
sys_siglist[SIGTTOU ] = "SIGTTOU";
#endif
#ifdef SIGSTOP
sys_siglist[SIGSTOP ] = "SIGSTOP";
#endif
#ifdef SIGXCPU
sys_siglist[SIGXCPU ] = "SIGXCPU";
#endif
#ifdef SIGXFSZ
sys_siglist[SIGXFSZ ] = "SIGXFSZ";
#endif
#ifdef SIGVTALRM
sys_siglist[SIGVTALRM ] = "SIGVTALRM";
#endif
#ifdef SIGPROF
sys_siglist[SIGPROF ] = "SIGPROF";
#endif
#ifdef SIGWINCH
sys_siglist[SIGWINCH ] = "SIGWINCH";
#endif
#ifdef SIGCONT
sys_siglist[SIGCONT ] = "SIGCONT";
#endif
#ifdef SIGURG
sys_siglist[SIGURG ] = "SIGURG";
#endif
#ifdef SIGIO
sys_siglist[SIGIO ] = "SIGIO";
#endif
#ifdef SIGWIND
sys_siglist[SIGWIND ] = "SIGWIND";
#endif
#ifdef SIGPHONE
sys_siglist[SIGPHONE ] = "SIGPHONE";
#endif
#ifdef SIGPOLL
sys_siglist[SIGPOLL ] = "SIGPOLL";
#endif
}
#endif /* USG */