]> git.cworth.org Git - grrobot/blobdiff - src/args.c
* README: Update to refer to cairo instead of Xr.
[grrobot] / src / args.c
index aee5e940531a66a4ca54753aed555a419c779b12..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.
+ */
 
-/* XXX: SAMPLE: */
-static char args_doc[] = "<file>";
+enum {
+    ARGS_VAL_HELP = 256
+};
 
-static struct argp_option options[] = {
-    /* name,           key, arg,       flags, doc */
-    {"host",           'h', "HOST", 0, "Host running RR server"},
-    {"port",           'p', "PORT", 0, "Port of server"},
-    {"user",           'u', "USERNAME", 0, "Username for conection"},
-    {"game",           'g', "GAME", 0, "Game to join"},
-    {"watch",          'w', 0, 0,      "Watch instad of join"},
+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:
-       argp_usage (state);
-       break;
-
-/*
-    case ARGP_KEY_END:
-       if (state->arg_num < 1)
-           argp_usage (state);
-       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 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);
 }
-           
-static struct argp argp = { options, parse_opt, args_doc, doc };
 
-error_t
-args_parse(args_t *args, int argc, char *argv[])
+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;
@@ -107,5 +127,50 @@ args_parse(args_t *args, int argc, char *argv[])
        args->game = ARGS_GAME_DEFAULT;
     args->watch = 0;
 
-    return argp_parse (&argp, argc, argv, 0, 0, args);
+    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;
 }