Re: Finding source files under Cygwin

Earl Chew
2002-09-16T20:14:13Z

Christopher Faylor wrote:
> I'm sorry but it is rarely a good idea to mix functionality like this.
> You're mixing an (arguable) bug fix with an (arguable) gdb enhancement.
>
> Please submit each as a separate patch.

Ok. Here's the patch to robustly handle the presence
of DIRNAME_SEPARATOR in the file names embedded in the object file.

Earl
--
> ---------------------------------------------------------------------+
> Earl Chew http://www.agilent.com |
> Agilent Technologies mailto:earl_chew@agilent.com |
> Advanced Networks Division Tel: +1 604 454 3411 |
> 2500-4710 Kingsway Fax: +1 604 454 3401 |
> Burnaby BC V5H 4M2 Canada |
> ---------------------------------------------------------------------+
ChangeLog:

* source.c: Source file lookup changes.
(openp): Delegate to openp_1.
(openp_1): Allow arbitrary path component separators.
(open_source_file): Use \0 to separate path components
when splitting path to insert $cdir.

--- ../../gdb-5.2.1-orig/gdb/source.c 2002-01-17 13:15:18.000000000
-0800
+++ source.c 2002-09-16 13:08:17.000000000 -0700
@@ -71,6 +71,11 @@

/* Prototypes for local functions. */

+static int openp_1 (const char *path, int pathlen, char sep,
+ int try_cwd_first, const char *string,
+ int mode, int prot,
+ char **filename_opened);
+
static int get_filename_and_charpos (struct symtab *, char **);

static void reverse_search_command (char *, int);
@@ -507,6 +512,11 @@
/* Open a file named STRING, searching path PATH (dir names sep by some
char)
using mode MODE and protection bits PROT in the calls to open.

+ The internal function openp_1 accepts an additional arguemnt SEP
+ which is normally set to DIRNAME_SEPARATOR by openp, but for
internal use
+ (see open_source_file) it may be set to \0 to avoid any ambiguity
+ when separating path components.
+
If TRY_CWD_FIRST, try to open ./STRING before searching PATH.
(ie pretend the first element of PATH is "."). This also indicates
that a slash in STRING disables searching of the path (this is
@@ -524,20 +534,37 @@

/* >>>> This should only allow files of certain types,
>>>> eg executable, non-directory */
+
int
openp (const char *path, int try_cwd_first, const char *string,
int mode, int prot,
char **filename_opened)
{
+ int pathlen = path ? strlen (path) : 0;
+
+ return openp_1 (path, pathlen, DIRNAME_SEPARATOR, try_cwd_first,
string,
+ mode, prot, filename_opened);
+}
+
+static int
+openp_1 (const char *path, int pathlen, char sep,
+ int try_cwd_first, const char *string,
+ int mode, int prot,
+ char **filename_opened)
+{
register int fd;
register char *filename;
const char *p;
+ const char *ep;
const char *p1;
register int len;
int alloclen;

if (!path)
- path = ".";
+ {
+ path = ".";
+ pathlen = 1;
+ }

#if defined(_WIN32) || defined(__CYGWIN__)
mode |= O_BINARY;
@@ -560,12 +587,12 @@
while (string[0] == '.' && IS_DIR_SEPARATOR (string[1]))
string += 2;

- alloclen = strlen (path) + strlen (string) + 2;
+ alloclen = pathlen + strlen (string) + 2;
filename = alloca (alloclen);
fd = -1;
- for (p = path; p; p = p1 ? p1 + 1 : 0)
+ for (p = path, ep = p + pathlen; p && (p < ep); p = p1 ? p1 + 1 : 0)
{
- p1 = strchr (p, DIRNAME_SEPARATOR);
+ p1 = strchr (p, sep);
if (p1)
len = p1 - p;
else
@@ -666,6 +693,8 @@
open_source_file (struct symtab *s)
{
char *path = source_path;
+ int pathlen = strlen (path);
+ char sep = DIRNAME_SEPARATOR;
const char *p;
int result;
char *fullname;
@@ -692,23 +721,36 @@
&& (p[cdir_len] == DIRNAME_SEPARATOR || p[cdir_len] == '\0'))
{
int len;
+ char *q;

path = (char *)
- alloca (strlen (source_path) + 1 + strlen (s->dirname) + 1);
+ alloca (pathlen + 1 + strlen (s->dirname) + 1);
len = p - source_path;
strncpy (path, source_path, len); /* Before $cdir */
strcpy (path + len, s->dirname); /* new stuff */
strcat (path + len, source_path + len + cdir_len); /* After
$cdir */
+
+ /* The segment inserted for $cdir may contain instances of
+ DIRNAME_SEPARATOR which causes ambiguity when parsing
+ the revised path. Use \0 to separate the path components
+ instead. */
+ pathlen = strlen (path);
+ sep = '\0';
+ for (q = path; len; len--, q++)
+ if (*q == DIRNAME_SEPARATOR) *q = sep;
+ for (q += strlen (s->dirname); *q; q++)
+ if (*q == DIRNAME_SEPARATOR) *q = sep;
}
}

- result = openp (path, 0, s->filename, OPEN_MODE, 0, &s->fullname);
+ result = openp_1 (path, pathlen, sep, 0,
+ s->filename, OPEN_MODE, 0, &s->fullname);
if (result < 0)
{
/* Didn't work. Try using just the basename. */
p = lbasename (s->filename);

if (p != s->filename)
- result = openp (path, 0, p, OPEN_MODE, 0, &s->fullname);
+ result = openp_1 (path, pathlen, sep, 0, p, OPEN_MODE, 0,
&s->fullname);
}

if (result >= 0)