* 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 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:
- 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;
args->file = NULL;
- return argp_parse (&argp, argc, argv,
- ARGP_LONG_ONLY,
- NULL, args);
+ 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;
}