abicompat: Make the commands more pleasant

Message ID 20211111023740.25611-1-tangmeng@uniontech.com
State New
Headers
Series abicompat: Make the commands more pleasant |

Commit Message

tangmeng Nov. 11, 2021, 2:37 a.m. UTC
  This submission uses getopt_long to replace strcmp
to obtain the options and parameters, which will
bring the user a better experience.
For example, the command will undergo the following
changes:
case1: # abicompat application lib1-path --lib-debug-info-dir1

  before prompt information:
    abicompat: wrong invocation
    try the --help option for more information
  now prompt information:
    abicompat: option '--lib-debug-info-dir1' requires an argument

Now it will be clearly pointed out which option is problematic.

case2: # abicompat application lib1-path --lib-debug-info-dir1 \
dir1 --unsupport-option

  before prompt information:
    abicompat: unrecognized option: --unsupport-option
    try the --help option for more information
  now prompt information:
    abicompat: unrecognized option '--unsupport-option'

Now it will be clear which option is not supported.

In addition, options have been added for application,
lib1, and lib2, and some prompt messages have been added.

            * tests/test-abicompat.cc (main): Adapt to the change of command.
            * tools/abicompat.cc: Add a new enum and an option long_options.
              (parse_command_line): Use getopt_long to replace strcmp.
              (main): Cooperate with the changes of parsw_command_line.

Signed-off-by: tangmeng <tangmeng@uniontech.com>
---
 tests/test-abicompat.cc |   4 +-
 tools/abicompat.cc      | 260 ++++++++++++++++++++--------------------
 2 files changed, 135 insertions(+), 129 deletions(-)
  

Patch

diff --git a/tests/test-abicompat.cc b/tests/test-abicompat.cc
index a1339eef..33341ae1 100644
--- a/tests/test-abicompat.cc
+++ b/tests/test-abicompat.cc
@@ -242,9 +242,9 @@  main()
 	abicompat += " --suppressions " + suppression_path;
       abicompat += " " + abicompat_options;
 
-      cmd = abicompat + " " + in_app_path + " " + in_lib1_path;
+      cmd = abicompat + " --application-path " + in_app_path + " --lib-v1-path " + in_lib1_path;
       if (!in_lib2_path.empty())
-	cmd += string(" ") + in_lib2_path;
+	cmd += string(" --lib-v2-path ") + in_lib2_path;
 
       cmd += " > " + out_report_path;
 
diff --git a/tools/abicompat.cc b/tools/abicompat.cc
index addd03a9..5f62ae56 100644
--- a/tools/abicompat.cc
+++ b/tools/abicompat.cc
@@ -26,6 +26,7 @@ 
 /// library provides.
 
 #include <unistd.h>
+#include <getopt.h>
 #include <cassert>
 #include <cstdio>
 #include <cstdlib>
@@ -89,16 +90,61 @@  public:
   {}
 }; // end struct options
 
+enum
+{
+  APPLICATION_PATH_OPTION,
+  LIB_V1_PATH_OPTION,
+  LIB_V2_PATH_OPTION,
+  LIST_UNDEFINED_SYSMBOLS_OPTION,
+  SHOW_BASE_NAMES_OPTION,
+  APP_DEBUG_INFO_DIR_OPTION,
+  LIB_DEBUG_INFO_DIR1_OPTION,
+  LIB_DEBUG_INFO_DIR2_OPTION,
+  SUPPRESSIONS_OPTION,
+  NO_REDUNDANT_OPTION,
+  NO_SHOW_LOCS_OPTION,
+  REDUNDANT_OPTION,
+  WEAK_MODE_OPTION,
+  HELP_OPTION,
+  VERSION_OPTION
+};
+
+const option long_options[] =
+{
+  {"application-path", required_argument, NULL, APPLICATION_PATH_OPTION},
+  {"lib-v1-path", required_argument, NULL, LIB_V1_PATH_OPTION},
+  {"lib-v2-path", required_argument, NULL, LIB_V2_PATH_OPTION},
+  {"list-undefined-symbols", no_argument, NULL, LIST_UNDEFINED_SYSMBOLS_OPTION},
+  {"show-base-names", no_argument, NULL, SHOW_BASE_NAMES_OPTION},
+  {"app-debug-info-dir", required_argument, NULL, APP_DEBUG_INFO_DIR_OPTION},
+  {"appd", required_argument, NULL, APP_DEBUG_INFO_DIR_OPTION},
+  {"lib-debug-info-dir1", required_argument, NULL, LIB_DEBUG_INFO_DIR1_OPTION},
+  {"libd1", required_argument, NULL, LIB_DEBUG_INFO_DIR1_OPTION},
+  {"lib-debug-info-dir2", required_argument, NULL, LIB_DEBUG_INFO_DIR2_OPTION},
+  {"libd2", required_argument, NULL, LIB_DEBUG_INFO_DIR2_OPTION},
+  {"suppressions", required_argument, NULL, SUPPRESSIONS_OPTION},
+  {"suppr", required_argument, NULL, SUPPRESSIONS_OPTION},
+  {"no-redundant", no_argument, NULL, NO_REDUNDANT_OPTION},
+  {"no-show-locs", no_argument, NULL, NO_SHOW_LOCS_OPTION},
+  {"redundant", no_argument, NULL, REDUNDANT_OPTION},
+  {"weak-mode", no_argument, NULL, WEAK_MODE_OPTION},
+  {"help", no_argument, NULL, HELP_OPTION},
+  {"version", no_argument, NULL, VERSION_OPTION},
+  {NULL, 0, NULL, 0}
+};
+
 static void
 display_usage(const string& prog_name, ostream& out)
 {
   emit_prefix(prog_name, out)
     << "usage: " << prog_name
-    << " [options] [application-path] [lib-v1-path] [lib-v2-path]"
+    << " [options] --application-path [application-path] "
+    << "--lib-v1-path [lib-v1-path] --lib-v2-path [lib-v2-path]"
     << "\n"
     << " where options can be: \n"
-    << "  --help|-h  display this help message\n"
-    << "  --version|-v  show program version information and exit\n"
+    << "  --application-path  set the path to the application\n"
+    << "  --lib-v1-path  set the path to the lib-v1\n"
+    << "  --lib-v2-path  set the path to the lib-v2\n"
     << "  --list-undefined-symbols|-u  display the list of "
     "undefined symbols of the application\n"
     << "  --show-base-names|b  in the report, only show the base names "
@@ -115,122 +161,84 @@  display_usage(const string& prog_name, ostream& out)
     << "  --redundant  display redundant changes (this is the default)\n"
     << "  --weak-mode  check compatibility between the application and "
     "just one version of the library.\n"
+    << "  --help|-h  display this help message\n"
+    << "  --version|-v  show program version information and exit\n"
     ;
 }
 
 static bool
 parse_command_line(int argc, char* argv[], options& opts)
 {
-  if (argc < 2)
-    return false;
+  int c;
 
-  for (int i = 1; i < argc; ++i)
+  while ((c = getopt_long(argc, argv, "vhub", long_options, NULL)) != -1)
     {
-      if (argv[i][0] != '-')
-	{
-	  if (opts.app_path.empty())
-	    opts.app_path = argv[i];
-	  else if (opts.lib1_path.empty())
-	    opts.lib1_path = argv[i];
-	  else if (opts.lib2_path.empty())
-	    opts.lib2_path = argv[i];
-	  else
-	    return false;
-	}
-      else if (!strcmp(argv[i], "--version")
-	       || !strcmp(argv[i], "-v"))
-	{
-	  opts.display_version = true;
-	  return true;
-	}
-      else if (!strcmp(argv[i], "--list-undefined-symbols")
-	       || !strcmp(argv[i], "-u"))
-	opts.list_undefined_symbols_only = true;
-      else if (!strcmp(argv[i], "--show-base-names")
-	       || !strcmp(argv[i], "-b"))
-	opts.show_base_names = true;
-      else if (!strcmp(argv[i], "--app-debug-info-dir")
-	       || !strcmp(argv[i], "--appd"))
-	{
-	  if (argc <= i + 1
-	      || argv[i + 1][0] == '-')
-	    return false;
-	  // elfutils wants the root path to the debug info to be
-	  // absolute.
-	  opts.app_di_root_path =
-	    abigail::tools_utils::make_path_absolute(argv[i + 1]);
-	  ++i;
-	}
-      else if (!strcmp(argv[i], "--lib-debug-info-dir1")
-	       || !strcmp(argv[i], "--libd1"))
-	{
-	  if (argc <= i + 1
-	      || argv[i + 1][0] == '-')
-	    return false;
-	  // elfutils wants the root path to the debug info to be
-	  // absolute.
-	  opts.lib1_di_root_path =
-	    abigail::tools_utils::make_path_absolute(argv[i + 1]);
-	  ++i;
-	}
-      else if (!strcmp(argv[i], "--lib-debug-info-dir2")
-	       || !strcmp(argv[i], "--libd2"))
-	{
-	  if (argc <= i + 1
-	      || argv[i + 1][0] == '-')
-	    return false;
-	  // elfutils wants the root path to the debug info to be
-	  // absolute.
-	  opts.lib2_di_root_path =
-	    abigail::tools_utils::make_path_absolute(argv[i + 1]);
-	  ++i;
-	}
-      else if (!strcmp(argv[i], "--suppressions")
-	       || !strcmp(argv[i], "--suppr"))
-	{
-	  int j = i + 1;
-	  if (j >= argc)
-	    return false;
-	  opts.suppression_paths.push_back(argv[j]);
-	  ++i;
-	}
-      else if (!strcmp(argv[i], "--redundant"))
+      switch(c)
         {
-	  opts.show_redundant = true;
-	  opts.redundant_opt_set = true;
-	}
-      else if (!strcmp(argv[i], "--no-redundant"))
-        {
-  	  opts.show_redundant = false;
-	  opts.no_redundant_opt_set = true;
-	}
-      else if (!strcmp(argv[i], "--no-show-locs"))
-	opts.show_locs = false;
-      else if (!strcmp(argv[i], "--help")
-	       || !strcmp(argv[i], "-h"))
-	{
-	  opts.display_help = true;
-	  return true;
-	}
-      else if (!strcmp(argv[i], "--weak-mode"))
-	opts.weak_mode = true;
-      else
-	{
-	  opts.unknow_option = argv[i];
-	  return false;
-	}
-    }
-
-  if (!opts.list_undefined_symbols_only)
-    {
-      if (opts.app_path.empty()
-	  || opts.lib1_path.empty())
-	return false;
-      if (!opts.weak_mode && opts.lib2_path.empty())
-	opts.weak_mode = true;
-    }
-
-  return true;
+        case 'v':
+        case VERSION_OPTION:
+          opts.display_version = true;
+          break;
+        case 'h':
+        case HELP_OPTION:
+          opts.display_help = true;
+          break;
+        case APPLICATION_PATH_OPTION:
+          opts.app_path = optarg;
+          break;
+        case LIB_V1_PATH_OPTION:
+          opts.lib1_path = optarg;
+          break;
+        case LIB_V2_PATH_OPTION:
+          opts.lib2_path = optarg;
+          break;
+        case 'u':
+        case LIST_UNDEFINED_SYSMBOLS_OPTION:
+          opts.list_undefined_symbols_only = true;
+          break;
+        case 'b':
+        case SHOW_BASE_NAMES_OPTION:
+          opts.show_base_names = true;
+          break;
+        case APP_DEBUG_INFO_DIR_OPTION:
+          opts.app_di_root_path =
+            abigail::tools_utils::make_path_absolute(optarg);
+          break;
+        case LIB_DEBUG_INFO_DIR1_OPTION:
+          // elfutils wants the root path to the debug info to be
+          // absolute.
+          opts.lib1_di_root_path =
+            abigail::tools_utils::make_path_absolute(optarg);
+          break;
+        case LIB_DEBUG_INFO_DIR2_OPTION:
+          // elfutils wants the root path to the debug info to be
+          // absolute.
+          opts.lib2_di_root_path =
+            abigail::tools_utils::make_path_absolute(optarg);
+          break;
+        case SUPPRESSIONS_OPTION:
+          opts.suppression_paths.push_back(optarg);
+          break;
+        case NO_REDUNDANT_OPTION:
+          opts.show_redundant = false;
+          opts.no_redundant_opt_set = true;
+          break;
+        case NO_SHOW_LOCS_OPTION:
+          opts.show_locs = false;
+          break;
+        case REDUNDANT_OPTION:
+          opts.show_redundant = true;
+          opts.redundant_opt_set = true;
+          break;
+        case WEAK_MODE_OPTION:
+          opts.weak_mode = true;
+          break;
+        default:
+          display_usage(argv[0], cout);
+          return 1;
+        }
+  }
+  return 0;
 }
 
 using abigail::tools_utils::check_file;
@@ -615,23 +623,8 @@  main(int argc, char* argv[])
 {
   options opts(argv[0]);
 
-  if (!parse_command_line(argc, argv, opts))
-    {
-      if (!opts.unknow_option.empty())
-	{
-	  emit_prefix(argv[0], cerr)
-	    << "unrecognized option: " << opts.unknow_option << "\n"
-	    << "try the --help option for more information\n";
-	  return (abigail::tools_utils::ABIDIFF_USAGE_ERROR
-		  | abigail::tools_utils::ABIDIFF_ERROR);
-	}
-
-      emit_prefix(argv[0], cerr)
-	<< "wrong invocation\n"
-	<< "try the --help option for more information\n";
-      return (abigail::tools_utils::ABIDIFF_USAGE_ERROR
-	      | abigail::tools_utils::ABIDIFF_ERROR);
-    }
+  if (parse_command_line(argc, argv, opts) != 0)
+    return 1;
 
   if (opts.display_help)
     {
@@ -648,6 +641,19 @@  main(int argc, char* argv[])
       return 0;
     }
 
+  if (!opts.list_undefined_symbols_only)
+    {
+      if (opts.app_path.empty()
+        || opts.lib1_path.empty())
+        {
+          emit_prefix(argv[0], cerr)
+	    << "The application path and lib-v1 path options must be set!\n";
+           return false;
+	}
+      if (!opts.weak_mode && opts.lib2_path.empty())
+       opts.weak_mode = true;
+    }
+
   if (opts.weak_mode && !opts.lib2_path.empty())
     {
       emit_prefix(argv[0], cout)