]> git.cworth.org Git - grrobot/blobdiff - src/args.c
* README: Update to refer to cairo instead of Xr.
[grrobot] / src / args.c
index 1498dbb62ec4164634b408c36294c70dddbf4b56..9e8d34c13cdee8017f099a7ee84ddb8459ec19ff 100644 (file)
  * Author: Carl Worth <carl@theworths.org>
  */
 
+#include <stdio.h>
 #include <stdlib.h>
-#include <argp.h>
+#include <string.h>
+#include <libgen.h>
+#include <getopt.h>
 
 #include "args.h"
 
-const char *argp_program_version = "grrobot " VERSION;
+static const char ARGS_PROGRAM_VERSION[] = VERSION;
+static const char ARGS_PROGRAM_DESCRIPTION[] = "Ricochet Robot using GTK+ and cairo";
+static const char ARGS_PROGRAM_BUG_ADDRESS[] = "<cworth@cworth.org>";
 
-const char *argp_program_bug_address = "<carl@theworths.org>";
+static const char ARGS_PROGRAM_ARGDOC[] = "[<file>]";
 
-static char doc[] = "grrobot - Ricochet Robot using GTK+ and Xr";
+/* XXX: getopt is rather annoying in that you must maintain a
+ * string-encoding of the options in addition to the table. For
+ * example, to enable the sample display option below, one would have
+ * to add "d:" to the optstring.
+ *
+ * A useful exercise would be to write a function to generate the
+ * optstring from the table.
+ *
+ * The other annoying thing is that the table does not include help
+ * strings, so the args_help function below must also be maintained
+ * manually.
+ */
 
-static char args_doc[] = "[file]";
+enum {
+    ARGS_VAL_HELP = 256
+};
 
-static struct option options[] = {
-    {"host",           required_argument,      0,      'h'},
-    {"port",           required_argument,      0,      'p'},
-    {"user",           required_argument,      0,      'u'},
-    {"game",           required_argument,      0,      'g'},
-    {"watch",          no_argument,            0,      'w'},
-    {0,                0,                      0,      0}
+static const char args_optstring[] = "h:p:u:g:wHV";
+static const struct option args_options[] = {
+    /* name,           has_arg,flag,   val */
+    {"host",           1,      0,      'h'},
+    {"port",           1,      0,      'p'},
+    {"user",           1,      0,      'u'},
+    {"game",           1,      0,      'g'},
+    {"watch",          0,      0,      'w'},
+    {"help",           0,      0,      ARGS_VAL_HELP},
+    {"version",                0,      0,      'V'},
+    { 0 }
 };
 
-static error_t
-parse_opt (int key, char *arg, struct argp_state *state)
+static void
+args_help (const char *argv0)
 {
-    struct args *args = state->input;
-
-    switch (key) {
-    case 'h':
-       args->host = arg;
-       break;
-    case 'p':
-       args->port = arg;
-       break;
-    case 'u':
-       args->user = arg;
-       break;
-    case 'g':
-       args->game = arg;
-       break;
-    case 'w':
-       args->watch = 1;
-       break;
-
-    case ARGP_KEY_ARG:
-       args->file = arg;
-       break;
-
-    default:
-       return ARGP_ERR_UNKNOWN;
-    }
+    char *argv0_copy = strdup (argv0);
+    char *argv0_base = basename (argv0_copy);
 
-    return 0;
+    printf ("Usage: %s [OPTIONS] %s\n", argv0_base, ARGS_PROGRAM_ARGDOC);
+    printf ("%s - %s\n", argv0, ARGS_PROGRAM_DESCRIPTION);
+    printf ("Connect to HOST:PORT as USER and join GAME to play ricochet robot.\n");
+    printf ("Or play locally with the position from <file> if provided.\n");
+    printf ("\n");
+    printf ("  -h, --host=HOST\tHost to connect to running rrserve [%s]\n",
+           ARGS_HOST_DEFAULT);
+    printf ("  -p, --port=PORT\tPort to connect to on HOST [%s]\n",
+           ARGS_PORT_DEFAULT);
+    printf ("  -u, --user=NAME\tUsername to connect as [%s]\n",
+           ARGS_USER_DEFAULT);
+    printf ("  -g, --game=GAME\tGame to join initially [%s]\n",
+           ARGS_GAME_DEFAULT);
+    printf ("\n");
+    printf ("  -w, --watch    \tJust watch games instead of playing\n");
+    printf ("\n");
+    printf ("  -?, --help     \tPrint this help message\n");
+    printf ("  -V, --version  \tPrint program version\n");
+
+    free (argv0_copy);
 }
-           
-static struct argp argp = { options, parse_opt, args_doc, doc };
 
-error_t
-args_parse(args_t *args, int argc, char *argv[])
+static void
+args_usage (const char *argv0)
 {
+    char *argv0_copy = strdup (argv0);
+    char *argv0_base = basename (argv0_copy);
+
+    printf ("Usage: %s [OPTIONS] %s\n", argv0_base, ARGS_PROGRAM_ARGDOC);
+    printf ("Try `%s --help' for more information.\n", argv0_base);
+
+    free (argv0_copy);
+}
+
+int
+args_parse (args_t *args, int argc, char *argv[])
+{
+    int c;
+
     args->host = getenv ("RR_HOST");
     if (args->host == NULL)
        args->host = ARGS_HOST_DEFAULT;
@@ -99,8 +128,49 @@ args_parse(args_t *args, int argc, char *argv[])
     args->watch = 0;
 
     args->file = NULL;
+
+    while (1) {
+       c = getopt_long (argc, argv, args_optstring, args_options, NULL);
+       if (c == -1)
+           break;
+
+       switch (c) {
+       case 'h':
+           args->host = optarg;
+           break;
+       case 'p':
+           args->port = optarg;
+           break;
+       case 'u':
+           args->user = optarg;
+           break;
+       case 'g':
+           args->game = optarg;
+           break;
+       case 'w':
+           args->watch = 1;
+           break;
+       case 'V':
+           printf ("%s\n", ARGS_PROGRAM_VERSION);
+           exit (0);
+           break;
+       case ARGS_VAL_HELP:
+           args_help (argv[0]);
+           exit (0);
+           break;
+       case '?':
+           args_usage (argv[0]);
+           exit (1);
+           break;
+       default:
+           fprintf (stderr, "Unhandled option: %d\n", c);
+           exit (1);
+           break;
+       }
+    }
+    if (argc - optind == 1)
+       args->file = argv[optind];
+
     return 0;
-    return argp_parse (&argp, argc, argv,
-                      ARGP_LONG_ONLY,
-                      NULL, args);
 }