This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [plugins][patch] Print plugin help.


> OK with:

You approved the second patch but not the first one :-)

I have attached both and updated them with the comments.

version.patch:

2009-04-08  Rafael Avila de Espindola  <espindola@google.com>
        * gcc-plugin.h (plugin_event): Add PLUGIN_INFO.
	(plugin_info): New.
	* opts.c (common_handle_option): Don't call print_version.
	* plugin.c (plugin_name_args): Add version.
	(register_plugin_info): New.
	(register_callback): Handle PLUGIN_INFO.
	(try_init_one_plugin): New.
	(init_one_plugin): Use try_init_one_plugin.
	(finalize_one_plugin): New.
	(finalize_plugins): New.
	(print_options): New.
	(print_version_one_plugin): New.
	(print_plugins_versions): New.
	* plugin.h (print_plugins_versions): New.
	(finalize_plugins): New.
	* toplev.c (compile_file): Don't call initialize_plugins.
	(print_version): Call print_plugins_versions.
	(toplev_main): Call initialize_plugins. Call print_version if needed.
	Call finalize_plugins.

help.patch:
2009-04-08  Rafael Avila de Espindola  <espindola@google.com>
	* common.opt (fhelp): Add Var(help_flag).
	* gcc-plugin.h (plugin_info): Add help.
	* plugin.c (plugin_name_args): Add help.
	(register_plugin_info): Set plugin->help.
	(print_help_one_plugin): New.
	(print_plugins_help): New.
	* plugin.h (print_plugins_help): New.
	* toplev.c (toplev_main): Call print_plugins_help if needed.

2009-04-08  Rafael Avila de Espindola  <espindola@google.com>
	* g++.dg/plugin/selfassign.c (plugin_init): Add version and help.
	* gcc.dg/plugin/selfassign.c (plugin_init): Add version and help.

Cheers,
-- 
Rafael Avila de Espindola

Google | Gordon House | Barrow Street | Dublin 4 | Ireland
Registered in Dublin, Ireland | Registration Number: 368047
diff --git a/gcc/gcc-plugin.h b/gcc/gcc-plugin.h
index 46f7e11..b6afbff 100644
--- a/gcc/gcc-plugin.h
+++ b/gcc/gcc-plugin.h
@@ -27,6 +27,7 @@ enum plugin_event
   PLUGIN_FINISH_UNIT,           /* Useful for summary processing.  */
   PLUGIN_CXX_CP_PRE_GENERICIZE, /* Allows to see low level AST in C++ FE.  */
   PLUGIN_FINISH,                /* Called before GCC exits.  */
+  PLUGIN_INFO,                  /* Infomation about the plugin */
   PLUGIN_EVENT_LAST             /* Dummy event used for indexing callback
                                    array.  */
 };
@@ -55,6 +56,11 @@ struct plugin_pass
   enum pass_positioning_ops pos_op; /* how to insert the new pass.  */
 };
 
+struct plugin_info
+{
+  const char *version;
+};
+
 /* Function type for the plugin initialization routine. Each plugin module
    should define this as an externally-visible function with name
    "plugin_init."
diff --git a/gcc/opts.c b/gcc/opts.c
index 8f3c0c7..b2bfbbf 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -1580,7 +1580,6 @@ common_handle_option (size_t scode, const char *arg, int value,
 
     case OPT_fversion:
     case OPT__version:
-      print_version (stderr, "");
       exit_after_options = true;
       break;
 
diff --git a/gcc/plugin.c b/gcc/plugin.c
index 9551eb8..1e6e0a8 100644
--- a/gcc/plugin.c
+++ b/gcc/plugin.c
@@ -43,6 +43,7 @@ struct plugin_name_args
   const char *full_name;
   int argc;
   struct plugin_argument *argv;
+  const char *version;
 };
 
 /* Hash table for the plugin_name_args objects created during command-line
@@ -427,6 +428,14 @@ register_pass (const char *plugin_name, struct plugin_pass *pass_info)
     }
 }
 
+static void
+register_plugin_info (const char* name, struct plugin_info *info)
+{
+  void **slot = htab_find_slot (plugin_name_args_tab, name, NO_INSERT);
+  struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
+  plugin->version = info->version;
+}
+
 /* Called from the plugin's initialization code. Register a single callback.
    This function can be called multiple times.
 
@@ -446,6 +455,9 @@ register_callback (const char *plugin_name,
       case PLUGIN_PASS_MANAGER_SETUP:
         register_pass (plugin_name, (struct plugin_pass *) user_data);
         break;
+      case PLUGIN_INFO:
+	register_plugin_info (plugin_name, (struct plugin_info *) user_data);
+	break;
       case PLUGIN_FINISH_STRUCT:
       case PLUGIN_FINISH_UNIT:
       case PLUGIN_CXX_CP_PRE_GENERICIZE:
@@ -511,18 +523,9 @@ invoke_plugin_callbacks (enum plugin_event event, void *gcc_data)
 #define PTR_UNION_AS_VOID_PTR(NAME) (NAME._q)
 #define PTR_UNION_AS_CAST_PTR(NAME) (NAME._nq)
 
-/* Routine to dlopen and initialize one plugin. This function is passed to
-   (and called by) the hash table traverse routine. Return 1 for the
-   htab_traverse to continue scan, 0 to stop.
-
-   SLOT - slot of the hash table element
-   INFO - auxiliary pointer handed to hash table traverse routine
-          (unused in this function)  */
-
-static int
-init_one_plugin (void **slot, void * ARG_UNUSED (info))
+static bool
+try_init_one_plugin (struct plugin_name_args *plugin)
 {
-  struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
   void *dl_handle;
   plugin_init_func plugin_init;
   char *err;
@@ -532,7 +535,7 @@ init_one_plugin (void **slot, void * ARG_UNUSED (info))
   if (!dl_handle)
     {
       error (G_("Cannot load plugin %s\n%s"), plugin->full_name, dlerror ());
-      return 1;
+      return 0;
     }
 
   /* Clear any existing error.  */
@@ -546,22 +549,37 @@ init_one_plugin (void **slot, void * ARG_UNUSED (info))
     {
       error (G_("Cannot find %s in plugin %s\n%s"), str_plugin_init_func_name,
              plugin->full_name, err);
-      return 1;
+      return 0;
     }
 
   /* Call the plugin-provided initialization routine with the arguments.  */
   if ((*plugin_init) (plugin->base_name, plugin->argc, plugin->argv))
     {
       error (G_("Fail to initialize plugin %s"), plugin->full_name);
-      return 1;
+      return 0;
     }
 
-  /* We can now delete the plugin_name_args object as it will no longer
-     be used. Note that base_name and argv fields (both of which were also
-     dynamically allocated) are not freed as they could still be used by
-     the plugin code.  */
-  XDELETE (plugin);
+  return 1;
+}
+
+/* Routine to dlopen and initialize one plugin. This function is passed to
+   (and called by) the hash table traverse routine. Return 1 for the
+   htab_traverse to continue scan, 0 to stop.
 
+   SLOT - slot of the hash table element
+   INFO - auxiliary pointer handed to hash table traverse routine
+          (unused in this function)  */
+
+static int
+init_one_plugin (void **slot, void * ARG_UNUSED (info))
+{
+  struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
+  bool ok = try_init_one_plugin (plugin);
+  if (!ok)
+    {
+      htab_remove_elt (plugin_name_args_tab, plugin->base_name);
+      XDELETE (plugin);
+    }
   return 1;
 }
 
@@ -577,8 +595,63 @@ initialize_plugins (void)
  
   /* Traverse and initialize each plugin specified in the command-line.  */
   htab_traverse_noresize (plugin_name_args_tab, init_one_plugin, NULL);
+}
+
+static int
+finalize_one_plugin (void **slot, void * ARG_UNUSED (info))
+{
+  struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
+  XDELETE (plugin);
+  return 1;
+}
+
+void
+finalize_plugins(void)
+{
+  if (!plugin_name_args_tab)
+    return;
+
+  /* We can now delete the plugin_name_args object as it will no longer
+     be used. Note that base_name and argv fields (both of which were also
+     dynamically allocated) are not freed as they could still be used by
+     the plugin code.  */
+
+  htab_traverse_noresize (plugin_name_args_tab, finalize_one_plugin, NULL);
 
   /* PLUGIN_NAME_ARGS_TAB is no longer needed, just delete it.  */
   htab_delete (plugin_name_args_tab);
   plugin_name_args_tab = NULL;
 }
+
+/* Used to pass options to htab_traverse callbacks. */
+struct print_options
+{
+  FILE *file;
+  const char *indent;
+};
+
+/* Print the version of one plugin. */
+static int
+print_version_one_plugin (void **slot, void *data)
+{
+  struct print_options *opt = (struct print_options *) data;
+  struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
+  const char *version = plugin->version ? plugin->version : "Unknown version.";
+
+  fprintf(opt->file, " %s%s: %s\n", opt->indent, plugin->base_name, version);
+  return 1;
+}
+
+/* Print the version of each plugin. */
+void
+print_plugins_versions (FILE *file, const char *indent)
+{
+  struct print_options opt;
+  opt.file = file;
+  opt.indent = indent;
+  if (!plugin_name_args_tab || htab_elements (plugin_name_args_tab) == 0)
+    return;
+
+  fprintf(file, "%sVersions of loaded plugins:\n", indent);
+  htab_traverse_noresize (plugin_name_args_tab, print_version_one_plugin, &opt);
+}
diff --git a/gcc/plugin.h b/gcc/plugin.h
index 95f0802..9823e03 100644
--- a/gcc/plugin.h
+++ b/gcc/plugin.h
@@ -30,5 +30,10 @@ extern void parse_plugin_arg_opt (const char *arg);
 extern void invoke_plugin_callbacks (enum plugin_event event, void *gcc_data);
 /* Main plugin initialization function.  */
 extern void initialize_plugins (void);
+/* Print the version of each plugin. */
+extern void print_plugins_versions (FILE *file, const char *indent);
+/* Free memory allocated by the plugin system. */
+extern void finalize_plugins(void);
+
 
 #endif /* PLUGIN_H */
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 63a6ddc..c038bfe 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -968,7 +968,6 @@ compile_file (void)
   init_final (main_input_filename);
   coverage_init (aux_base_name);
   statistics_init ();
-  initialize_plugins ();
 
   timevar_push (TV_PARSE);
 
@@ -1163,6 +1162,8 @@ print_version (FILE *file, const char *indent)
 	   file == stderr ? _(fmt4) : fmt4,
 	   indent, *indent != 0 ? " " : "",
 	   PARAM_VALUE (GGC_MIN_EXPAND), PARAM_VALUE (GGC_MIN_HEAPSIZE));
+
+  print_plugins_versions(file, indent);
 }
 
 #ifdef ASM_COMMENT_START
@@ -2270,6 +2271,11 @@ toplev_main (unsigned int argc, const char **argv)
 
   init_local_tick ();
 
+  initialize_plugins();
+
+  if (version_flag)
+    print_version (stderr, "");
+
   /* Exit early if we can (e.g. -help).  */
   if (!exit_after_options)
     do_compile ();
@@ -2280,6 +2286,7 @@ toplev_main (unsigned int argc, const char **argv)
   /* Invoke registered plugin callbacks if any.  */
   invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
 
+  finalize_plugins();
   if (errorcount || sorrycount)
     return (FATAL_EXIT_CODE);
 
diff --git a/gcc/common.opt b/gcc/common.opt
index 2d5188d..8e3e9fd 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -39,7 +39,7 @@ Alias for --help=target
 ;; program's insatiable desire to turn options starting with a
 ;; double dash (--) into options starting with a dash f (-f).
 fhelp
-Common
+Common Var(help_flag)
 
 fhelp=
 Common Joined
diff --git a/gcc/gcc-plugin.h b/gcc/gcc-plugin.h
index b6afbff..63ea129 100644
--- a/gcc/gcc-plugin.h
+++ b/gcc/gcc-plugin.h
@@ -59,6 +59,7 @@ struct plugin_pass
 struct plugin_info
 {
   const char *version;
+  const char *help;
 };
 
 /* Function type for the plugin initialization routine. Each plugin module
diff --git a/gcc/plugin.c b/gcc/plugin.c
index 1e6e0a8..a3c2ca7 100644
--- a/gcc/plugin.c
+++ b/gcc/plugin.c
@@ -44,6 +44,7 @@ struct plugin_name_args
   int argc;
   struct plugin_argument *argv;
   const char *version;
+  const char *help;
 };
 
 /* Hash table for the plugin_name_args objects created during command-line
@@ -434,6 +435,7 @@ register_plugin_info (const char* name, struct plugin_info *info)
   void **slot = htab_find_slot (plugin_name_args_tab, name, NO_INSERT);
   struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
   plugin->version = info->version;
+  plugin->help = info->help;
 }
 
 /* Called from the plugin's initialization code. Register a single callback.
@@ -655,3 +657,44 @@ print_plugins_versions (FILE *file, const char *indent)
   fprintf(file, "%sVersions of loaded plugins:\n", indent);
   htab_traverse_noresize (plugin_name_args_tab, print_version_one_plugin, &opt);
 }
+
+/* Print help for one plugin. */
+static int
+print_help_one_plugin (void **slot, void *data)
+{
+  struct print_options *opt = (struct print_options *) data;
+  struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
+  const char *help = plugin->help ? plugin->help : "No help available .";
+
+  char *dup = xstrdup (help);
+  char *p, *nl;
+  fprintf(opt->file, " %s%s:\n", opt->indent, plugin->base_name);
+
+  for (p = nl = dup; nl; p = nl)
+    {
+      nl = strchr (nl, '\n');
+      if (nl)
+	{
+	  *nl = '\0';
+	  nl++;
+	}
+      fprintf(opt->file, "   %s %s\n", opt->indent, p);
+    }
+
+  free (dup);
+  return 1;
+}
+
+/* Print help for each plugin. */
+void
+print_plugins_help (FILE *file, const char *indent)
+{
+  struct print_options opt;
+  opt.file = file;
+  opt.indent = indent;
+  if (!plugin_name_args_tab || htab_elements (plugin_name_args_tab) == 0)
+    return;
+
+  fprintf(file, "%sHelp for the loaded plugins:\n", indent);
+  htab_traverse_noresize (plugin_name_args_tab, print_help_one_plugin, &opt);
+}
diff --git a/gcc/plugin.h b/gcc/plugin.h
index 9823e03..42eff26 100644
--- a/gcc/plugin.h
+++ b/gcc/plugin.h
@@ -32,6 +32,8 @@ extern void invoke_plugin_callbacks (enum plugin_event event, void *gcc_data);
 extern void initialize_plugins (void);
 /* Print the version of each plugin. */
 extern void print_plugins_versions (FILE *file, const char *indent);
+/* Print help for each plugin. */
+extern void print_plugins_help (FILE *file, const char *indent);
 /* Free memory allocated by the plugin system. */
 extern void finalize_plugins(void);
 
diff --git a/gcc/testsuite/g++.dg/plugin/selfassign.c b/gcc/testsuite/g++.dg/plugin/selfassign.c
index 65b6269..d1dc9f8 100644
--- a/gcc/testsuite/g++.dg/plugin/selfassign.c
+++ b/gcc/testsuite/g++.dg/plugin/selfassign.c
@@ -299,6 +299,15 @@ plugin_init (const char *plugin_name, int argc, struct plugin_argument *argv)
   struct plugin_pass pass_info;
   bool enabled = true;
   int i;
+  struct plugin_info info = {"0.1",
+			     "check-operator-eq:\n" \
+			     "  check calls to operator=\n"\
+			     "no-check-operator-eq: bar\n" \
+			     "  don't check calls to operator=\n" \
+			     "enable:\n" \
+			     "  register the pass\n" \
+			     "disable: bar\n"
+                             "  don't register the pass\n" };
 
   /* Self-assign detection should happen after SSA is constructed.  */
   pass_info.pass = &pass_warn_self_assign.pass;
@@ -352,6 +361,8 @@ plugin_init (const char *plugin_name, int argc, struct plugin_argument *argv)
                  plugin_name, argv[i].key);
     }
 
+  register_callback (plugin_name, PLUGIN_INFO, NULL, &info);
+
   /* Register this new pass with GCC if the analysis is enabled.  */
   if (enabled)
     register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
diff --git a/gcc/testsuite/gcc.dg/plugin/selfassign.c b/gcc/testsuite/gcc.dg/plugin/selfassign.c
index 65b6269..d1dc9f8 100644
--- a/gcc/testsuite/gcc.dg/plugin/selfassign.c
+++ b/gcc/testsuite/gcc.dg/plugin/selfassign.c
@@ -299,6 +299,15 @@ plugin_init (const char *plugin_name, int argc, struct plugin_argument *argv)
   struct plugin_pass pass_info;
   bool enabled = true;
   int i;
+  struct plugin_info info = {"0.1",
+			     "check-operator-eq:\n" \
+			     "  check calls to operator=\n"\
+			     "no-check-operator-eq: bar\n" \
+			     "  don't check calls to operator=\n" \
+			     "enable:\n" \
+			     "  register the pass\n" \
+			     "disable: bar\n"
+                             "  don't register the pass\n" };
 
   /* Self-assign detection should happen after SSA is constructed.  */
   pass_info.pass = &pass_warn_self_assign.pass;
@@ -352,6 +361,8 @@ plugin_init (const char *plugin_name, int argc, struct plugin_argument *argv)
                  plugin_name, argv[i].key);
     }
 
+  register_callback (plugin_name, PLUGIN_INFO, NULL, &info);
+
   /* Register this new pass with GCC if the analysis is enabled.  */
   if (enabled)
     register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
diff --git a/gcc/toplev.c b/gcc/toplev.c
index c038bfe..da9b037 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -2276,6 +2276,9 @@ toplev_main (unsigned int argc, const char **argv)
   if (version_flag)
     print_version (stderr, "");
 
+  if (help_flag)
+    print_plugins_help (stderr, "");
+
   /* Exit early if we can (e.g. -help).  */
   if (!exit_after_options)
     do_compile ();

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]