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); +} + 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); }