The old C-style was cumbersome make making one responsible for manually
create and pass a closure (separate function and *_info class for
closed-over variables).

I would have liked to redo this with C++ lambdas, so we could:

- derive environment types implicitly
- have fewer stray static functions
- make the return-type polymorphism type safe.

But I was advised on IRC that introducing template specializations in
the driver would a open compile time performance can of worms. It was
instead suggested I do it the old OOP way: this patch.

The old OOP way I don't really like, as it doesn't really reduce
boilerplate, but at least the environment accessing is well-typed now
(no `data` to `info` casts), and the `info->` boilerplate is also gone.

Most of the diff is just fixing the indent after moving the functions
inside the new classes.

gcc/ChangeLog:

        * gcc.cc (for_each_path): Made method on class below.
        (class find_within_paths): Class below has virtual method for
        callback, instead of function and and data arguments.
        (struct add_to_obstack_info): Renamed without trailing _info.
        (struct add_to_obstack): Now inherits from find_within_paths.
        (add_to_obstack): Became the callback on the above class which
        inherited its name.
        (build_search_list): Updated to use add_to_obstack.
        (struct file_at_path_info): Renamed without trailing _info.
        (struct file_at_path): Now inherits from find_within_paths.
        (file_at_path): Became the callback on the above class which
        inherited its name.
        (find_a_file): Updated to use new file_at_path.
        (struct spec_path_info): Renamed without trailing _info.
        (struct spec_path): Now inherits from find_within_paths.
        (spec_path): Became the callback on the above class which
        inherited its name.
        (do_spec_1): Updated to use new spec_path.

Signed-off-by: John Ericson <g...@johnericson.me>
---
 gcc/gcc.cc | 485 ++++++++++++++++++++++++++---------------------------
 1 file changed, 242 insertions(+), 243 deletions(-)

diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index bfa588ee5f0..ed2d9e22684 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -2774,190 +2774,194 @@ clear_failure_queue (void)
 
    Returns the value returned by CALLBACK.  */
 
-static void *
-for_each_path (const struct path_prefix *paths,
-              bool do_multi,
-              size_t extra_space,
-              void *(*callback) (char *, void *),
-              void *callback_info)
-{
-  struct prefix_list *pl;
-  const char *multi_dir = NULL;
-  const char *multi_os_dir = NULL;
-  const char *multiarch_suffix = NULL;
-  const char *multi_suffix;
-  const char *just_multi_suffix;
-  char *path = NULL;
-  void *ret = NULL;
-  bool skip_multi_dir = false;
-  bool skip_multi_os_dir = false;
-
-  multi_suffix = machine_suffix;
-  just_multi_suffix = just_machine_suffix;
-  if (do_multi && multilib_dir && strcmp (multilib_dir, ".") != 0)
-    {
-      multi_dir = concat (multilib_dir, dir_separator_str, NULL);
-      multi_suffix = concat (multi_suffix, multi_dir, NULL);
-      just_multi_suffix = concat (just_multi_suffix, multi_dir, NULL);
-    }
-  if (do_multi && multilib_os_dir && strcmp (multilib_os_dir, ".") != 0)
-    multi_os_dir = concat (multilib_os_dir, dir_separator_str, NULL);
-  if (multiarch_dir)
-    multiarch_suffix = concat (multiarch_dir, dir_separator_str, NULL);
+class find_within_paths
+{
+protected:
+  virtual void *
+  callback (char *);
 
-  while (1)
-    {
-      size_t multi_dir_len = 0;
-      size_t multi_os_dir_len = 0;
-      size_t multiarch_len = 0;
-      size_t suffix_len;
-      size_t just_suffix_len;
-      size_t len;
-
-      if (multi_dir)
-       multi_dir_len = strlen (multi_dir);
-      if (multi_os_dir)
-       multi_os_dir_len = strlen (multi_os_dir);
-      if (multiarch_suffix)
-       multiarch_len = strlen (multiarch_suffix);
-      suffix_len = strlen (multi_suffix);
-      just_suffix_len = strlen (just_multi_suffix);
-
-      if (path == NULL)
-       {
-         len = paths->max_len + extra_space + 1;
-         len += MAX (MAX (suffix_len, multi_os_dir_len), multiarch_len);
-         path = XNEWVEC (char, len);
-       }
+public:
+  void *
+  for_each_path (const struct path_prefix *paths,
+                bool do_multi,
+                size_t extra_space)
+  {
+    struct prefix_list *pl;
+    const char *multi_dir = NULL;
+    const char *multi_os_dir = NULL;
+    const char *multiarch_suffix = NULL;
+    const char *multi_suffix;
+    const char *just_multi_suffix;
+    char *path = NULL;
+    void *ret = NULL;
+    bool skip_multi_dir = false;
+    bool skip_multi_os_dir = false;
+
+    multi_suffix = machine_suffix;
+    just_multi_suffix = just_machine_suffix;
+    if (do_multi && multilib_dir && strcmp (multilib_dir, ".") != 0)
+      {
+       multi_dir = concat (multilib_dir, dir_separator_str, NULL);
+       multi_suffix = concat (multi_suffix, multi_dir, NULL);
+       just_multi_suffix = concat (just_multi_suffix, multi_dir, NULL);
+      }
+    if (do_multi && multilib_os_dir && strcmp (multilib_os_dir, ".") != 0)
+      multi_os_dir = concat (multilib_os_dir, dir_separator_str, NULL);
+    if (multiarch_dir)
+      multiarch_suffix = concat (multiarch_dir, dir_separator_str, NULL);
 
-      for (pl = paths->plist; pl != 0; pl = pl->next)
-       {
-         len = strlen (pl->prefix);
-         memcpy (path, pl->prefix, len);
+    while (1)
+      {
+       size_t multi_dir_len = 0;
+       size_t multi_os_dir_len = 0;
+       size_t multiarch_len = 0;
+       size_t suffix_len;
+       size_t just_suffix_len;
+       size_t len;
+
+       if (multi_dir)
+         multi_dir_len = strlen (multi_dir);
+       if (multi_os_dir)
+         multi_os_dir_len = strlen (multi_os_dir);
+       if (multiarch_suffix)
+         multiarch_len = strlen (multiarch_suffix);
+       suffix_len = strlen (multi_suffix);
+       just_suffix_len = strlen (just_multi_suffix);
+
+       if (path == NULL)
+         {
+           len = paths->max_len + extra_space + 1;
+           len += MAX (MAX (suffix_len, multi_os_dir_len), multiarch_len);
+           path = XNEWVEC (char, len);
+         }
 
-         /* Look first in MACHINE/VERSION subdirectory.  */
-         if (!skip_multi_dir)
-           {
-             memcpy (path + len, multi_suffix, suffix_len + 1);
-             ret = callback (path, callback_info);
-             if (ret)
-               break;
-           }
+       for (pl = paths->plist; pl != 0; pl = pl->next)
+         {
+           len = strlen (pl->prefix);
+           memcpy (path, pl->prefix, len);
 
-         /* Some paths are tried with just the machine (ie. target)
-            subdir.  This is used for finding as, ld, etc.  */
-         if (!skip_multi_dir
-             && pl->require_machine_suffix == 2)
-           {
-             memcpy (path + len, just_multi_suffix, just_suffix_len + 1);
-             ret = callback (path, callback_info);
-             if (ret)
-               break;
-           }
+           /* Look first in MACHINE/VERSION subdirectory.  */
+           if (!skip_multi_dir)
+             {
+               memcpy (path + len, multi_suffix, suffix_len + 1);
+               ret = callback (path);
+               if (ret)
+                 break;
+             }
 
-         /* Now try the multiarch path.  */
-         if (!skip_multi_dir
-             && !pl->require_machine_suffix && multiarch_dir)
-           {
-             memcpy (path + len, multiarch_suffix, multiarch_len + 1);
-             ret = callback (path, callback_info);
-             if (ret)
-               break;
-           }
+           /* Some paths are tried with just the machine (ie. target)
+              subdir.  This is used for finding as, ld, etc.  */
+           if (!skip_multi_dir
+               && pl->require_machine_suffix == 2)
+             {
+               memcpy (path + len, just_multi_suffix, just_suffix_len + 1);
+               ret = callback (path);
+               if (ret)
+                 break;
+             }
 
-         /* Now try the base path.  */
-         if (!pl->require_machine_suffix
-             && !(pl->os_multilib ? skip_multi_os_dir : skip_multi_dir))
-           {
-             const char *this_multi;
-             size_t this_multi_len;
+           /* Now try the multiarch path.  */
+           if (!skip_multi_dir
+               && !pl->require_machine_suffix && multiarch_dir)
+             {
+               memcpy (path + len, multiarch_suffix, multiarch_len + 1);
+               ret = callback (path);
+               if (ret)
+                 break;
+             }
 
-             if (pl->os_multilib)
-               {
-                 this_multi = multi_os_dir;
-                 this_multi_len = multi_os_dir_len;
-               }
-             else
-               {
-                 this_multi = multi_dir;
-                 this_multi_len = multi_dir_len;
-               }
+           /* Now try the base path.  */
+           if (!pl->require_machine_suffix
+               && !(pl->os_multilib ? skip_multi_os_dir : skip_multi_dir))
+             {
+               const char *this_multi;
+               size_t this_multi_len;
 
-             if (this_multi_len)
-               memcpy (path + len, this_multi, this_multi_len + 1);
-             else
-               path[len] = '\0';
+               if (pl->os_multilib)
+                 {
+                   this_multi = multi_os_dir;
+                   this_multi_len = multi_os_dir_len;
+                 }
+               else
+                 {
+                   this_multi = multi_dir;
+                   this_multi_len = multi_dir_len;
+                 }
 
-             ret = callback (path, callback_info);
-             if (ret)
-               break;
-           }
-       }
-      if (pl)
-       break;
+               if (this_multi_len)
+                 memcpy (path + len, this_multi, this_multi_len + 1);
+               else
+                 path[len] = '\0';
 
-      if (multi_dir == NULL && multi_os_dir == NULL)
-       break;
+               ret = callback (path);
+               if (ret)
+                 break;
+             }
+         }
+       if (pl)
+         break;
 
-      /* Run through the paths again, this time without multilibs.
-        Don't repeat any we have already seen.  */
-      if (multi_dir)
-       {
-         free (CONST_CAST (char *, multi_dir));
-         multi_dir = NULL;
-         free (CONST_CAST (char *, multi_suffix));
-         multi_suffix = machine_suffix;
-         free (CONST_CAST (char *, just_multi_suffix));
-         just_multi_suffix = just_machine_suffix;
-       }
-      else
-       skip_multi_dir = true;
-      if (multi_os_dir)
-       {
-         free (CONST_CAST (char *, multi_os_dir));
-         multi_os_dir = NULL;
-       }
-      else
-       skip_multi_os_dir = true;
-    }
+       if (multi_dir == NULL && multi_os_dir == NULL)
+         break;
 
-  if (multi_dir)
-    {
-      free (CONST_CAST (char *, multi_dir));
-      free (CONST_CAST (char *, multi_suffix));
-      free (CONST_CAST (char *, just_multi_suffix));
-    }
-  if (multi_os_dir)
-    free (CONST_CAST (char *, multi_os_dir));
-  if (ret != path)
-    free (path);
-  return ret;
-}
+       /* Run through the paths again, this time without multilibs.
+          Don't repeat any we have already seen.  */
+       if (multi_dir)
+         {
+           free (CONST_CAST (char *, multi_dir));
+           multi_dir = NULL;
+           free (CONST_CAST (char *, multi_suffix));
+           multi_suffix = machine_suffix;
+           free (CONST_CAST (char *, just_multi_suffix));
+           just_multi_suffix = just_machine_suffix;
+         }
+       else
+         skip_multi_dir = true;
+       if (multi_os_dir)
+         {
+           free (CONST_CAST (char *, multi_os_dir));
+           multi_os_dir = NULL;
+         }
+       else
+         skip_multi_os_dir = true;
+      }
+
+    if (multi_dir)
+      {
+       free (CONST_CAST (char *, multi_dir));
+       free (CONST_CAST (char *, multi_suffix));
+       free (CONST_CAST (char *, just_multi_suffix));
+      }
+    if (multi_os_dir)
+      free (CONST_CAST (char *, multi_os_dir));
+    if (ret != path)
+      free (path);
+    return ret;
+  }
+};
 
 /* Callback for build_search_list.  Adds path to obstack being built.  */
 
-struct add_to_obstack_info {
+struct add_to_obstack : find_within_paths {
   struct obstack *ob;
   bool check_dir;
   bool first_time;
-};
-
-static void *
-add_to_obstack (char *path, void *data)
-{
-  struct add_to_obstack_info *info = (struct add_to_obstack_info *) data;
 
-  if (info->check_dir && !is_directory (path))
-    return NULL;
+private:
+  void *callback (char *path) override
+  {
+    if (check_dir && !is_directory (path))
+      return NULL;
 
-  if (!info->first_time)
-    obstack_1grow (info->ob, PATH_SEPARATOR);
+    if (!first_time)
+      obstack_1grow (ob, PATH_SEPARATOR);
 
-  obstack_grow (info->ob, path, strlen (path));
+    obstack_grow (ob, path, strlen (path));
 
-  info->first_time = false;
-  return NULL;
-}
+    first_time = false;
+    return NULL;
+  }
+};
 
 /* Add or change the value of an environment variable, outputting the
    change to standard error if in verbose mode.  */
@@ -2979,7 +2983,7 @@ static char *
 build_search_list (const struct path_prefix *paths, const char *prefix,
                   bool check_dir, bool do_multi)
 {
-  struct add_to_obstack_info info;
+  struct add_to_obstack info;
 
   info.ob = &collect_obstack;
   info.check_dir = check_dir;
@@ -2988,7 +2992,7 @@ build_search_list (const struct path_prefix *paths, const 
char *prefix,
   obstack_grow (&collect_obstack, prefix, strlen (prefix));
   obstack_1grow (&collect_obstack, '=');
 
-  for_each_path (paths, do_multi, 0, add_to_obstack, &info);
+  info.for_each_path (paths, do_multi, 0);
 
   obstack_1grow (&collect_obstack, '\0');
   return XOBFINISH (&collect_obstack, char *);
@@ -3026,38 +3030,37 @@ access_check (const char *name, int mode)
    path.  If the resulting file exists in the right mode, return the
    full pathname to the file.  */
 
-struct file_at_path_info {
+struct file_at_path : find_within_paths {
   const char *name;
   const char *suffix;
   int name_len;
   int suffix_len;
   int mode;
-};
 
-static void *
-file_at_path (char *path, void *data)
-{
-  struct file_at_path_info *info = (struct file_at_path_info *) data;
-  size_t len = strlen (path);
+private:
+  void *callback (char *path) override
+  {
+    size_t len = strlen (path);
 
-  memcpy (path + len, info->name, info->name_len);
-  len += info->name_len;
+    memcpy (path + len, name, name_len);
+    len += name_len;
 
-  /* Some systems have a suffix for executable files.
-     So try appending that first.  */
-  if (info->suffix_len)
-    {
-      memcpy (path + len, info->suffix, info->suffix_len + 1);
-      if (access_check (path, info->mode) == 0)
-       return path;
-    }
+    /* Some systems have a suffix for executable files.
+       So try appending that first.  */
+    if (suffix_len)
+      {
+       memcpy (path + len, suffix, suffix_len + 1);
+       if (access_check (path, mode) == 0)
+         return path;
+      }
 
-  path[len] = '\0';
-  if (access_check (path, info->mode) == 0)
-    return path;
+    path[len] = '\0';
+    if (access_check (path, mode) == 0)
+      return path;
 
-  return NULL;
-}
+    return NULL;
+  }
+};
 
 /* Search for NAME using the prefix list PREFIXES.  MODE is passed to
    access to check permissions.  If DO_MULTI is true, search multilib
@@ -3068,7 +3071,7 @@ static char *
 find_a_file (const struct path_prefix *pprefix, const char *name, int mode,
             bool do_multi)
 {
-  struct file_at_path_info info;
+  struct file_at_path info;
 
   /* Find the filename in question (special case for absolute paths).  */
 
@@ -3086,9 +3089,8 @@ find_a_file (const struct path_prefix *pprefix, const 
char *name, int mode,
   info.suffix_len = strlen (info.suffix);
   info.mode = mode;
 
-  return (char*) for_each_path (pprefix, do_multi,
-                               info.name_len + info.suffix_len,
-                               file_at_path, &info);
+  return (char*) info.for_each_path (pprefix, do_multi,
+                                    info.name_len + info.suffix_len);
 }
 
 /* Specialization of find_a_file for programs that also takes into account
@@ -6008,65 +6010,64 @@ do_self_spec (const char *spec)
 
 /* Callback for processing %D and %I specs.  */
 
-struct spec_path_info {
+struct spec_path : find_within_paths {
   const char *option;
   const char *append;
   size_t append_len;
   bool omit_relative;
   bool separate_options;
   bool realpaths;
-};
 
-static void *
-spec_path (char *path, void *data)
-{
-  struct spec_path_info *info = (struct spec_path_info *) data;
-  size_t len = 0;
-  char save = 0;
+private:
+  void *callback (char *path) override
+  {
+    size_t len = 0;
+    char save = 0;
 
-  /* The path must exist; we want to resolve it to the realpath so that this
-     can be embedded as a runpath.  */
-  if (info->realpaths)
-     path = lrealpath (path);
+    /* The path must exist; we want to resolve it to the realpath so that this
+       can be embedded as a runpath.  */
+    if (realpaths)
+       path = lrealpath (path);
 
-  /* However, if we failed to resolve it - perhaps because there was a bogus
-     -B option on the command line, then punt on this entry.  */
-  if (!path)
-    return NULL;
+    /* However, if we failed to resolve it - perhaps because there was a bogus
+       -B option on the command line, then punt on this entry.  */
+    if (!path)
+      return NULL;
 
-  if (info->omit_relative && !IS_ABSOLUTE_PATH (path))
-    return NULL;
+    if (omit_relative && !IS_ABSOLUTE_PATH (path))
+      return NULL;
 
-  if (info->append_len != 0)
-    {
-      len = strlen (path);
-      memcpy (path + len, info->append, info->append_len + 1);
-    }
+    if (append_len != 0)
+      {
+       len = strlen (path);
+       memcpy (path + len, append, append_len + 1);
+      }
 
-  if (!is_directory (path))
-    return NULL;
+    if (!is_directory (path))
+      return NULL;
 
-  do_spec_1 (info->option, 1, NULL);
-  if (info->separate_options)
-    do_spec_1 (" ", 0, NULL);
+    do_spec_1 (option, 1, NULL);
+    if (separate_options)
+      do_spec_1 (" ", 0, NULL);
 
-  if (info->append_len == 0)
-    {
-      len = strlen (path);
-      save = path[len - 1];
-      if (IS_DIR_SEPARATOR (path[len - 1]))
-       path[len - 1] = '\0';
-    }
+    if (append_len == 0)
+      {
+       len = strlen (path);
+       save = path[len - 1];
+       if (IS_DIR_SEPARATOR (path[len - 1]))
+         path[len - 1] = '\0';
+      }
 
-  do_spec_1 (path, 1, NULL);
-  do_spec_1 (" ", 0, NULL);
+    do_spec_1 (path, 1, NULL);
+    do_spec_1 (" ", 0, NULL);
 
-  /* Must not damage the original path.  */
-  if (info->append_len == 0)
-    path[len - 1] = save;
+    /* Must not damage the original path.  */
+    if (append_len == 0)
+      path[len - 1] = save;
 
-  return NULL;
-}
+    return NULL;
+  }
+};
 
 /* True if we should compile INFILE. */
 
@@ -6250,7 +6251,7 @@ do_spec_1 (const char *spec, int inswitch, const char 
*soft_matched_part)
             that we search for startfiles.  */
          case 'D':
            {
-             struct spec_path_info info;
+             struct spec_path info;
 
              info.option = "-L";
              info.append_len = 0;
@@ -6267,13 +6268,13 @@ do_spec_1 (const char *spec, int inswitch, const char 
*soft_matched_part)
              info.separate_options = false;
              info.realpaths = false;
 
-             for_each_path (&startfile_prefixes, true, 0, spec_path, &info);
+             info.for_each_path (&startfile_prefixes, true, 0);
            }
            break;
 
          case 'P':
            {
-             struct spec_path_info info;
+             struct spec_path info;
 
              info.option = RUNPATH_OPTION;
              info.append_len = 0;
@@ -6282,7 +6283,7 @@ do_spec_1 (const char *spec, int inswitch, const char 
*soft_matched_part)
              /* We want to embed the actual paths that have the libraries.  */
              info.realpaths = true;
 
-             for_each_path (&startfile_prefixes, true, 0, spec_path, &info);
+             info.for_each_path (&startfile_prefixes, true, 0);
            }
            break;
 
@@ -6561,7 +6562,7 @@ do_spec_1 (const char *spec, int inswitch, const char 
*soft_matched_part)
 
          case 'I':
            {
-             struct spec_path_info info;
+             struct spec_path info;
 
              if (multilib_dir)
                {
@@ -6609,8 +6610,7 @@ do_spec_1 (const char *spec, int inswitch, const char 
*soft_matched_part)
              info.separate_options = true;
              info.realpaths = false;
 
-             for_each_path (&include_prefixes, false, info.append_len,
-                            spec_path, &info);
+             info.for_each_path (&include_prefixes, false, info.append_len);
 
              info.append = "include-fixed";
              if (*sysroot_hdrs_suffix_spec)
@@ -6623,14 +6623,13 @@ do_spec_1 (const char *spec, int inswitch, const char 
*soft_matched_part)
                  info.append = concat (info.append, dir_separator_str,
                                        multiarch_dir, NULL);
                  info.append_len = strlen (info.append);
-                 for_each_path (&include_prefixes, false, info.append_len,
-                                spec_path, &info);
+                 info.for_each_path (&include_prefixes, false,
+                                     info.append_len);
 
                  info.append = "include-fixed";
                }
              info.append_len = strlen (info.append);
-             for_each_path (&include_prefixes, false, info.append_len,
-                            spec_path, &info);
+             info.for_each_path (&include_prefixes, false, info.append_len);
            }
            break;
 
-- 
2.49.0

Reply via email to