# HG changeset patch
# User Markus Mützel <markus.muetzel@gmx.de>
# Date 1626000852 -7200
#      Sun Jul 11 12:54:12 2021 +0200
# Node ID f5ac11533e128795007f7a09ee27d21e803bfe78
# Parent  e2e493712818facff1d0962321970c4f56af5dbe
main.cc: Use getopt to parse command line arguments (bug #60886).

* src/main.in.cc (main): Use getopt to parse command line arguments.
* libinterp/options-usage.h (octave_getopt_options long_opts): Add command line
  options "force-gui" and "no-gui-libs" to struct.

diff -r e2e493712818 -r f5ac11533e12 libinterp/options-usage.h
--- a/libinterp/options-usage.h	Fri Jul 09 04:05:58 2021 -0400
+++ b/libinterp/options-usage.h	Sun Jul 11 12:54:12 2021 +0200
@@ -62,23 +62,24 @@
 #define DOC_CACHE_FILE_OPTION 2
 #define EVAL_OPTION 3
 #define EXEC_PATH_OPTION 4
-#define GUI_OPTION 5
-#define IMAGE_PATH_OPTION 6
-#define INFO_FILE_OPTION 7
-#define INFO_PROG_OPTION 8
-#define DEBUG_JIT_OPTION 9
-#define JIT_COMPILER_OPTION 10
-#define LINE_EDITING_OPTION 11
-#define NO_GUI_OPTION 12
-#define NO_INIT_FILE_OPTION 13
-#define NO_INIT_PATH_OPTION 14
-#define NO_LINE_EDITING_OPTION 15
-#define NO_SITE_FILE_OPTION 16
-#define PERSIST_OPTION 17
-#define SERVER_OPTION 18
-#define TEXI_MACROS_FILE_OPTION 19
-#define TRADITIONAL_OPTION 20
-#define EXPERIMENTAL_TERMINAL_WIDGET_OPTION 21
+#define EXPERIMENTAL_TERMINAL_WIDGET_OPTION 5
+#define GUI_OPTION 6
+#define IMAGE_PATH_OPTION 7
+#define INFO_FILE_OPTION 8
+#define INFO_PROG_OPTION 9
+#define DEBUG_JIT_OPTION 10
+#define JIT_COMPILER_OPTION 11
+#define LINE_EDITING_OPTION 12
+#define NO_GUI_OPTION 13
+#define NO_GUI_LIBS_OPTION 14
+#define NO_INIT_FILE_OPTION 15
+#define NO_INIT_PATH_OPTION 16
+#define NO_LINE_EDITING_OPTION 17
+#define NO_SITE_FILE_OPTION 18
+#define PERSIST_OPTION 19
+#define SERVER_OPTION 20
+#define TEXI_MACROS_FILE_OPTION 21
+#define TRADITIONAL_OPTION 22
 struct octave_getopt_options long_opts[] =
 {
   { "braindead",                octave_no_arg,       0, TRADITIONAL_OPTION },
@@ -90,6 +91,7 @@
   { "eval",                     octave_required_arg, 0, EVAL_OPTION },
   { "exec-path",                octave_required_arg, 0, EXEC_PATH_OPTION },
   { "experimental-terminal-widget", octave_no_arg,   0, EXPERIMENTAL_TERMINAL_WIDGET_OPTION },
+  { "force-gui",                octave_no_arg,       0, GUI_OPTION },
   { "gui",                      octave_no_arg,       0, GUI_OPTION },
   { "help",                     octave_no_arg,       0, 'h' },
   { "image-path",               octave_required_arg, 0, IMAGE_PATH_OPTION },
@@ -99,6 +101,7 @@
   { "jit-compiler",             octave_no_arg,       0, JIT_COMPILER_OPTION },
   { "line-editing",             octave_no_arg,       0, LINE_EDITING_OPTION },
   { "no-gui",                   octave_no_arg,       0, NO_GUI_OPTION },
+  { "no-gui-libs",              octave_no_arg,       0, NO_GUI_LIBS_OPTION },
   { "no-history",               octave_no_arg,       0, 'H' },
   { "no-init-file",             octave_no_arg,       0, NO_INIT_FILE_OPTION },
   { "no-init-path",             octave_no_arg,       0, NO_INIT_PATH_OPTION },
diff -r e2e493712818 -r f5ac11533e12 src/main.in.cc
--- a/src/main.in.cc	Fri Jul 09 04:05:58 2021 -0400
+++ b/src/main.in.cc	Sun Jul 11 12:54:12 2021 +0200
@@ -54,6 +54,7 @@
 #undef OCTAVE_API
 #define OCTAVE_API
 #include "fcntl-wrappers.h"
+#include "getopt-wrapper.h"
 #include "signal-wrappers.h"
 #include "unistd-wrappers.h"
 #include "wait-wrappers.h"
@@ -79,6 +80,7 @@
 #endif
 
 #include "display-available.h"
+#include "options-usage.h"
 #include "shared-fcns.h"
 
 #if defined (HAVE_OCTAVE_QT_GUI) && ! defined (OCTAVE_USE_WINDOWS_API)
@@ -270,108 +272,100 @@
   // --address-sanitizer option.
   static char **new_argv = new char * [argc + 2];
 
+  int next_optind = 1;
   int k = 1;
 
   bool warn_display = true;
   bool no_display = false;
 
-  for (int i = 1; i < argc; i++)
+  while (true)
     {
-      if (! strcmp (argv[i], "--no-gui-libs"))
-        {
-          // Run the version of Octave that is not linked with any GUI
-          // libraries.  It may not be possible to do plotting or any
-          // ui* calls, but it will be a little faster to start and
-          // require less memory.  Don't pass the --no-gui-libs option
-          // on as that option is not recognized by Octave.
+      int long_idx;
 
-          gui_libs = false;
-          file = octave_cli;
-        }
-      else if (! strcmp (argv[i], "--no-gui"))
-        {
-          // If we see this option, then we can just exec octave; we
-          // don't have to create a child process and wait for it to
-          // exit.  But do exec "octave-gui", not "octave-cli", because
-          // even if the --no-gui option is given, we may be asked to do
-          // some plotting or ui* calls.
+      int optc = octave_getopt_long_wrapper (argc, argv, short_opts, long_opts,
+                                         &long_idx);
+      int old_optind = next_optind;
+      next_optind = octave_optind_wrapper ();
+
+      if (optc < 0)
+        break;
 
-          start_gui = false;
-          new_argv[k++] = argv[i];
-        }
-      else if (! strcmp (argv[i], "--gui") || ! strcmp (argv[i], "--force-gui"))
+      switch (optc)
         {
-          // If we see this option, then we fork and exec octave with
-          // the --gui option, while continuing to handle signals in the
-          // terminal.
-          // Do not copy the arg now, since we still not know if the
-          // gui should really be launched.  Just store the index.
+          case NO_GUI_LIBS_OPTION:
+            // Run the version of Octave that is not linked with any GUI
+            // libraries.  It may not be possible to do plotting or any ui*
+            // calls, but it will be a little faster to start and require less
+            // memory.  Don't pass the --no-gui-libs option on as that option
+            // is not recognized by Octave.
+            gui_libs = false;
+            file = octave_cli;
+            break;
 
-          start_gui = true;
-          idx_gui = i;
-        }
-      else if (! strcmp (argv[i], "--experimental-terminal-widget"))
-        {
-          // If we see this option, then we don't fork and exec.
+          case NO_GUI_OPTION:
+            // If we see this option, then we can just exec octave; we don't
+            // have to create a child process and wait for it to exit.  But do
+            // exec "octave-gui", not "octave-cli", because even if the
+            // --no-gui option is given, we may be asked to do some plotting or
+            // ui* calls.
+            start_gui = false;
+            new_argv[k++] = argv[old_optind];
+            break;
 
-          fork_and_exec = false;
-          new_argv[k++] = argv[i];
-        }
-      else if (! strcmp (argv[i], "--persist"))
-        {
-          // FIXME: How can we reliably detect if this option appears
-          //        after a FILE argument.  In this case octave ignores
-          //        the option, but the GUI might still be launched if
-          //        --gui is also given.
+          case GUI_OPTION:
+            // If we see this option, then we fork and exec octave with the
+            // --gui option, while continuing to handle signals in the
+            // terminal.
+            // Do not copy the arg now, since we still not know if the gui
+            // should really be launched.  Just store the index.
+            start_gui = true;
+            idx_gui = old_optind;
+            break;
 
-          persist_octave = true;
-          new_argv[k++] = argv[i];
-        }
-      else if (! strcmp (argv[i], "--server"))
-        {
-          server = true;
-          new_argv[k++] = argv[i];
-        }
-      else if (! strcmp (argv[i], "--eval") ||
-               (strlen (argv[i]) > 0 && argv[i][0] != '-'))
-        {
-          eval_code = true;
-          new_argv[k++] = argv[i];
-        }
-      else if (! strcmp (argv[i], "--silent") || ! strcmp (argv[i], "--quiet"))
-        {
-          warn_display = false;
-          new_argv[k++] = argv[i];
-        }
-      else if (! strcmp (argv[i], "--no-window-system"))
-        {
-          no_display = true;
-          new_argv[k++] = argv[i];
+          case EXPERIMENTAL_TERMINAL_WIDGET_OPTION:
+            // If we see this option, then we don't fork and exec.
+            fork_and_exec = false;
+            new_argv[k++] = argv[old_optind];
+            break;
+
+          case PERSIST_OPTION:
+            // FIXME: How can we reliably detect if this option appears after
+            //        a FILE argument.  In this case octave ignores the option,
+            //        but the GUI might still be launched if --gui is also
+            //        given.
+            persist_octave = true;
+            new_argv[k++] = argv[old_optind];
+            break;
+
+          case SERVER_OPTION:
+            server = true;
+            new_argv[k++] = argv[old_optind];
+            break;
+
+          case EVAL_OPTION:
+          case 0:
+            eval_code = true;
+            for (int i = old_optind; i < next_optind; i++)
+              new_argv[k++] = argv[i];
+            break;
+
+          case 'q':
+            // options "--silent" or "--quiet"
+            warn_display = false;
+            new_argv[k++] = argv[old_optind];
+            break;
+
+          case 'W':
+            // option "--no-window-system"
+            no_display = true;
+            new_argv[k++] = argv[old_optind];
+            break;
+
+          default:
+            for (int i = old_optind; i < next_optind; i++)
+              new_argv[k++] = argv[i];
+            break;
         }
-      else if (strlen (argv[i]) > 1 && argv[i][0] == '-' && argv[i][1] != '-')
-        {
-          // Handle all single-letter command line options here; they may
-          // occur alone or may be aggregated into a single argument.
-
-          std::size_t len = strlen (argv[i]);
-
-          for (std::size_t j = 1; j < len; j++)
-            switch (argv[i][j])
-              {
-              case 'W':
-                no_display = true;
-                break;
-              case 'q':
-                warn_display = false;
-                break;
-              default:
-                break;
-              }
-
-          new_argv[k++] = argv[i];
-        }
-      else
-        new_argv[k++] = argv[i];
     }
 
   if (start_gui && eval_code && ! persist_octave)
