Re: [RFA] New substitute-path commands

Joel Brobecker
2006-07-07T05:22:26Z

[-- Attachment #1: Type: text/plain, Size: 1007 bytes --]

Hello,

Here is a second take at this new functionality, updated as suggested:

> set substitute-path FROM TO
>
> [We can make it use buildargv for uniform quoting of TO and FROM.
> I'd recommend that.]
>
> unset substitute-path FROM
>
> show substitute-path

Added bonus, I included a documentation patch for review.

2006-07-06 Joel Brobecker <brobecker@adacore.com

* source.c (substitute_path_from): New static variable.
(substitute_path_to): Likewise.
(xrewrite_source_path): New function.
(find_and_open_source): Add source path rewriting support.
(show_substitute_path_command): New function.
(unset_substitute_path_command): New function.
(set_substitute_path_command): New function.
(_initialize_source): Add new substitute-path commands.

Documentation ChangeLog entry:

* gdb.texinfo (Source Path): Add documentation for new
substitute-path commands.

Tested on x86-linux, no regression.

Thanks,
--
Joel

[-- Attachment #2: subst.diff --]
[-- Type: text/plain, Size: 6910 bytes --]

Index: source.c
===================================================================
RCS file: /cvs/src/src/gdb/source.c,v
retrieving revision 1.75
diff -u -p -r1.75 source.c
--- source.c 15 May 2006 15:50:13 -0000 1.75
+++ source.c 7 Jul 2006 04:50:31 -0000
@@ -73,6 +73,11 @@ static void show_directories (char *, in

char *source_path;

+/* Support for source path substitution commands. */
+
+static char *substitute_path_from = NULL;
+static char *substitute_path_to = NULL;
+
/* Symtab of default file for listing lines of. */

static struct symtab *current_source_symtab;
@@ -828,6 +833,47 @@ source_full_path_of (char *filename, cha
return 1;
}

+/* If the user specified a source path substitution rule, then
+ try applying it on PATH, and return the new path. This new
+ path must be deallocated afterwards.
+
+ Return NULL if no substitution rule was specified by the user,
+ or of this rule didn't apply to the given PATH. */
+
+static char *
+xrewrite_source_path (const char *path)
+{
+ char *from_start;
+ char *new_path;
+
+ /* If no path substitution rule was specified, then no rewrite
+ is actually needed. */
+
+ if (substitute_path_from == NULL)
+ return NULL;
+
+ /* Search for the first occurence of SUBSTITUTE_PATH_FROM.
+ No substitution needed of not found. */
+
+ from_start = strstr (path, substitute_path_from);
+
+ if (from_start == NULL)
+ return NULL;
+
+ /* Compute the rewritten path and return it. */
+
+ new_path = (char *) xmalloc (strlen (path) + 1
+ + strlen (substitute_path_to)
+ - strlen (substitute_path_from));
+ strncpy (new_path, path, from_start - path);
+ strcpy (new_path + (from_start - path),
+ substitute_path_to);
+ strcat (new_path,
+ from_start + strlen (substitute_path_from));
+
+ return new_path;
+}
+
/* This function is capable of finding the absolute path to a
source file, and opening it, provided you give it an
OBJFILE and FILENAME. Both the DIRNAME and FULLNAME are only
@@ -844,7 +890,7 @@ source_full_path_of (char *filename, cha
FULLNAME is set to the absolute path to the file just opened.

On Failure
- A non valid file descriptor is returned. ( the return value is negitive )
+ A non valid file descriptor is returned. ( the return value is negative )
FULLNAME is set to NULL. */
int
find_and_open_source (struct objfile *objfile,
@@ -857,8 +903,22 @@ find_and_open_source (struct objfile *ob
int result;

/* Quick way out if we already know its full name */
+
if (*fullname)
{
+ {
+ /* The user may have requested that source paths be rewritten
+ according to a substitution rule he provided. Check if
+ this is the case, and do the rewrite if appropriate. */
+ char *rewritten_fullname = xrewrite_source_path (*fullname);
+
+ if (rewritten_fullname != NULL)
+ {
+ xfree (*fullname);
+ *fullname = rewritten_fullname;
+ }
+ }
+
result = open (*fullname, OPEN_MODE);
if (result >= 0)
return result;
@@ -869,6 +929,27 @@ find_and_open_source (struct objfile *ob

if (dirname != NULL)
{
+ /* If necessary, rewrite the compilation directory name according
+ to the source path substitution rules specified by the user.
+
+ Normally, we should really try to do the rewrite on the entire
+ path as opposed to just the directory name, but that's making
+ things much more complicated since we now have to concat the
+ dirname and filename, apply the substitution rule, and then do
+ [...] ??? How do we split the path back into dirname and filename?
+ In practice, the source path substitution feature should be used
+ when the entire tree has been moved, in which case only the root
+ part of the tree path will need to be rewritten. So this should
+ not be a problem in practice. */
+
+ char *rewritten_dirname = xrewrite_source_path (dirname);
+
+ if (rewritten_dirname != NULL)
+ {
+ make_cleanup (xfree, rewritten_dirname);
+ dirname = rewritten_dirname;
+ }
+
/* Replace a path entry of $cdir with the compilation directory name */
#define cdir_len 5
/* We cast strstr's result in case an ANSIhole has made it const,
@@ -1587,6 +1668,65 @@ reverse_search_command (char *regex, int
fclose (stream);
return;
}
+
+/* Print the current source path substitution rule. */
+
+static void
+show_substitute_path_command (char *args, int from_tty)
+{
+ if (substitute_path_from == NULL)
+ printf_filtered (_("No source path substitution rule specified.\n"));
+ else
+ printf_filtered (_("`%s' in source paths now substituted with `%s'.\n"),
+ substitute_path_from, substitute_path_to);
+}
+
+/* Delete the current source path substitution rule. */
+
+static void
+unset_substitute_path_command (char *args, int from_tty)
+{
+ if (substitute_path_from != NULL)
+ {
+ xfree (substitute_path_from);
+ substitute_path_from = NULL;
+ }
+
+ if (substitute_path_to != NULL)
+ {
+ xfree (substitute_path_to);
+ substitute_path_to = NULL;
+ }
+}
+
+/* Add a new source path substitution rule. */
+
+static void
+set_substitute_path_command (char *args, int from_tty)
+{
+ char *from_path, *to_path;
+ char **argv = buildargv (args);
+
+ if (argv == NULL || argv[0] == NULL || argv [1] == NULL)
+ error (_("Incorrect usage, too few arguments in command"));
+
+ if (argv[2] != NULL)
+ error (_("Incorrect usage, too many arguments in command"));
+
+ /* Remove any previous substitution rule. */
+
+ unset_substitute_path_command (NULL, from_tty);
+
+ /* Insert the new substitution rule, and print a confirmation message
+ to the user. */
+
+ substitute_path_from = xstrdup (argv[0]);
+ substitute_path_to = xstrdup (argv[1]);
+ freeargv (argv);
+
+ show_substitute_path_command (NULL, from_tty);
+}
+
\f
void
_initialize_source (void)
@@ -1666,4 +1806,19 @@ Show number of source lines gdb will lis
NULL,
show_lines_to_list,
&setlist, &showlist);
+
+ add_cmd ("substitute-path", class_files, set_substitute_path_command,
+ _("\
+Add a source path substitution rule. If a substitution rule was previously\n\
+set, it is overridden."), &setlist);
+
+ add_cmd ("substitute-path", class_files, unset_substitute_path_command,
+ _("\
+Remove the current source path substitution rule. Has no effect\n\
+if no path substitution rule was previously specified."),
+ &unsetlist);
+
+ add_cmd ("substitute-path", class_files, show_substitute_path_command,
+ _("Show the current source path substitution rule."),
+ &showlist);
}

[-- Attachment #3: subst-doc.diff --]
[-- Type: text/plain, Size: 2302 bytes --]

Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.340
diff -u -p -r1.340 gdb.texinfo
--- doc/gdb.texinfo 21 Jun 2006 13:57:21 -0000 1.340
+++ doc/gdb.texinfo 7 Jul 2006 04:51:00 -0000
@@ -5033,6 +5033,23 @@ To add other directories, use the @code{
The search path is used to find both program source files and @value{GDBN}
script files (read using the @samp{-command} option and @samp{source} command).

+In addition to the source path, @value{GDBN} provides a set of commands
+that manage a source path substitution rule. Instead of attempting to
+locate the source file using the original source path as described above,
+it will first apply the substitution rule to that source path, and use
+the resulting path instead. By default, there is no substitution rule
+defined, but this can be very useful in the case when your source tree
+has been moved to a different location from the one where the sources
+were compiled. To define a source path substitution rule, use the
+@code{set substitute-path} command.
+
+Using the previous example, suppose the @file{foo-1.0} tree has been
+moved from @file{/usr/src} to @file{/mnt/cross}, then you can tell
+GDB to replace @file{/usr/src} in all source path names with
+@file{/mnt/cross}. The first lookup will then be
+@file{/mnt/cross/foo-1.0/lib/foo.c} in place of the original location
+of @file{/usr/src/foo-1.0/lib/foo.c}.
+
@table @code
@item directory @var{dirname} @dots{}
@item dir @var{dirname} @dots{}
@@ -5068,6 +5085,21 @@ Reset the source path to its default val
@item show directories
@kindex show directories
Print the source path: show which directories it contains.
+
+@item set substitute-path @var{FROM} @var{TO}
+@kindex set substitute-path
+Define a source path substitution rule. The new substitution rule
+replaces any rule previously defined.
+
+@item unset substitute-path
+@kindex unset substitute-path
+If a source path substitution rule is active, then cancel it.
+This command has no effect otherwise.
+
+@item show substitute-path
+@kindex show substitute-path
+Print the source path substitution rule if defined.
+
@end table

If your source path is cluttered with directories that are no longer of