X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Futils.c;h=556486b635eef28c8466ccd907af9ee8645437c6;hb=0d5f99947baa22a5dda53be002c3885ffe311ca5;hp=3d820deae0b661527fd8eff1e287ceb59409426d;hpb=25d41031648fa41bc108e1a3c6794da69c8bdd0f;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/utils.c b/gdb/utils.c index 3d820deae0..556486b635 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -1,7 +1,7 @@ /* General utility routines for GDB, the GNU debugger. Copyright 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software + 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GDB. @@ -61,10 +61,6 @@ #include -#ifdef USE_MMALLOC -#include "mmalloc.h" -#endif - #ifdef NEED_DECLARATION_MALLOC extern PTR malloc (); /* OK: PTR */ #endif @@ -96,14 +92,11 @@ static void vfprintf_maybe_filtered (struct ui_file *, const char *, static void fputs_maybe_filtered (const char *, struct ui_file *, int); -#if defined (USE_MMALLOC) && !defined (NO_MMCHECK) -static void malloc_botch (void); -#endif +static void do_my_cleanups (struct cleanup **, struct cleanup *); static void prompt_for_continue (void); -static void set_width_command (char *, int, struct cmd_list_element *); - +static void set_screen_size (void); static void set_width (void); /* Chain of cleanup actions established with make_cleanup, @@ -267,9 +260,9 @@ struct cleanup * make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function, void *arg) { - register struct cleanup *new + struct cleanup *new = (struct cleanup *) xmalloc (sizeof (struct cleanup)); - register struct cleanup *old_chain = *pmy_chain; + struct cleanup *old_chain = *pmy_chain; new->next = *pmy_chain; new->function = function; @@ -283,40 +276,40 @@ make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function, until we get back to the point OLD_CHAIN in the cleanup_chain. */ void -do_cleanups (register struct cleanup *old_chain) +do_cleanups (struct cleanup *old_chain) { do_my_cleanups (&cleanup_chain, old_chain); } void -do_final_cleanups (register struct cleanup *old_chain) +do_final_cleanups (struct cleanup *old_chain) { do_my_cleanups (&final_cleanup_chain, old_chain); } void -do_run_cleanups (register struct cleanup *old_chain) +do_run_cleanups (struct cleanup *old_chain) { do_my_cleanups (&run_cleanup_chain, old_chain); } void -do_exec_cleanups (register struct cleanup *old_chain) +do_exec_cleanups (struct cleanup *old_chain) { do_my_cleanups (&exec_cleanup_chain, old_chain); } void -do_exec_error_cleanups (register struct cleanup *old_chain) +do_exec_error_cleanups (struct cleanup *old_chain) { do_my_cleanups (&exec_error_cleanup_chain, old_chain); } -void -do_my_cleanups (register struct cleanup **pmy_chain, - register struct cleanup *old_chain) +static void +do_my_cleanups (struct cleanup **pmy_chain, + struct cleanup *old_chain) { - register struct cleanup *ptr; + struct cleanup *ptr; while ((ptr = *pmy_chain) != old_chain) { *pmy_chain = ptr->next; /* Do this first incase recursion */ @@ -329,28 +322,28 @@ do_my_cleanups (register struct cleanup **pmy_chain, until we get back to the point OLD_CHAIN in the cleanup_chain. */ void -discard_cleanups (register struct cleanup *old_chain) +discard_cleanups (struct cleanup *old_chain) { discard_my_cleanups (&cleanup_chain, old_chain); } void -discard_final_cleanups (register struct cleanup *old_chain) +discard_final_cleanups (struct cleanup *old_chain) { discard_my_cleanups (&final_cleanup_chain, old_chain); } void -discard_exec_error_cleanups (register struct cleanup *old_chain) +discard_exec_error_cleanups (struct cleanup *old_chain) { discard_my_cleanups (&exec_error_cleanup_chain, old_chain); } void -discard_my_cleanups (register struct cleanup **pmy_chain, - register struct cleanup *old_chain) +discard_my_cleanups (struct cleanup **pmy_chain, + struct cleanup *old_chain) { - register struct cleanup *ptr; + struct cleanup *ptr; while ((ptr = *pmy_chain) != old_chain) { *pmy_chain = ptr->next; @@ -428,7 +421,6 @@ free_current_contents (void *ptr) In such cases, we may not be certain where the first cleanup is, unless we have a do-nothing one to always use as the base. */ -/* ARGSUSED */ void null_cleanup (void *arg) { @@ -578,7 +570,7 @@ vwarning (const char *string, va_list args) wrap_here (""); /* Force out any buffered output */ gdb_flush (gdb_stdout); if (warning_pre_print) - fprintf_unfiltered (gdb_stderr, warning_pre_print); + fputs_unfiltered (warning_pre_print, gdb_stderr); vfprintf_unfiltered (gdb_stderr, string, args); fprintf_unfiltered (gdb_stderr, "\n"); va_end (args); @@ -628,6 +620,38 @@ do_write (void *data, const char *buffer, long length_buffer) ui_file_write (data, buffer, length_buffer); } +/* Cause a silent error to occur. Any error message is recorded + though it is not issued. */ +NORETURN void +error_silent (const char *string, ...) +{ + va_list args; + struct ui_file *tmp_stream = mem_fileopen (); + va_start (args, string); + make_cleanup_ui_file_delete (tmp_stream); + vfprintf_unfiltered (tmp_stream, string, args); + /* Copy the stream into the GDB_LASTERR buffer. */ + ui_file_rewind (gdb_lasterr); + ui_file_put (tmp_stream, do_write, gdb_lasterr); + va_end (args); + + throw_exception (RETURN_ERROR); +} + +/* Output an error message including any pre-print text to gdb_stderr. */ +void +error_output_message (char *pre_print, char *msg) +{ + target_terminal_ours (); + wrap_here (""); /* Force out any buffered output */ + gdb_flush (gdb_stdout); + annotate_error_begin (); + if (pre_print) + fputs_filtered (pre_print, gdb_stderr); + fputs_filtered (msg, gdb_stderr); + fprintf_filtered (gdb_stderr, "\n"); +} + NORETURN void error_stream (struct ui_file *stream) { @@ -644,7 +668,7 @@ error_stream (struct ui_file *stream) gdb_flush (gdb_stdout); annotate_error_begin (); if (error_pre_print) - fprintf_filtered (gdb_stderr, error_pre_print); + fputs_filtered (error_pre_print, gdb_stderr); ui_file_put (stream, do_write, gdb_stderr); fprintf_filtered (gdb_stderr, "\n"); @@ -689,42 +713,49 @@ static void internal_vproblem (struct internal_problem *problem, const char *file, int line, const char *fmt, va_list ap) { - static char msg[] = "Recursive internal problem.\n"; static int dejavu; int quit_p; int dump_core_p; + char *reason; /* Don't allow infinite error/warning recursion. */ - switch (dejavu) - { - case 0: - dejavu = 1; - break; - case 1: - dejavu = 2; - fputs_unfiltered (msg, gdb_stderr); - abort (); /* NOTE: GDB has only three calls to abort(). */ - default: - dejavu = 3; - write (STDERR_FILENO, msg, sizeof (msg)); - exit (1); - } + { + static char msg[] = "Recursive internal problem.\n"; + switch (dejavu) + { + case 0: + dejavu = 1; + break; + case 1: + dejavu = 2; + fputs_unfiltered (msg, gdb_stderr); + abort (); /* NOTE: GDB has only three calls to abort(). */ + default: + dejavu = 3; + write (STDERR_FILENO, msg, sizeof (msg)); + exit (1); + } + } /* Try to get the message out and at the start of a new line. */ target_terminal_ours (); begin_line (); - /* The error/warning message. Format using a style similar to a - compiler error message. */ - fprintf_unfiltered (gdb_stderr, "%s:%d: %s: ", file, line, problem->name); - vfprintf_unfiltered (gdb_stderr, fmt, ap); - fputs_unfiltered ("\n", gdb_stderr); - - /* Provide more details so that the user knows that they are living - on the edge. */ - fprintf_unfiltered (gdb_stderr, "\ -A problem internal to GDB has been detected. Further\n\ -debugging may prove unreliable.\n"); + /* Create a string containing the full error/warning message. Need + to call query with this full string, as otherwize the reason + (error/warning) and question become separated. Format using a + style similar to a compiler error message. Include extra detail + so that the user knows that they are living on the edge. */ + { + char *msg; + xvasprintf (&msg, fmt, ap); + xasprintf (&reason, "\ +%s:%d: %s: %s\n\ +A problem internal to GDB has been detected,\n\ +further debugging may prove unreliable.", file, line, problem->name, msg); + xfree (msg); + make_cleanup (xfree, reason); + } switch (problem->should_quit) { @@ -732,7 +763,7 @@ debugging may prove unreliable.\n"); /* Default (yes/batch case) is to quit GDB. When in batch mode this lessens the likelhood of GDB going into an infinate loop. */ - quit_p = query ("Quit this debugging session? "); + quit_p = query ("%s\nQuit this debugging session? ", reason); break; case AUTO_BOOLEAN_TRUE: quit_p = 1; @@ -750,7 +781,7 @@ debugging may prove unreliable.\n"); /* Default (yes/batch case) is to dump core. This leaves a GDB `dropping' so that it is easier to see that something went wrong in GDB. */ - dump_core_p = query ("Create a core file of GDB? "); + dump_core_p = query ("%s\nCreate a core file of GDB? ", reason); break; break; case AUTO_BOOLEAN_TRUE: @@ -915,7 +946,7 @@ quit (void) /* Don't use *_filtered; we don't want to prompt the user to continue. */ if (quit_pre_print) - fprintf_unfiltered (gdb_stderr, quit_pre_print); + fputs_unfiltered (quit_pre_print, gdb_stderr); #ifdef __MSDOS__ /* No steenking SIGINT will ever be coming our way when the @@ -954,8 +985,6 @@ request_quit (int signo) /* Memory management stuff (malloc friends). */ -#if !defined (USE_MMALLOC) - static void * mmalloc (void *md, size_t size) { @@ -983,63 +1012,13 @@ mfree (void *md, void *ptr) free (ptr); /* NOTE: GDB's only call to free() */ } -#endif /* USE_MMALLOC */ - -#if !defined (USE_MMALLOC) || defined (NO_MMCHECK) - -void -init_malloc (void *md) -{ -} - -#else /* Have mmalloc and want corruption checking */ - -static void -malloc_botch (void) -{ - fprintf_unfiltered (gdb_stderr, "Memory corruption\n"); - internal_error (__FILE__, __LINE__, "failed internal consistency check"); -} - -/* Attempt to install hooks in mmalloc/mrealloc/mfree for the heap specified - by MD, to detect memory corruption. Note that MD may be NULL to specify - the default heap that grows via sbrk. - - Note that for freshly created regions, we must call mmcheckf prior to any - mallocs in the region. Otherwise, any region which was allocated prior to - installing the checking hooks, which is later reallocated or freed, will - fail the checks! The mmcheck function only allows initial hooks to be - installed before the first mmalloc. However, anytime after we have called - mmcheck the first time to install the checking hooks, we can call it again - to update the function pointer to the memory corruption handler. - - Returns zero on failure, non-zero on success. */ - -#ifndef MMCHECK_FORCE -#define MMCHECK_FORCE 0 -#endif - +/* This used to do something interesting with USE_MMALLOC. + * It can be retired any time. -- chastain 2004-01-19. */ void init_malloc (void *md) { - if (!mmcheckf (md, malloc_botch, MMCHECK_FORCE)) - { - /* Don't use warning(), which relies on current_target being set - to something other than dummy_target, until after - initialize_all_files(). */ - - fprintf_unfiltered - (gdb_stderr, - "warning: failed to install memory consistency checks; "); - fprintf_unfiltered (gdb_stderr, - "configuration should define NO_MMCHECK or MMCHECK_FORCE\n"); - } - - mmtrace (); } -#endif /* Have mmalloc and want corruption checking */ - /* Called when a memory allocation fails, with the number of bytes of memory requested in SIZE. */ @@ -1171,6 +1150,17 @@ xfree (void *ptr) /* Like asprintf/vasprintf but get an internal_error if the call fails. */ +char * +xstrprintf (const char *format, ...) +{ + char *ret; + va_list args; + va_start (args, format); + xvasprintf (&ret, format, args); + va_end (args); + return ret; +} + void xasprintf (char **ret, const char *format, ...) { @@ -1203,7 +1193,7 @@ xvasprintf (char **ret, const char *format, va_list ap) int myread (int desc, char *addr, int len) { - register int val; + int val; int orglen = len; while (len > 0) @@ -1226,7 +1216,7 @@ myread (int desc, char *addr, int len) char * savestring (const char *ptr, size_t size) { - register char *p = (char *) xmalloc (size + 1); + char *p = (char *) xmalloc (size + 1); memcpy (p, ptr, size); p[size] = 0; return p; @@ -1235,7 +1225,7 @@ savestring (const char *ptr, size_t size) char * msavestring (void *md, const char *ptr, size_t size) { - register char *p = (char *) xmmalloc (md, size + 1); + char *p = (char *) xmmalloc (md, size + 1); memcpy (p, ptr, size); p[size] = 0; return p; @@ -1248,7 +1238,7 @@ mstrsave (void *md, const char *ptr) } void -print_spaces (register int n, register struct ui_file *file) +print_spaces (int n, struct ui_file *file) { fputs_unfiltered (n_spaces (n), file); } @@ -1276,8 +1266,8 @@ int query (const char *ctlstr, ...) { va_list args; - register int answer; - register int ans2; + int answer; + int ans2; int retval; va_start (args, ctlstr); @@ -1381,7 +1371,7 @@ int parse_escape (char **string_ptr) { int target_char; - register int c = *(*string_ptr)++; + int c = *(*string_ptr)++; if (c_parse_backslash (c, &target_char)) return target_char; else @@ -1439,8 +1429,8 @@ parse_escape (char **string_ptr) case '6': case '7': { - register int i = c - '0'; - register int count = 0; + int i = c - '0'; + int count = 0; while (++count < 3) { c = (**string_ptr); @@ -1549,11 +1539,12 @@ fputstrn_unfiltered (const char *str, int n, int quoter, } - /* Number of lines per page or UINT_MAX if paging is disabled. */ static unsigned int lines_per_page; + /* Number of chars per line or UINT_MAX if line folding is disabled. */ static unsigned int chars_per_line; + /* Current count of lines printed on this page, chars on this line. */ static unsigned int lines_printed, chars_printed; @@ -1582,7 +1573,8 @@ static char *wrap_indent; static int wrap_column; -/* Inialize the lines and chars per page */ +/* Inialize the number of lines per page and chars per line. */ + void init_page_info (void) { @@ -1590,66 +1582,67 @@ init_page_info (void) if (!tui_get_command_dimension (&chars_per_line, &lines_per_page)) #endif { - /* These defaults will be used if we are unable to get the correct - values from termcap. */ + int rows, cols; + #if defined(__GO32__) - lines_per_page = ScreenRows (); - chars_per_line = ScreenCols (); + rows = ScreenRows (); + cols = ScreenCols (); + lines_per_page = rows; + chars_per_line = cols; #else - lines_per_page = 24; - chars_per_line = 80; - -#if !defined (_WIN32) - /* Initialize the screen height and width from termcap. */ - { - char *termtype = getenv ("TERM"); + /* Make sure Readline has initialized its terminal settings. */ + rl_reset_terminal (NULL); - /* Positive means success, nonpositive means failure. */ - int status; + /* Get the screen size from Readline. */ + rl_get_screen_size (&rows, &cols); + lines_per_page = rows; + chars_per_line = cols; - /* 2048 is large enough for all known terminals, according to the - GNU termcap manual. */ - char term_buffer[2048]; - - if (termtype) - { - status = tgetent (term_buffer, termtype); - if (status > 0) - { - int val; - int running_in_emacs = getenv ("EMACS") != NULL; - - val = tgetnum ("li"); - if (val >= 0 && !running_in_emacs) - lines_per_page = val; - else - /* The number of lines per page is not mentioned - in the terminal description. This probably means - that paging is not useful (e.g. emacs shell window), - so disable paging. */ - lines_per_page = UINT_MAX; - - val = tgetnum ("co"); - if (val >= 0) - chars_per_line = val; - } - } - } -#endif + /* Readline should have fetched the termcap entry for us. */ + if (tgetnum ("li") < 0 || getenv ("EMACS")) + { + /* The number of lines per page is not mentioned in the + terminal description. This probably means that paging is + not useful (e.g. emacs shell window), so disable paging. */ + lines_per_page = UINT_MAX; + } + /* FIXME: Get rid of this junk. */ #if defined(SIGWINCH) && defined(SIGWINCH_HANDLER) - - /* If there is a better way to determine the window size, use it. */ SIGWINCH_HANDLER (SIGWINCH); #endif -#endif + /* If the output is not a terminal, don't paginate it. */ if (!ui_file_isatty (gdb_stdout)) lines_per_page = UINT_MAX; - } /* the command_line_version */ +#endif + } + + set_screen_size (); set_width (); } +/* Set the screen size based on LINES_PER_PAGE and CHARS_PER_LINE. */ + +static void +set_screen_size (void) +{ + int rows = lines_per_page; + int cols = chars_per_line; + + if (rows <= 0) + rows = INT_MAX; + + if (cols <= 0) + rl_get_screen_size (NULL, &cols); + + /* Update Readline's idea of the terminal size. */ + rl_set_screen_size (rows, cols); +} + +/* Reinitialize WRAP_BUFFER according to the current value of + CHARS_PER_LINE. */ + static void set_width (void) { @@ -1663,16 +1656,22 @@ set_width (void) } else wrap_buffer = (char *) xrealloc (wrap_buffer, chars_per_line + 2); - wrap_pointer = wrap_buffer; /* Start it at the beginning */ + wrap_pointer = wrap_buffer; /* Start it at the beginning. */ } -/* ARGSUSED */ static void set_width_command (char *args, int from_tty, struct cmd_list_element *c) { + set_screen_size (); set_width (); } +static void +set_height_command (char *args, int from_tty, struct cmd_list_element *c) +{ + set_screen_size (); +} + /* Wait, so the user can read what's on the screen. Prompt the user to continue by pressing RETURN. */ @@ -2468,27 +2467,19 @@ initialize_utils (void) { struct cmd_list_element *c; - c = add_set_cmd ("width", class_support, var_uinteger, - (char *) &chars_per_line, + c = add_set_cmd ("width", class_support, var_uinteger, &chars_per_line, "Set number of characters gdb thinks are in a line.", &setlist); add_show_from_set (c, &showlist); set_cmd_sfunc (c, set_width_command); - add_show_from_set - (add_set_cmd ("height", class_support, - var_uinteger, (char *) &lines_per_page, - "Set number of lines gdb thinks are in a page.", &setlist), - &showlist); + c = add_set_cmd ("height", class_support, var_uinteger, &lines_per_page, + "Set number of lines gdb thinks are in a page.", &setlist); + add_show_from_set (c, &showlist); + set_cmd_sfunc (c, set_height_command); init_page_info (); - /* If the output is not a terminal, don't paginate it. */ - if (!ui_file_isatty (gdb_stdout)) - lines_per_page = UINT_MAX; - - set_width_command ((char *) NULL, 0, c); - add_show_from_set (add_set_cmd ("demangle", class_support, var_boolean, (char *) &demangle, @@ -2911,3 +2902,19 @@ gnu_debuglink_crc32 (unsigned long crc, unsigned char *buf, size_t len) crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8); return ~crc & 0xffffffff;; } + +ULONGEST +align_up (ULONGEST v, int n) +{ + /* Check that N is really a power of two. */ + gdb_assert (n && (n & (n-1)) == 0); + return (v + n - 1) & -n; +} + +ULONGEST +align_down (ULONGEST v, int n) +{ + /* Check that N is really a power of two. */ + gdb_assert (n && (n & (n-1)) == 0); + return (v & -n); +}