| Index: gdb/source.c
 | 
| diff --git a/gdb/source.c b/gdb/source.c
 | 
| index 909f2523b7224d1282c6463de3def84dbe25bb79..0ff0782d453a67d39c7436c3e313dcc31d6e3357 100644
 | 
| --- a/gdb/source.c
 | 
| +++ b/gdb/source.c
 | 
| @@ -243,7 +243,8 @@ select_source_symtab (struct symtab *s)
 | 
|       if one exists.  */
 | 
|    if (lookup_symbol (main_name (), 0, VAR_DOMAIN, 0))
 | 
|      {
 | 
| -      sals = decode_line_spec (main_name (), DECODE_LINE_FUNFIRSTLINE);
 | 
| +      sals = decode_line_with_current_source (main_name (),
 | 
| +					      DECODE_LINE_FUNFIRSTLINE);
 | 
|        sal = sals.sals[0];
 | 
|        xfree (sals.sals);
 | 
|        current_source_pspace = sal.pspace;
 | 
| @@ -440,62 +441,40 @@ add_path (char *dirname, char **which_path, int parse_separators)
 | 
|  {
 | 
|    char *old = *which_path;
 | 
|    int prefix = 0;
 | 
| -  char **argv = NULL;
 | 
| -  char *arg;
 | 
| -  int argv_index = 0;
 | 
| +  VEC (char_ptr) *dir_vec = NULL;
 | 
| +  struct cleanup *back_to;
 | 
| +  int ix;
 | 
| +  char *name;
 | 
|  
 | 
|    if (dirname == 0)
 | 
|      return;
 | 
|  
 | 
|    if (parse_separators)
 | 
|      {
 | 
| +      char **argv, **argvp;
 | 
| +
 | 
|        /* This will properly parse the space and tab separators
 | 
| -	 and any quotes that may exist.  DIRNAME_SEPARATOR will
 | 
| -	 be dealt with later.  */
 | 
| +	 and any quotes that may exist.  */
 | 
|        argv = gdb_buildargv (dirname);
 | 
| -      make_cleanup_freeargv (argv);
 | 
|  
 | 
| -      arg = argv[0];
 | 
| +      for (argvp = argv; *argvp; argvp++)
 | 
| +	dirnames_to_char_ptr_vec_append (&dir_vec, *argvp);
 | 
| +
 | 
| +      freeargv (argv);
 | 
|      }
 | 
|    else
 | 
| -    {
 | 
| -      arg = xstrdup (dirname);
 | 
| -      make_cleanup (xfree, arg);
 | 
| -    }
 | 
| +    VEC_safe_push (char_ptr, dir_vec, xstrdup (dirname));
 | 
| +  back_to = make_cleanup_free_char_ptr_vec (dir_vec);
 | 
|  
 | 
| -  do
 | 
| +  for (ix = 0; VEC_iterate (char_ptr, dir_vec, ix, name); ++ix)
 | 
|      {
 | 
| -      char *name = arg;
 | 
|        char *p;
 | 
|        struct stat st;
 | 
|  
 | 
| -      {
 | 
| -	char *separator = NULL;
 | 
| -
 | 
| -	/* Spaces and tabs will have been removed by buildargv().
 | 
| -	   The directories will there be split into a list but
 | 
| -	   each entry may still contain DIRNAME_SEPARATOR.  */
 | 
| -	if (parse_separators)
 | 
| -	  separator = strchr (name, DIRNAME_SEPARATOR);
 | 
| -
 | 
| -	if (separator == 0)
 | 
| -	  p = arg = name + strlen (name);
 | 
| -	else
 | 
| -	  {
 | 
| -	    p = separator;
 | 
| -	    arg = p + 1;
 | 
| -	    while (*arg == DIRNAME_SEPARATOR)
 | 
| -	      ++arg;
 | 
| -	  }
 | 
| -
 | 
| -	/* If there are no more directories in this argument then start
 | 
| -	   on the next argument next time round the loop (if any).  */
 | 
| -	if (*arg == '\0')
 | 
| -	  arg = parse_separators ? argv[++argv_index] : NULL;
 | 
| -      }
 | 
| -
 | 
| -      /* name is the start of the directory.
 | 
| -	 p is the separator (or null) following the end.  */
 | 
| +      /* Spaces and tabs will have been removed by buildargv().
 | 
| +         NAME is the start of the directory.
 | 
| +	 P is the '\0' following the end.  */
 | 
| +      p = name + strlen (name);
 | 
|  
 | 
|        while (!(IS_DIR_SEPARATOR (*name) && p <= name + 1)	/* "/" */
 | 
|  #ifdef HAVE_DOS_BASED_FILE_SYSTEM
 | 
| @@ -573,65 +552,54 @@ add_path (char *dirname, char **which_path, int parse_separators)
 | 
|      append:
 | 
|        {
 | 
|  	unsigned int len = strlen (name);
 | 
| +	char tinybuf[2];
 | 
|  
 | 
|  	p = *which_path;
 | 
| -	while (1)
 | 
| +	/* FIXME: we should use realpath() or its work-alike
 | 
| +	   before comparing.  Then all the code above which
 | 
| +	   removes excess slashes and dots could simply go away.  */
 | 
| +	if (!filename_cmp (p, name))
 | 
|  	  {
 | 
| -	    /* FIXME: we should use realpath() or its work-alike
 | 
| -	       before comparing.  Then all the code above which
 | 
| -	       removes excess slashes and dots could simply go away.  */
 | 
| -	    if (!filename_ncmp (p, name, len)
 | 
| -		&& (p[len] == '\0' || p[len] == DIRNAME_SEPARATOR))
 | 
| -	      {
 | 
| -		/* Found it in the search path, remove old copy.  */
 | 
| -		if (p > *which_path)
 | 
| -		  p--;		/* Back over leading separator.  */
 | 
| -		if (prefix > p - *which_path)
 | 
| -		  goto skip_dup;	/* Same dir twice in one cmd.  */
 | 
| -		strcpy (p, &p[len + 1]);	/* Copy from next \0 or  : */
 | 
| -	      }
 | 
| -	    p = strchr (p, DIRNAME_SEPARATOR);
 | 
| -	    if (p != 0)
 | 
| -	      ++p;
 | 
| -	    else
 | 
| -	      break;
 | 
| +	    /* Found it in the search path, remove old copy.  */
 | 
| +	    if (p > *which_path)
 | 
| +	      p--;		/* Back over leading separator.  */
 | 
| +	    if (prefix > p - *which_path)
 | 
| +	      goto skip_dup;	/* Same dir twice in one cmd.  */
 | 
| +	    memmove (p, &p[len + 1], strlen (&p[len + 1]) + 1);	/* Copy from next \0 or  : */
 | 
|  	  }
 | 
| -	if (p == 0)
 | 
| -	  {
 | 
| -	    char tinybuf[2];
 | 
|  
 | 
| -	    tinybuf[0] = DIRNAME_SEPARATOR;
 | 
| -	    tinybuf[1] = '\0';
 | 
| +	tinybuf[0] = DIRNAME_SEPARATOR;
 | 
| +	tinybuf[1] = '\0';
 | 
|  
 | 
| -	    /* If we have already tacked on a name(s) in this command,
 | 
| -	       be sure they stay on the front as we tack on some
 | 
| -	       more.  */
 | 
| -	    if (prefix)
 | 
| -	      {
 | 
| -		char *temp, c;
 | 
| -
 | 
| -		c = old[prefix];
 | 
| -		old[prefix] = '\0';
 | 
| -		temp = concat (old, tinybuf, name, (char *)NULL);
 | 
| -		old[prefix] = c;
 | 
| -		*which_path = concat (temp, "", &old[prefix], (char *) NULL);
 | 
| -		prefix = strlen (temp);
 | 
| -		xfree (temp);
 | 
| -	      }
 | 
| -	    else
 | 
| -	      {
 | 
| -		*which_path = concat (name, (old[0] ? tinybuf : old),
 | 
| -				      old, (char *)NULL);
 | 
| -		prefix = strlen (name);
 | 
| -	      }
 | 
| -	    xfree (old);
 | 
| -	    old = *which_path;
 | 
| +	/* If we have already tacked on a name(s) in this command,
 | 
| +	   be sure they stay on the front as we tack on some
 | 
| +	   more.  */
 | 
| +	if (prefix)
 | 
| +	  {
 | 
| +	    char *temp, c;
 | 
| +
 | 
| +	    c = old[prefix];
 | 
| +	    old[prefix] = '\0';
 | 
| +	    temp = concat (old, tinybuf, name, (char *)NULL);
 | 
| +	    old[prefix] = c;
 | 
| +	    *which_path = concat (temp, "", &old[prefix], (char *) NULL);
 | 
| +	    prefix = strlen (temp);
 | 
| +	    xfree (temp);
 | 
| +	  }
 | 
| +	else
 | 
| +	  {
 | 
| +	    *which_path = concat (name, (old[0] ? tinybuf : old),
 | 
| +				  old, (char *)NULL);
 | 
| +	    prefix = strlen (name);
 | 
|  	  }
 | 
| +	xfree (old);
 | 
| +	old = *which_path;
 | 
|        }
 | 
|      skip_dup:
 | 
|        ;
 | 
|      }
 | 
| -  while (arg != NULL);
 | 
| +
 | 
| +  do_cleanups (back_to);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -712,10 +680,11 @@ openp (const char *path, int opts, const char *string,
 | 
|  {
 | 
|    int fd;
 | 
|    char *filename;
 | 
| -  const char *p;
 | 
| -  const char *p1;
 | 
| -  int len;
 | 
|    int alloclen;
 | 
| +  VEC (char_ptr) *dir_vec;
 | 
| +  struct cleanup *back_to;
 | 
| +  int ix;
 | 
| +  char *dir;
 | 
|  
 | 
|    /* The open syscall MODE parameter is not specified.  */
 | 
|    gdb_assert ((mode & O_CREAT) == 0);
 | 
| @@ -778,16 +747,15 @@ openp (const char *path, int opts, const char *string,
 | 
|    alloclen = strlen (path) + strlen (string) + 2;
 | 
|    filename = alloca (alloclen);
 | 
|    fd = -1;
 | 
| -  for (p = path; p; p = p1 ? p1 + 1 : 0)
 | 
| +
 | 
| +  dir_vec = dirnames_to_char_ptr_vec (path);
 | 
| +  back_to = make_cleanup_free_char_ptr_vec (dir_vec);
 | 
| +
 | 
| +  for (ix = 0; VEC_iterate (char_ptr, dir_vec, ix, dir); ++ix)
 | 
|      {
 | 
| -      p1 = strchr (p, DIRNAME_SEPARATOR);
 | 
| -      if (p1)
 | 
| -	len = p1 - p;
 | 
| -      else
 | 
| -	len = strlen (p);
 | 
| +      size_t len = strlen (dir);
 | 
|  
 | 
| -      if (len == 4 && p[0] == '$' && p[1] == 'c'
 | 
| -	  && p[2] == 'w' && p[3] == 'd')
 | 
| +      if (strcmp (dir, "$cwd") == 0)
 | 
|  	{
 | 
|  	  /* Name is $cwd -- insert current directory name instead.  */
 | 
|  	  int newlen;
 | 
| @@ -802,11 +770,29 @@ openp (const char *path, int opts, const char *string,
 | 
|  	    }
 | 
|  	  strcpy (filename, current_directory);
 | 
|  	}
 | 
| +      else if (strchr(dir, '~'))
 | 
| +	{
 | 
| +	 /* See whether we need to expand the tilde.  */
 | 
| +	  int newlen;
 | 
| +	  char *tilde_expanded;
 | 
| +
 | 
| +	  tilde_expanded  = tilde_expand (dir);
 | 
| +
 | 
| +	  /* First, realloc the filename buffer if too short.  */
 | 
| +	  len = strlen (tilde_expanded);
 | 
| +	  newlen = len + strlen (string) + 2;
 | 
| +	  if (newlen > alloclen)
 | 
| +	    {
 | 
| +	      alloclen = newlen;
 | 
| +	      filename = alloca (alloclen);
 | 
| +	    }
 | 
| +	  strcpy (filename, tilde_expanded);
 | 
| +	  xfree (tilde_expanded);
 | 
| +	}
 | 
|        else
 | 
|  	{
 | 
|  	  /* Normal file name in path -- just use it.  */
 | 
| -	  strncpy (filename, p, len);
 | 
| -	  filename[len] = 0;
 | 
| +	  strcpy (filename, dir);
 | 
|  
 | 
|  	  /* Don't search $cdir.  It's also a magic path like $cwd, but we
 | 
|  	     don't have enough information to expand it.  The user *could*
 | 
| @@ -815,7 +801,7 @@ openp (const char *path, int opts, const char *string,
 | 
|  	     contexts.  If the user really has '$cdir' one can use './$cdir'.
 | 
|  	     We can get $cdir when loading scripts.  When loading source files
 | 
|  	     $cdir must have already been expanded to the correct value.  */
 | 
| -	  if (strcmp (filename, "$cdir") == 0)
 | 
| +	  if (strcmp (dir, "$cdir") == 0)
 | 
|  	    continue;
 | 
|  	}
 | 
|  
 | 
| @@ -834,6 +820,8 @@ openp (const char *path, int opts, const char *string,
 | 
|  	}
 | 
|      }
 | 
|  
 | 
| +  do_cleanups (back_to);
 | 
| +
 | 
|  done:
 | 
|    if (filename_opened)
 | 
|      {
 | 
| @@ -971,26 +959,6 @@ rewrite_source_path (const char *path)
 | 
|    return new_path;
 | 
|  }
 | 
|  
 | 
| -/* This function is capable of finding the absolute path to a
 | 
| -   source file, and opening it, provided you give it a FILENAME.  Both the
 | 
| -   DIRNAME and FULLNAME are only added suggestions on where to find the file.
 | 
| -
 | 
| -   FILENAME should be the filename to open.
 | 
| -   DIRNAME is the compilation directory of a particular source file.
 | 
| -           Only some debug formats provide this info.
 | 
| -   FULLNAME can be the last known absolute path to the file in question.
 | 
| -     Space for the path must have been malloc'd.  If a path substitution
 | 
| -     is applied we free the old value and set a new one.
 | 
| -
 | 
| -   On Success 
 | 
| -     A valid file descriptor is returned (the return value is positive).
 | 
| -     FULLNAME is set to the absolute path to the file just opened.
 | 
| -     The caller is responsible for freeing FULLNAME.
 | 
| -
 | 
| -   On Failure
 | 
| -     An invalid file descriptor is returned (the return value is negative).
 | 
| -     FULLNAME is set to NULL.  */
 | 
| -
 | 
|  int
 | 
|  find_and_open_source (const char *filename,
 | 
|  		      const char *dirname,
 | 
| @@ -1017,7 +985,16 @@ find_and_open_source (const char *filename,
 | 
|  
 | 
|        result = open (*fullname, OPEN_MODE);
 | 
|        if (result >= 0)
 | 
| -	return result;
 | 
| +	{
 | 
| +	  /* Call xfullpath here to be consistent with openp
 | 
| +	     which we use below.  */
 | 
| +	  char *lpath = xfullpath (*fullname);
 | 
| +
 | 
| +	  xfree (*fullname);
 | 
| +	  *fullname = lpath;
 | 
| +	  return result;
 | 
| +	}
 | 
| +
 | 
|        /* Didn't work -- free old one, try again.  */
 | 
|        xfree (*fullname);
 | 
|        *fullname = NULL;
 | 
| @@ -1429,7 +1406,7 @@ line_info (char *arg, int from_tty)
 | 
|      }
 | 
|    else
 | 
|      {
 | 
| -      sals = decode_line_spec_1 (arg, DECODE_LINE_LIST_MODE);
 | 
| +      sals = decode_line_with_last_displayed (arg, DECODE_LINE_LIST_MODE);
 | 
|  
 | 
|        dont_repeat ();
 | 
|      }
 | 
| 
 |