* source.c: #include gdb_assert.h.
authorJoel Brobecker <brobecker@gnat.com>
Tue, 8 Aug 2006 22:06:06 +0000 (22:06 +0000)
committerJoel Brobecker <brobecker@gnat.com>
Tue, 8 Aug 2006 22:06:06 +0000 (22:06 +0000)
        (substitute_path_rule): New struct.
        (substitute_path_rules): New static global variable.
        (substitute_path_rule_matches): New function.
        (get_substitute_path_rule): New function.
        (rewrite_source_path): New function.
        (find_and_open_source): Add source path rewriting support.
        (strip_trailing_directory_separator): New function.
        (find_substitute_path_rule): New function.
        (add_substitute_path_rule): New function.
        (delete_substitute_path_rule): New function.
        (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.
        * Makefile.in (source.o): Add dependency on gdb_assert.h.

gdb/ChangeLog
gdb/Makefile.in
gdb/source.c

index 818c28f250e3e5f8c60706ade9d8460a7b178e92..15927211b527c8f48c6c6fbd1bd8c925f9e56b7d 100644 (file)
@@ -1,3 +1,22 @@
+2006-08-08  Joel Brobecker  <brobecker@adacore.com>
+
+       * source.c: #include gdb_assert.h.
+       (substitute_path_rule): New struct.
+       (substitute_path_rules): New static global variable.
+       (substitute_path_rule_matches): New function.
+       (get_substitute_path_rule): New function.
+       (rewrite_source_path): New function.
+       (find_and_open_source): Add source path rewriting support.
+       (strip_trailing_directory_separator): New function.
+       (find_substitute_path_rule): New function.
+       (add_substitute_path_rule): New function.
+       (delete_substitute_path_rule): New function.
+       (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.
+       * Makefile.in (source.o): Add dependency on gdb_assert.h.
+
 2006-08-08  Joel Brobecker  <brobecker@adacore.com>
 
        * i386-tdep.c (i386_follow_jump): Use read_memory_nobpt to read
index 21a6abcaca0796442e9673e6e4257e7bb173b7b5..797492046ca9b139aec07e2d1485e09839eb89f8 100644 (file)
@@ -2639,7 +2639,8 @@ source.o: source.c $(defs_h) $(symtab_h) $(expression_h) $(language_h) \
        $(command_h) $(source_h) $(gdbcmd_h) $(frame_h) $(value_h) \
        $(gdb_string_h) $(gdb_stat_h) $(gdbcore_h) $(gdb_regex_h) \
        $(symfile_h) $(objfiles_h) $(annotate_h) $(gdbtypes_h) $(linespec_h) \
-       $(filenames_h) $(completer_h) $(ui_out_h) $(readline_h)
+       $(filenames_h) $(completer_h) $(ui_out_h) $(readline_h) \
+       $(gdb_assert_h)
 sparc64fbsd-nat.o: sparc64fbsd-nat.c $(defs_h) $(regcache_h) $(target_h) \
        $(fbsd_nat_h) $(sparc64_tdep_h) $(sparc_nat_h) $(bsd_kvm_h)
 sparc64fbsd-tdep.o: sparc64fbsd-tdep.c $(defs_h) $(frame_h) \
index 800491959d519a61bf794393baa307ceb3997dd9..f254015fa1f139ece9b4b37dc982c6cfc4d29eae 100644 (file)
@@ -29,6 +29,7 @@
 #include "gdbcmd.h"
 #include "frame.h"
 #include "value.h"
+#include "gdb_assert.h"
 
 #include <sys/types.h>
 #include "gdb_string.h"
@@ -73,6 +74,17 @@ static void show_directories (char *, int);
 
 char *source_path;
 
+/* Support for source path substitution commands.  */
+
+struct substitute_path_rule
+{
+  char *from;
+  char *to;
+  struct substitute_path_rule *next;
+};
+
+static struct substitute_path_rule *substitute_path_rules = NULL;
+
 /* Symtab of default file for listing lines of.  */
 
 static struct symtab *current_source_symtab;
@@ -828,6 +840,85 @@ source_full_path_of (char *filename, char **full_pathname)
   return 1;
 }
 
+/* Return non-zero if RULE matches PATH, that is if the rule can be
+   applied to PATH.  */
+
+static int
+substitute_path_rule_matches (const struct substitute_path_rule *rule,
+                              const char *path)
+{
+  const int from_len = strlen (rule->from);
+  const int path_len = strlen (path);
+  char *path_start;
+
+  if (path_len < from_len)
+    return 0;
+
+  /* The substitution rules are anchored at the start of the path,
+     so the path should start with rule->from.  There is no filename
+     comparison routine, so we need to extract the first FROM_LEN
+     characters from PATH first and use that to do the comparison.  */
+
+  path_start = alloca (from_len + 1);
+  strncpy (path_start, path, from_len);
+  path_start[from_len] = '\0';
+
+  if (FILENAME_CMP (path_start, rule->from) != 0)
+    return 0;
+
+  /* Make sure that the region in the path that matches the substitution
+     rule is immediately followed by a directory separator (or the end of
+     string character).  */
+  
+  if (path[from_len] != '\0' && !IS_DIR_SEPARATOR (path[from_len]))
+    return 0;
+
+  return 1;
+}
+
+/* Find the substitute-path rule that applies to PATH and return it.
+   Return NULL if no rule applies.  */
+
+static struct substitute_path_rule *
+get_substitute_path_rule (const char *path)
+{
+  struct substitute_path_rule *rule = substitute_path_rules;
+
+  while (rule != NULL && !substitute_path_rule_matches (rule, path))
+    rule = rule->next;
+
+  return rule;
+}
+
+/* If the user specified a source path substitution rule that applies
+   to PATH, then apply it and return the new path.  This new path must
+   be deallocated afterwards.  
+   
+   Return NULL if no substitution rule was specified by the user,
+   or if no rule applied to the given PATH.  */
+   
+static char *
+rewrite_source_path (const char *path)
+{
+  const struct substitute_path_rule *rule = get_substitute_path_rule (path);
+  char *new_path;
+  int from_len;
+  
+  if (rule == NULL)
+    return NULL;
+
+  from_len = strlen (rule->from);
+
+  /* Compute the rewritten path and return it.  */
+
+  new_path =
+    (char *) xmalloc (strlen (path) + 1 + strlen (rule->to) - from_len);
+  strcpy (new_path, rule->to);
+  strcat (new_path, path + from_len);
+
+  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 +935,7 @@ source_full_path_of (char *filename, char **full_pathname)
      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 ) 
+     An invalid file descriptor is returned. ( the return value is negative ) 
      FULLNAME is set to NULL.  */
 int
 find_and_open_source (struct objfile *objfile,
@@ -857,8 +948,20 @@ find_and_open_source (struct objfile *objfile,
   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 substitution rules he provided.  If a substitution
+         rule applies to this path, then apply it.  */
+      char *rewritten_fullname = rewrite_source_path (*fullname);
+
+      if (rewritten_fullname != NULL)
+        {
+          xfree (*fullname);
+          *fullname = rewritten_fullname;
+        }
+
       result = open (*fullname, OPEN_MODE);
       if (result >= 0)
        return result;
@@ -869,6 +972,17 @@ find_and_open_source (struct objfile *objfile,
 
   if (dirname != NULL)
     {
+      /* If necessary, rewrite the compilation directory name according
+         to the source path substitution rules specified by the user.  */
+
+      char *rewritten_dirname = rewrite_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 +1701,220 @@ reverse_search_command (char *regex, int from_tty)
   fclose (stream);
   return;
 }
+
+/* If the last character of PATH is a directory separator, then strip it.  */
+
+static void
+strip_trailing_directory_separator (char *path)
+{
+  const int last = strlen (path) - 1;
+
+  if (last < 0)
+    return;  /* No stripping is needed if PATH is the empty string.  */
+
+  if (IS_DIR_SEPARATOR (path[last]))
+    path[last] = '\0';
+}
+
+/* Return the path substitution rule that matches FROM.
+   Return NULL if no rule matches.  */
+
+static struct substitute_path_rule *
+find_substitute_path_rule (const char *from)
+{
+  struct substitute_path_rule *rule = substitute_path_rules;
+
+  while (rule != NULL)
+    {
+      if (FILENAME_CMP (rule->from, from) == 0)
+        return rule;
+      rule = rule->next;
+    }
+
+  return NULL;
+}
+
+/* Add a new substitute-path rule at the end of the current list of rules.
+   The new rule will replace FROM into TO.  */
+
+static void
+add_substitute_path_rule (char *from, char *to)
+{
+  struct substitute_path_rule *rule;
+  struct substitute_path_rule *new_rule;
+
+  new_rule = xmalloc (sizeof (struct substitute_path_rule));
+  new_rule->from = xstrdup (from);
+  new_rule->to = xstrdup (to);
+  new_rule->next = NULL;
+
+  /* If the list of rules are empty, then insert the new rule
+     at the head of the list.  */
+
+  if (substitute_path_rules == NULL)
+    {
+      substitute_path_rules = new_rule;
+      return;
+    }
+
+  /* Otherwise, skip to the last rule in our list and then append
+     the new rule.  */
+
+  rule = substitute_path_rules;
+  while (rule->next != NULL)
+    rule = rule->next;
+
+  rule->next = new_rule;
+}
+
+/* Remove the given source path substitution rule from the current list
+   of rules.  The memory allocated for that rule is also deallocated.  */
+
+static void
+delete_substitute_path_rule (struct substitute_path_rule *rule)
+{
+  if (rule == substitute_path_rules)
+    substitute_path_rules = rule->next;
+  else
+    {
+      struct substitute_path_rule *prev = substitute_path_rules;
+
+      while (prev != NULL && prev->next != rule)
+        prev = prev->next;
+
+      gdb_assert (prev != NULL);
+
+      prev->next = rule->next;
+    }
+
+  xfree (rule->from);
+  xfree (rule->to);
+  xfree (rule);
+}
+
+/* Implement the "show substitute-path" command.  */
+
+static void
+show_substitute_path_command (char *args, int from_tty)
+{
+  struct substitute_path_rule *rule = substitute_path_rules;
+  char **argv;
+  char *from = NULL;
+  
+  argv = buildargv (args);
+  make_cleanup_freeargv (argv);
+
+  /* We expect zero or one argument.  */
+
+  if (argv != NULL && argv[0] != NULL && argv[1] != NULL)
+    error (_("Too many arguments in command"));
+
+  if (argv != NULL && argv[0] != NULL)
+    from = argv[0];
+
+  /* Print the substitution rules.  */
+
+  if (from != NULL)
+    printf_filtered
+      (_("Source path substitution rule matching `%s':\n"), from);
+  else
+    printf_filtered (_("List of all source path substitution rules:\n"));
+
+  while (rule != NULL)
+    {
+      if (from == NULL || FILENAME_CMP (rule->from, from) == 0)
+        printf_filtered ("  `%s' -> `%s'.\n", rule->from, rule->to);
+      rule = rule->next;
+    }
+}
+
+/* Implement the "unset substitute-path" command.  */
+
+static void
+unset_substitute_path_command (char *args, int from_tty)
+{
+  struct substitute_path_rule *rule = substitute_path_rules;
+  char **argv = buildargv (args);
+  char *from = NULL;
+  int rule_found = 0;
+
+  /* This function takes either 0 or 1 argument.  */
+
+  if (argv != NULL && argv[0] != NULL && argv[1] != NULL)
+    error (_("Incorrect usage, too many arguments in command"));
+
+  if (argv != NULL && argv[0] != NULL)
+    from = argv[0];
+
+  /* If the user asked for all the rules to be deleted, ask him
+     to confirm and give him a chance to abort before the action
+     is performed.  */
+
+  if (from == NULL
+      && !query (_("Delete all source path substitution rules? ")))
+    error (_("Canceled"));
+
+  /* Delete the rule matching the argument.  No argument means that
+     all rules should be deleted.  */
+
+  while (rule != NULL)
+    {
+      struct substitute_path_rule *next = rule->next;
+
+      if (from == NULL || FILENAME_CMP (from, rule->from) == 0)
+        {
+          delete_substitute_path_rule (rule);
+          rule_found = 1;
+        }
+
+      rule = next;
+    }
+  
+  /* If the user asked for a specific rule to be deleted but
+     we could not find it, then report an error.  */
+
+  if (from != NULL && !rule_found)
+    error (_("No substitution rule defined for `%s'"), from);
+}
+
+/* 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;
+  struct substitute_path_rule *rule;
+  
+  argv = buildargv (args);
+  make_cleanup_freeargv (argv);
+
+  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"));
+
+  if (*(argv[0]) == '\0')
+    error (_("First argument must be at least one character long"));
+
+  /* Strip any trailing directory separator character in either FROM
+     or TO.  The substitution rule already implicitly contains them.  */
+  strip_trailing_directory_separator (argv[0]);
+  strip_trailing_directory_separator (argv[1]);
+
+  /* If a rule with the same "from" was previously defined, then
+     delete it.  This new rule replaces it.  */
+
+  rule = find_substitute_path_rule (argv[0]);
+  if (rule != NULL)
+    delete_substitute_path_rule (rule);
+      
+  /* Insert the new substitution rule.  */
+
+  add_substitute_path_rule (argv[0], argv[1]);
+}
+
 \f
 void
 _initialize_source (void)
@@ -1666,4 +1994,19 @@ Show number of source lines gdb will list by default."), NULL,
                            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.  This 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);
 }