X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Futils.c;h=6065d8221b3f7dc476acd165e3b925c3cf60bf4b;hb=77dec115afceba0cc5eb3e925ad1bf1e1ecd8bf5;hp=a43b13da90cb9f8a25401a470f6fe8bf75ea1657;hpb=2b54dda2fae8e3b6020b5c0dc217983f895a1554;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/utils.c b/gdb/utils.c index a43b13da90..6065d8221b 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -1,8 +1,6 @@ /* General utility routines for GDB, the GNU debugger. - Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, - 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, - 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986-2013 Free Software Foundation, Inc. This file is part of GDB. @@ -24,9 +22,12 @@ #include "gdb_assert.h" #include #include "gdb_string.h" +#include "gdb_wait.h" #include "event-top.h" #include "exceptions.h" #include "gdbthread.h" +#include "fnmatch.h" +#include "gdb_bfd.h" #ifdef HAVE_SYS_RESOURCE_H #include #endif /* HAVE_SYS_RESOURCE_H */ @@ -88,9 +89,6 @@ extern PTR realloc (); /* ARI: PTR */ extern void free (); #endif -/* readline defines this. */ -#undef savestring - void (*deprecated_error_begin_hook) (void); /* Prototypes for local functions */ @@ -100,30 +98,32 @@ static void vfprintf_maybe_filtered (struct ui_file *, const char *, static void fputs_maybe_filtered (const char *, struct ui_file *, int); -static void do_my_cleanups (struct cleanup **, struct cleanup *); - static void prompt_for_continue (void); static void set_screen_size (void); static void set_width (void); -/* A flag indicating whether to timestamp debugging messages. */ +/* Time spent in prompt_for_continue in the currently executing command + waiting for user to respond. + Initialized in make_command_stats_cleanup. + Modified in prompt_for_continue and defaulted_query. + Used in report_command_stats. */ -static int debug_timestamp = 0; +static struct timeval prompt_for_continue_wait_time; -/* Chain of cleanup actions established with make_cleanup, - to be executed if an error happens. */ +/* A flag indicating whether to timestamp debugging messages. */ -static struct cleanup *cleanup_chain; /* cleaned up after a failed command */ -static struct cleanup *final_cleanup_chain; /* cleaned up when gdb exits */ +static int debug_timestamp = 0; /* Nonzero if we have job control. */ int job_control; +#ifndef HAVE_PYTHON /* Nonzero means a quit has been requested. */ int quit_flag; +#endif /* HAVE_PYTHON */ /* Nonzero means quit immediately if Control-C is typed now, rather than waiting until QUIT is executed. Be careful in setting this; @@ -138,6 +138,41 @@ int quit_flag; int immediate_quit; +#ifndef HAVE_PYTHON + +/* Clear the quit flag. */ + +void +clear_quit_flag (void) +{ + quit_flag = 0; +} + +/* Set the quit flag. */ + +void +set_quit_flag (void) +{ + quit_flag = 1; +} + +/* Return true if the quit flag has been set, false otherwise. */ + +int +check_quit_flag (void) +{ + /* This is written in a particular way to avoid races. */ + if (quit_flag) + { + quit_flag = 0; + return 1; + } + + return 0; +} + +#endif /* HAVE_PYTHON */ + /* Nonzero means that strings with character values >0x7F should be printed as octal escapes. Zero means just print the value (e.g. it's an international character, and the terminal or window can cope.) */ @@ -173,31 +208,11 @@ show_pagination_enabled (struct ui_file *file, int from_tty, } +/* Cleanup utilities. -/* 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 (make_cleanup_ftype *function, void *arg) -{ - return make_my_cleanup (&cleanup_chain, function, arg); -} - -struct cleanup * -make_cleanup_dtor (make_cleanup_ftype *function, void *arg, - void (*dtor) (void *)) -{ - return make_my_cleanup2 (&cleanup_chain, - function, arg, dtor); -} - -struct cleanup * -make_final_cleanup (make_cleanup_ftype *function, void *arg) -{ - return make_my_cleanup (&final_cleanup_chain, function, arg); -} + These are not defined in cleanups.c (nor declared in cleanups.h) + because while they use the "cleanup API" they are not part of the + "cleanup API". */ static void do_freeargv (void *arg) @@ -208,7 +223,7 @@ do_freeargv (void *arg) struct cleanup * make_cleanup_freeargv (char **arg) { - return make_my_cleanup (&cleanup_chain, do_freeargv, arg); + return make_cleanup (do_freeargv, arg); } static void @@ -220,17 +235,17 @@ do_dyn_string_delete (void *arg) struct cleanup * make_cleanup_dyn_string_delete (dyn_string_t arg) { - return make_my_cleanup (&cleanup_chain, do_dyn_string_delete, arg); + return make_cleanup (do_dyn_string_delete, arg); } static void do_bfd_close_cleanup (void *arg) { - bfd_close (arg); + gdb_bfd_unref (arg); } struct cleanup * -make_cleanup_bfd_close (bfd *abfd) +make_cleanup_bfd_unref (bfd *abfd) { return make_cleanup (do_bfd_close_cleanup, abfd); } @@ -297,7 +312,7 @@ do_ui_file_delete (void *arg) struct cleanup * make_cleanup_ui_file_delete (struct ui_file *arg) { - return make_my_cleanup (&cleanup_chain, do_ui_file_delete, arg); + return make_cleanup (do_ui_file_delete, arg); } /* Helper function for make_cleanup_ui_out_redirect_pop. */ @@ -317,7 +332,7 @@ do_ui_out_redirect_pop (void *arg) struct cleanup * make_cleanup_ui_out_redirect_pop (struct ui_out *uiout) { - return make_my_cleanup (&cleanup_chain, do_ui_out_redirect_pop, uiout); + return make_cleanup (do_ui_out_redirect_pop, uiout); } static void @@ -329,7 +344,7 @@ do_free_section_addr_info (void *arg) struct cleanup * make_cleanup_free_section_addr_info (struct section_addr_info *addrs) { - return make_my_cleanup (&cleanup_chain, do_free_section_addr_info, addrs); + return make_cleanup (do_free_section_addr_info, addrs); } struct restore_integer_closure @@ -358,8 +373,7 @@ make_cleanup_restore_integer (int *variable) c->variable = variable; c->value = *variable; - return make_my_cleanup2 (&cleanup_chain, restore_integer, (void *)c, - xfree); + return make_cleanup_dtor (restore_integer, (void *) c, xfree); } /* Remember the current value of *VARIABLE and make it restored when @@ -386,7 +400,7 @@ do_unpush_target (void *arg) struct cleanup * make_cleanup_unpush_target (struct target_ops *ops) { - return make_my_cleanup (&cleanup_chain, do_unpush_target, ops); + return make_cleanup (do_unpush_target, ops); } /* Helper for make_cleanup_htab_delete compile time checking the types. */ @@ -449,7 +463,7 @@ do_value_free_to_mark (void *value) struct cleanup * make_cleanup_value_free_to_mark (struct value *mark) { - return make_my_cleanup (&cleanup_chain, do_value_free_to_mark, mark); + return make_cleanup (do_value_free_to_mark, mark); } /* Helper for make_cleanup_value_free. */ @@ -465,7 +479,7 @@ do_value_free (void *value) struct cleanup * make_cleanup_value_free (struct value *value) { - return make_my_cleanup (&cleanup_chain, do_value_free, value); + return make_cleanup (do_value_free, value); } /* Helper for make_cleanup_free_so. */ @@ -483,133 +497,29 @@ do_free_so (void *arg) struct cleanup * make_cleanup_free_so (struct so_list *so) { - return make_my_cleanup (&cleanup_chain, do_free_so, so); + return make_cleanup (do_free_so, so); } -struct cleanup * -make_my_cleanup2 (struct cleanup **pmy_chain, make_cleanup_ftype *function, - void *arg, void (*free_arg) (void *)) -{ - struct cleanup *new - = (struct cleanup *) xmalloc (sizeof (struct cleanup)); - struct cleanup *old_chain = *pmy_chain; - - new->next = *pmy_chain; - new->function = function; - new->free_arg = free_arg; - new->arg = arg; - *pmy_chain = new; - - return old_chain; -} - -struct cleanup * -make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function, - void *arg) -{ - return make_my_cleanup2 (pmy_chain, function, arg, NULL); -} - -/* Discard cleanups and do the actions they describe - until we get back to the point OLD_CHAIN in the cleanup_chain. */ - -void -do_cleanups (struct cleanup *old_chain) -{ - do_my_cleanups (&cleanup_chain, old_chain); -} - -void -do_final_cleanups (struct cleanup *old_chain) -{ - do_my_cleanups (&final_cleanup_chain, old_chain); -} +/* Helper for make_cleanup_restore_current_language. */ static void -do_my_cleanups (struct cleanup **pmy_chain, - struct cleanup *old_chain) -{ - struct cleanup *ptr; - - while ((ptr = *pmy_chain) != old_chain) - { - *pmy_chain = ptr->next; /* Do this first in case of recursion. */ - (*ptr->function) (ptr->arg); - if (ptr->free_arg) - (*ptr->free_arg) (ptr->arg); - xfree (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 (struct cleanup *old_chain) -{ - discard_my_cleanups (&cleanup_chain, old_chain); -} - -void -discard_final_cleanups (struct cleanup *old_chain) -{ - discard_my_cleanups (&final_cleanup_chain, old_chain); -} - -void -discard_my_cleanups (struct cleanup **pmy_chain, - struct cleanup *old_chain) +do_restore_current_language (void *p) { - struct cleanup *ptr; - - while ((ptr = *pmy_chain) != old_chain) - { - *pmy_chain = ptr->next; - if (ptr->free_arg) - (*ptr->free_arg) (ptr->arg); - xfree (ptr); - } -} + enum language saved_lang = (uintptr_t) p; -/* Set the cleanup_chain to 0, and return the old cleanup chain. */ -struct cleanup * -save_cleanups (void) -{ - return save_my_cleanups (&cleanup_chain); + set_language (saved_lang); } -struct cleanup * -save_final_cleanups (void) -{ - return save_my_cleanups (&final_cleanup_chain); -} +/* Remember the current value of CURRENT_LANGUAGE and make it restored when + the cleanup is run. */ struct cleanup * -save_my_cleanups (struct cleanup **pmy_chain) +make_cleanup_restore_current_language (void) { - struct cleanup *old_chain = *pmy_chain; + enum language saved_lang = current_language->la_language; - *pmy_chain = 0; - return old_chain; -} - -/* Restore the cleanup chain from a previously saved chain. */ -void -restore_cleanups (struct cleanup *chain) -{ - restore_my_cleanups (&cleanup_chain, chain); -} - -void -restore_final_cleanups (struct cleanup *chain) -{ - restore_my_cleanups (&final_cleanup_chain, chain); -} - -void -restore_my_cleanups (struct cleanup **pmy_chain, struct cleanup *chain) -{ - *pmy_chain = chain; + return make_cleanup (do_restore_current_language, + (void *) (uintptr_t) saved_lang); } /* This function is useful for cleanups. @@ -635,18 +545,6 @@ free_current_contents (void *ptr) } } -/* Provide a known function that does nothing, to use as a base for - a possibly long chain of cleanups. This is useful where we - use the cleanup chain for handling normal cleanups as well as dealing - with cleanups that need to be done as a result of a call to error(). - 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. */ - -void -null_cleanup (void *arg) -{ -} - /* If nonzero, display time usage both at startup and for each command. */ static int display_time; @@ -703,6 +601,10 @@ report_command_stats (void *arg) timeval_sub (&delta_wall_time, &now_wall_time, &start_stats->start_wall_time); + /* Subtract time spend in prompt_for_continue from walltime. */ + timeval_sub (&delta_wall_time, + &delta_wall_time, &prompt_for_continue_wait_time); + printf_unfiltered (msg_type == 0 ? _("Startup time: %ld.%06ld (cpu), %ld.%06ld (wall)\n") : _("Command execution time: %ld.%06ld (cpu), %ld.%06ld (wall)\n"), @@ -736,6 +638,7 @@ report_command_stats (void *arg) struct cleanup * make_command_stats_cleanup (int msg_type) { + static const struct timeval zero_timeval = { 0 }; struct cmd_stats *new_stat = XMALLOC (struct cmd_stats); #ifdef HAVE_SBRK @@ -747,6 +650,9 @@ make_command_stats_cleanup (int msg_type) new_stat->start_cpu_time = get_run_time (); gettimeofday (&new_stat->start_wall_time, NULL); + /* Initalize timer to keep track of how long we waited for the user. */ + prompt_for_continue_wait_time = zero_timeval; + return make_cleanup_dtor (report_command_stats, new_stat, xfree); } @@ -887,7 +793,7 @@ can_dump_core (const char *reason) const char internal_problem_ask[] = "ask"; const char internal_problem_yes[] = "yes"; const char internal_problem_no[] = "no"; -static const char *internal_problem_modes[] = +static const char *const internal_problem_modes[] = { internal_problem_ask, internal_problem_yes, @@ -971,7 +877,7 @@ internal_vproblem (struct internal_problem *problem, /* Default (yes/batch case) is to quit GDB. When in batch mode this lessens the likelihood of GDB going into an infinite loop. */ - if (caution == 0) + if (!confirm) { /* Emit the message and quit. */ fputs_unfiltered (reason, gdb_stderr); @@ -1277,20 +1183,6 @@ myread (int desc, char *addr, int len) return orglen; } -/* 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 (const char *ptr, size_t size) -{ - char *p = (char *) xmalloc (size + 1); - - memcpy (p, ptr, size); - p[size] = 0; - return p; -} - void print_spaces (int n, struct ui_file *file) { @@ -1356,6 +1248,9 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args) int def_value; char def_answer, not_def_answer; char *y_string, *n_string, *question; + /* Used to add duration we waited for user to respond to + prompt_for_continue_wait_time. */ + struct timeval prompt_started, prompt_ended, prompt_delta; /* Set up according to which answer is the default. */ if (defchar == '\0') @@ -1385,7 +1280,7 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args) /* Automatically answer the default value if the user did not want prompts or the command was issued with the server prefix. */ - if (! caution || server_command) + if (!confirm || server_command) return def_value; /* If input isn't coming from the user directly, just say what @@ -1413,6 +1308,9 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args) /* Format the question outside of the loop, to avoid reusing args. */ question = xstrvprintf (ctlstr, args); + /* Used for calculating time spend waiting for user. */ + gettimeofday (&prompt_started, NULL); + while (1) { wrap_here (""); /* Flush any buffered output. */ @@ -1490,6 +1388,12 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args) y_string, n_string); } + /* Add time spend in this routine to prompt_for_continue_wait_time. */ + gettimeofday (&prompt_ended, NULL); + timeval_sub (&prompt_delta, &prompt_ended, &prompt_started); + timeval_add (&prompt_for_continue_wait_time, + &prompt_for_continue_wait_time, &prompt_delta); + xfree (question); if (annotation_level > 1) printf_filtered (("\n\032\032post-query\n")); @@ -1852,11 +1756,6 @@ init_page_info (void) lines_per_page = UINT_MAX; } - /* FIXME: Get rid of this junk. */ -#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER) - SIGWINCH_HANDLER (SIGWINCH); -#endif - /* If the output is not a terminal, don't paginate it. */ if (!ui_file_isatty (gdb_stdout)) lines_per_page = UINT_MAX; @@ -1963,6 +1862,11 @@ prompt_for_continue (void) { char *ignore; char cont_prompt[120]; + /* Used to add duration we waited for user to respond to + prompt_for_continue_wait_time. */ + struct timeval prompt_started, prompt_ended, prompt_delta; + + gettimeofday (&prompt_started, NULL); if (annotation_level > 1) printf_unfiltered (("\n\032\032pre-prompt-for-continue\n")); @@ -1978,6 +1882,7 @@ prompt_for_continue (void) reinitialize_more_filter (); immediate_quit++; + QUIT; /* On a real operating system, the user can quit with SIGINT. But not on GO32. @@ -1990,6 +1895,12 @@ prompt_for_continue (void) out to DOS. */ ignore = gdb_readline_wrapper (cont_prompt); + /* Add time spend in this routine to prompt_for_continue_wait_time. */ + gettimeofday (&prompt_ended, NULL); + timeval_sub (&prompt_delta, &prompt_ended, &prompt_started); + timeval_add (&prompt_for_continue_wait_time, + &prompt_for_continue_wait_time, &prompt_delta); + if (annotation_level > 1) printf_unfiltered (("\n\032\032post-prompt-for-continue\n")); @@ -2000,7 +1911,7 @@ prompt_for_continue (void) while (*p == ' ' || *p == '\t') ++p; if (p[0] == 'q') - async_request_quit (0); + quit (); xfree (ignore); } immediate_quit--; @@ -2590,7 +2501,7 @@ print_spaces_filtered (int n, struct ui_file *stream) demangling is off, the name is printed in its "raw" form. */ void -fprintf_symbol_filtered (struct ui_file *stream, char *name, +fprintf_symbol_filtered (struct ui_file *stream, const char *name, enum language lang, int arg_mode) { char *demangled; @@ -2821,15 +2732,20 @@ void initialize_utils (void) { add_setshow_uinteger_cmd ("width", class_support, &chars_per_line, _("\ -Set number of characters gdb thinks are in a line."), _("\ -Show number of characters gdb thinks are in a line."), NULL, +Set number of characters where GDB should wrap lines of its output."), _("\ +Show number of characters where GDB should wrap lines of its output."), _("\ +This affects where GDB wraps its output to fit the screen width.\n\ +Setting this to zero prevents GDB from wrapping its output."), set_width_command, show_chars_per_line, &setlist, &showlist); add_setshow_uinteger_cmd ("height", class_support, &lines_per_page, _("\ -Set number of lines gdb thinks are in a page."), _("\ -Show number of lines gdb thinks are in a page."), NULL, +Set number of lines in a page for GDB output pagination."), _("\ +Show number of lines in a page for GDB output pagination."), _("\ +This affects the number of lines after which GDB will pause\n\ +its output and ask you whether to continue.\n\ +Setting this to zero causes GDB never pause during output."), set_height_command, show_lines_per_page, &setlist, &showlist); @@ -2838,8 +2754,11 @@ Show number of lines gdb thinks are in a page."), NULL, add_setshow_boolean_cmd ("pagination", class_support, &pagination_enabled, _("\ -Set state of pagination."), _("\ -Show state of pagination."), NULL, +Set state of GDB output pagination."), _("\ +Show state of GDB output pagination."), _("\ +When pagination is ON, GDB pauses at end of each screenful of\n\ +its output and asks you whether to continue.\n\ +Turning pagination off is an alternative to \"set height 0\"."), NULL, show_pagination_enabled, &setlist, &showlist); @@ -2870,11 +2789,6 @@ When set, debugging messages will be marked with seconds and microseconds."), &setdebuglist, &showdebuglist); } -/* Machine specific function to handle SIGWINCH signal. */ - -#ifdef SIGWINCH_HANDLER_BODY -SIGWINCH_HANDLER_BODY -#endif /* Print routines to handle variable size regs, etc. */ /* Temporary storage using circular buffer. */ #define NUMCELLS 16 @@ -3340,125 +3254,27 @@ gdb_realpath (const char *filename) } #endif - /* This system is a lost cause, just dup the buffer. */ - return xstrdup (filename); -} - -/* Return a copy of FILENAME, with its directory prefix canonicalized - by gdb_realpath. */ - -char * -xfullpath (const char *filename) -{ - const char *base_name = lbasename (filename); - char *dir_name; - char *real_path; - char *result; - - /* Extract the basename of filename, and return immediately - a copy of filename if it does not contain any directory prefix. */ - if (base_name == filename) - return xstrdup (filename); - - dir_name = alloca ((size_t) (base_name - filename + 2)); - /* Allocate enough space to store the dir_name + plus one extra - character sometimes needed under Windows (see below), and - then the closing \000 character. */ - strncpy (dir_name, filename, base_name - filename); - dir_name[base_name - filename] = '\000'; + /* The MS Windows method. If we don't have realpath, we assume we + don't have symlinks and just canonicalize to a Windows absolute + path. GetFullPath converts ../ and ./ in relative paths to + absolute paths, filling in current drive if one is not given + or using the current directory of a specified drive (eg, "E:foo"). + It also converts all forward slashes to back slashes. */ + /* The file system is case-insensitive but case-preserving. + So we do not lowercase the path. Otherwise, we might not + be able to display the original casing in a given path. */ +#if defined (_WIN32) + { + char buf[MAX_PATH]; + DWORD len = GetFullPathName (filename, MAX_PATH, buf, NULL); -#ifdef HAVE_DOS_BASED_FILE_SYSTEM - /* We need to be careful when filename is of the form 'd:foo', which - is equivalent of d:./foo, which is totally different from d:/foo. */ - if (strlen (dir_name) == 2 && isalpha (dir_name[0]) && dir_name[1] == ':') - { - dir_name[2] = '.'; - dir_name[3] = '\000'; - } + if (len > 0 && len < MAX_PATH) + return xstrdup (buf); + } #endif - /* Canonicalize the directory prefix, and build the resulting - filename. If the dirname realpath already contains an ending - directory separator, avoid doubling it. */ - real_path = gdb_realpath (dir_name); - if (IS_DIR_SEPARATOR (real_path[strlen (real_path) - 1])) - result = concat (real_path, base_name, (char *) NULL); - else - result = concat (real_path, SLASH_STRING, base_name, (char *) NULL); - - xfree (real_path); - return result; -} - - -/* This is the 32-bit CRC function used by the GNU separate debug - facility. An executable may contain a section named - .gnu_debuglink, which holds the name of a separate executable file - containing its debug info, and a checksum of that file's contents, - computed using this function. */ -unsigned long -gnu_debuglink_crc32 (unsigned long crc, unsigned char *buf, size_t len) -{ - static const unsigned int crc32_table[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, - 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, - 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, - 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, - 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, - 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, - 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, - 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, - 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, - 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, - 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, - 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, - 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, - 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, - 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, - 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, - 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, - 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, - 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, - 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, - 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, - 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, - 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, - 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, - 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, - 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, - 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, - 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, - 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, - 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, - 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, - 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, - 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, - 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, - 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, - 0x2d02ef8d - }; - unsigned char *end; - - crc = ~crc & 0xffffffff; - for (end = buf + len; buf < end; ++buf) - crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8); - return ~crc & 0xffffffff; + /* This system is a lost cause, just dup the buffer. */ + return xstrdup (filename); } ULONGEST @@ -3651,6 +3467,17 @@ compare_positive_ints (const void *ap, const void *bp) return * (int *) ap - * (int *) bp; } +/* String compare function for qsort. */ + +int +compare_strings (const void *arg1, const void *arg2) +{ + const char **s1 = (const char **) arg1; + const char **s2 = (const char **) arg2; + + return strcmp (*s1, *s2); +} + #define AMBIGUOUS_MESS1 ".\nMatching formats:" #define AMBIGUOUS_MESS2 \ ".\nUse \"set gnutarget format-name\" to specify the format." @@ -3773,6 +3600,188 @@ producer_is_gcc_ge_4 (const char *producer) return minor; } +/* Helper for make_cleanup_free_char_ptr_vec. */ + +static void +do_free_char_ptr_vec (void *arg) +{ + VEC (char_ptr) *char_ptr_vec = arg; + + free_char_ptr_vec (char_ptr_vec); +} + +/* Make cleanup handler calling xfree for each element of CHAR_PTR_VEC and + final VEC_free for CHAR_PTR_VEC itself. + + You must not modify CHAR_PTR_VEC after this cleanup registration as the + CHAR_PTR_VEC base address may change on its updates. Contrary to VEC_free + this function does not (cannot) clear the pointer. */ + +struct cleanup * +make_cleanup_free_char_ptr_vec (VEC (char_ptr) *char_ptr_vec) +{ + return make_cleanup (do_free_char_ptr_vec, char_ptr_vec); +} + +/* Substitute all occurences of string FROM by string TO in *STRINGP. *STRINGP + must come from xrealloc-compatible allocator and it may be updated. FROM + needs to be delimited by IS_DIR_SEPARATOR or DIRNAME_SEPARATOR (or be + located at the start or end of *STRINGP. */ + +void +substitute_path_component (char **stringp, const char *from, const char *to) +{ + char *string = *stringp, *s; + const size_t from_len = strlen (from); + const size_t to_len = strlen (to); + + for (s = string;;) + { + s = strstr (s, from); + if (s == NULL) + break; + + if ((s == string || IS_DIR_SEPARATOR (s[-1]) + || s[-1] == DIRNAME_SEPARATOR) + && (s[from_len] == '\0' || IS_DIR_SEPARATOR (s[from_len]) + || s[from_len] == DIRNAME_SEPARATOR)) + { + char *string_new; + + string_new = xrealloc (string, (strlen (string) + to_len + 1)); + + /* Relocate the current S pointer. */ + s = s - string + string_new; + string = string_new; + + /* Replace from by to. */ + memmove (&s[to_len], &s[from_len], strlen (&s[from_len]) + 1); + memcpy (s, to, to_len); + + s += to_len; + } + else + s++; + } + + *stringp = string; +} + +#ifdef HAVE_WAITPID + +#ifdef SIGALRM + +/* SIGALRM handler for waitpid_with_timeout. */ + +static void +sigalrm_handler (int signo) +{ + /* Nothing to do. */ +} + +#endif + +/* Wrapper to wait for child PID to die with TIMEOUT. + TIMEOUT is the time to stop waiting in seconds. + If TIMEOUT is zero, pass WNOHANG to waitpid. + Returns PID if it was successfully waited for, otherwise -1. + + Timeouts are currently implemented with alarm and SIGALRM. + If the host does not support them, this waits "forever". + It would be odd though for a host to have waitpid and not SIGALRM. */ + +pid_t +wait_to_die_with_timeout (pid_t pid, int *status, int timeout) +{ + pid_t waitpid_result; + + gdb_assert (pid > 0); + gdb_assert (timeout >= 0); + + if (timeout > 0) + { +#ifdef SIGALRM +#if defined (HAVE_SIGACTION) && defined (SA_RESTART) + struct sigaction sa, old_sa; + + sa.sa_handler = sigalrm_handler; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + sigaction (SIGALRM, &sa, &old_sa); +#else + void (*ofunc) (); + + ofunc = (void (*)()) signal (SIGALRM, sigalrm_handler); +#endif + + alarm (timeout); +#endif + + waitpid_result = waitpid (pid, status, 0); + +#ifdef SIGALRM + alarm (0); +#if defined (HAVE_SIGACTION) && defined (SA_RESTART) + sigaction (SIGALRM, &old_sa, NULL); +#else + signal (SIGALRM, ofunc); +#endif +#endif + } + else + waitpid_result = waitpid (pid, status, WNOHANG); + + if (waitpid_result == pid) + return pid; + else + return -1; +} + +#endif /* HAVE_WAITPID */ + +/* Provide fnmatch compatible function for FNM_FILE_NAME matching of host files. + Both FNM_FILE_NAME and FNM_NOESCAPE must be set in FLAGS. + + It handles correctly HAVE_DOS_BASED_FILE_SYSTEM and + HAVE_CASE_INSENSITIVE_FILE_SYSTEM. */ + +int +gdb_filename_fnmatch (const char *pattern, const char *string, int flags) +{ + gdb_assert ((flags & FNM_FILE_NAME) != 0); + + /* It is unclear how '\' escaping vs. directory separator should coexist. */ + gdb_assert ((flags & FNM_NOESCAPE) != 0); + +#ifdef HAVE_DOS_BASED_FILE_SYSTEM + { + char *pattern_slash, *string_slash; + + /* Replace '\' by '/' in both strings. */ + + pattern_slash = alloca (strlen (pattern) + 1); + strcpy (pattern_slash, pattern); + pattern = pattern_slash; + for (; *pattern_slash != 0; pattern_slash++) + if (IS_DIR_SEPARATOR (*pattern_slash)) + *pattern_slash = '/'; + + string_slash = alloca (strlen (string) + 1); + strcpy (string_slash, string); + string = string_slash; + for (; *string_slash != 0; string_slash++) + if (IS_DIR_SEPARATOR (*string_slash)) + *string_slash = '/'; + } +#endif /* HAVE_DOS_BASED_FILE_SYSTEM */ + +#ifdef HAVE_CASE_INSENSITIVE_FILE_SYSTEM + flags |= FNM_CASEFOLD; +#endif /* HAVE_CASE_INSENSITIVE_FILE_SYSTEM */ + + return fnmatch (pattern, string, flags); +} + /* Provide a prototype to silence -Wmissing-prototypes. */ extern initialize_file_ftype _initialize_utils;