JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
platform-independent arg parsing
authorJoshua Grams <josh@qualdan.com>
Wed, 12 Apr 2006 16:55:57 +0000 (16:55 +0000)
committerJoshua Grams <josh@qualdan.com>
Wed, 12 Apr 2006 16:55:57 +0000 (16:55 +0000)
Makefile
args.c
args.h
main.c

index 6c0356a..90e50a6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -85,7 +85,7 @@ sprite.o: sprite.h common.h
 
 vor: $(objects)
        @echo linking $@ from $^
-       @$(CC) $(ldflags) -o $@ $^
+       @$(CC) $^ $(ldflags) -o $@
 
 include gfx.mk
 
diff --git a/args.c b/args.c
index 06efba3..11214a8 100644 (file)
--- a/args.c
+++ b/args.c
@@ -1,4 +1,5 @@
-#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
 #include "args.h"
 #include "config.h"
 
@@ -12,31 +13,102 @@ int opt_fullscreen;
 int opt_music;
 int opt_sound;
 
+static void
+show_help(void)
+{
+       puts("Dodge the rocks until you die.");
+       putchar('\n');
+       puts(" Gameplay Variations:");
+    puts("  -b, --bounciness=N%        Keep N% of speed when hitting edges (default 50%)");
+       puts("  -g, --game-speed=N%        50-200% (default 100%)");
+       putchar('\n');
+       puts(" Look and Feel:");
+       puts("  -f, --full-screen");
+       puts("  -m, --music                Enable music");
+       puts("  -s, --silent               No explosion sounds or music");
+       putchar('\n');
+       puts(" Informational:");
+       puts("  -?, --help                 Give this help list");
+       puts("  -V, --version              Print program version");
+       putchar('\n');
+       puts("Mandatory or optional arguments to long options are also mandatory or optional");
+       puts("for any corresponding short options.");
+       putchar('\n');
+       puts("Report bugs to <josh@qualdan.com>.");
+}
+
+int
+short_opt(char c, char *arg)
+{
+       int i;
 
-#ifndef WIN32
+       switch(c) {
+               case 'b': if(!arg || sscanf(arg, "%d%%", &i) != 1 || i < 0 || i > 100) {
+                                         fprintf(stderr, "bad --bounciness (-b) value (should be 0-100%%)\n\n");
+                                         return 0;
+                                 }
+                                 opt_bounciness = (float)i / 100;
+                                 *arg = 0;
+                                 break;
+               case 'f': opt_fullscreen = 1; break;
+               case 'g': if(!arg || sscanf(arg, "%d%%", &i) != 1 || i < 50 || i > 200) {
+                                         fprintf(stderr, "bad --game-speed (-g) value (should be 50-200%%)\n\n");
+                                         return 0;
+                                 }
+                                 opt_gamespeed = (float)i / 100;
+                                 *arg = 0;
+                                 break;
+               case 'l': if(sscanf(arg, "%f", &opt_max_lead) != 1) {
+                                         fprintf(stderr, "bad --max-lead (-l) value (must be a number)\n\n");
+                                         return 0;
+                                 }
+                                 opt_max_lead *= XSIZE;
+                                 *arg = 0;
+                                 break;
+               case 'm': opt_music = 1; break;
+               case 's': opt_sound = 0; opt_music = 0; break;
+               case 'V':
+                                 printf("Variations on Rockdodger %s\n", VERSION);
+                                 exit(0);
+               case '?':
+               case 'h': return 0;
+               default: 
+                                 fprintf(stderr, "unknown option -%c\n\n", c);
+                                 return 0;
+       }
+       return 1;
+}
 
-error_t parse_opt(int, char*, struct argp_state *);
+int
+parse_short_opts(const char *s, char *arg)
+{
+       while(s[1]) if(!short_opt(*s++, NULL)) return 0;
+       return short_opt(*s, arg);
+}
 
-const char *argp_program_version = "Variations on Rockdodger " VERSION;
-const char *argp_program_bug_address = "<josh@qualdan.com>";
-static char doc[] = "Dodge the rocks until you die.";
-static struct argp_option opts[] = {
-       {0, 0, 0, 0, "Gameplay Variations:"},
-       {"bounciness", 'b', "N%", 0, "Keep N% of speed when hitting edges (default 50%)"},
-       {"game-speed", 'g', "N%", 0, "50-100% (default 100%)"},
-       {"max-lead", 'l', "#SCREENS", OPTION_HIDDEN,
-               "Max distance ahead you can get\n (default 1 screen; < 0 means no limit)"},
-       {0, 0, 0, 0, "Look and Feel:"},
-       {"full-screen", 'f', 0, 0, ""},
-       {"music", 'm', 0, 0, "Enable music"},
-       {"silent", 's', 0, 0, "No explosion sounds or music"},
-       {0, 0, 0, 0, "Informational:", -1},
-       {0}
+static char *long_opts[] = {
+       "bounciness", "game-speed",
+       "full-screen", "music", "silent",
+       "help", "version"
 };
 
-struct argp argp = { opts, &parse_opt, 0, doc };
+static char short_opts[] = {
+       'b', 'g',
+       'f', 'm', 's',
+       'h', 'V'
+};
 
-#endif // !WIN32
+int
+parse_long_opt(const char *s, char *arg)
+{
+       int i;
+       for(i=0; i<sizeof(short_opts); i++) {
+               if(strcmp(s, long_opts[i]) == 0)
+                       return short_opt(short_opts[i], arg);
+       }
+       fprintf(stderr, "unknown long option --%s\n\n", s);
+       return 0;
+}
 
 void
 init_opts(void)
@@ -52,43 +124,31 @@ init_opts(void)
        opt_music = 0;
 }
 
-#ifndef WIN32
-
-error_t
-parse_opt(int key, char *arg, struct argp_state *state)
+int
+parse_opts(int argc, char *argv[])
 {
        int i;
+       char *r;
 
-       switch(key) {
-               case 'b': if(!sscanf(arg, "%d%%", &i)) {
-                                         fprintf(stderr, "bad --bounciness (-b) value (should be 0-100%%)\n");
-                                         argp_state_help(state, stderr, ARGP_HELP_STD_HELP);
-                                         return EINVAL;
-                                 }
-                                 if(i < 50) i = 50; else if(i > 100) i = 100;
-                                 opt_bounciness = (float)i / 100;
-                                 break;
-               case 'f': opt_fullscreen = 1; break;
-               case 'g': if(!sscanf(arg, "%d%%", &i)) {
-                                         fprintf(stderr, "bad --gamespeed (-g) value (should be 50-100%%)\n");
-                                         argp_state_help(state, stderr, ARGP_HELP_STD_HELP);
-                                         return EINVAL;
-                                 }
-                                 if(i < 0) i = 0; else if(i > 200) i = 100;
-                                 opt_gamespeed = (float)i / 100;
-                                 break;
-               case 'l': if(!sscanf(arg, "%f", &opt_max_lead)) {
-                                         fprintf(stderr, "bad --max-lead (-l) value (must be a number)\n");
-                                         argp_state_help(state, stderr, ARGP_HELP_STD_HELP);
-                                         return EINVAL;
-                                 }
-                                 opt_max_lead *= XSIZE;
-                                 break;
-               case 'm': opt_music = 1; break;
-               case 's': opt_sound = 0; opt_music = 0; break;
-               default: return ARGP_ERR_UNKNOWN;
+       init_opts();
+       for(i=1; i<argc; i++) {
+               char *s, *arg;
+               s = argv[i]; if(!*s) continue;
+               if(*s++ != '-') {
+                       fputs("not an option\n\n", stderr);
+                       show_help();
+                       return 0;
+               }
+
+               arg = NULL;
+               for(r=s; *r; r++) if(*r == '=') { *r = 0; arg = r+1; break; }
+               if(!arg && (i+1 < argc)) arg = argv[i+1];
+
+               if(*s == '-') {
+                       if(!parse_long_opt(s+1, arg)) { show_help(); return 0; }
+               } else {
+                  if(!parse_short_opts(s, arg)) { show_help(); return 0; }
+               }
        }
-       return 0;
+       return 1;
 }
-
-#endif // !WIN32
diff --git a/args.h b/args.h
index bf49c60..a71fd63 100644 (file)
--- a/args.h
+++ b/args.h
@@ -13,10 +13,6 @@ extern int opt_fullscreen;
 extern int opt_music;
 extern int opt_sound;
 
-#ifndef WIN32
-struct argp argp;
-#endif
-
-void init_opts(void);
+int parse_opts(int argc, char *argv[]);
 
 #endif // VOR_ARGS_H
diff --git a/main.c b/main.c
index 60ee8f0..3f4486b 100644 (file)
--- a/main.c
+++ b/main.c
@@ -19,9 +19,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
-#ifndef WIN32
-# include <argp.h>
-#endif
 #include <math.h>
 #include <SDL.h>
 #include <SDL_image.h>
@@ -590,12 +587,15 @@ init_score_entry(void)
 
 void
 gameloop() {
-       Uint8 *keystate = SDL_GetKeyState(NULL);
+       SDL_Event e;
+       Uint8 *keystate;
        float tmp;
 
 
        for(;;) {
-               SDL_PumpEvents();
+               while(SDL_PollEvent(&e)) {
+                       if(e.type == SDL_QUIT) return;
+               }
                keystate = SDL_GetKeyState(NULL);
 
                if(!paused) {
@@ -766,10 +766,7 @@ gameloop() {
 
 int
 main(int argc, char **argv) {
-       init_opts();
-#ifndef WIN32
-       argp_parse(&argp, argc, argv, 0, 0, 0);
-#endif
+       if(!parse_opts(argc, argv)) return 1;
 
        if(init()) {
                printf ("ta: '%s'\n",initerror);