JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
platform-independent arg parsing
[vor.git] / args.c
1 #include <string.h>
2 #include <stdlib.h>
3 #include "args.h"
4 #include "config.h"
5
6 // Gameplay Variations
7 float opt_bounciness;
8 float opt_gamespeed;
9 float opt_max_lead;
10
11 // Look and Feel
12 int opt_fullscreen;
13 int opt_music;
14 int opt_sound;
15
16 static void
17 show_help(void)
18 {
19         puts("Dodge the rocks until you die.");
20         putchar('\n');
21         puts(" Gameplay Variations:");
22     puts("  -b, --bounciness=N%        Keep N% of speed when hitting edges (default 50%)");
23         puts("  -g, --game-speed=N%        50-200% (default 100%)");
24         putchar('\n');
25         puts(" Look and Feel:");
26         puts("  -f, --full-screen");
27         puts("  -m, --music                Enable music");
28         puts("  -s, --silent               No explosion sounds or music");
29         putchar('\n');
30         puts(" Informational:");
31         puts("  -?, --help                 Give this help list");
32         puts("  -V, --version              Print program version");
33         putchar('\n');
34         puts("Mandatory or optional arguments to long options are also mandatory or optional");
35         puts("for any corresponding short options.");
36         putchar('\n');
37         puts("Report bugs to <josh@qualdan.com>.");
38 }
39
40 int
41 short_opt(char c, char *arg)
42 {
43         int i;
44
45         switch(c) {
46                 case 'b': if(!arg || sscanf(arg, "%d%%", &i) != 1 || i < 0 || i > 100) {
47                                           fprintf(stderr, "bad --bounciness (-b) value (should be 0-100%%)\n\n");
48                                           return 0;
49                                   }
50                                   opt_bounciness = (float)i / 100;
51                                   *arg = 0;
52                                   break;
53                 case 'f': opt_fullscreen = 1; break;
54                 case 'g': if(!arg || sscanf(arg, "%d%%", &i) != 1 || i < 50 || i > 200) {
55                                           fprintf(stderr, "bad --game-speed (-g) value (should be 50-200%%)\n\n");
56                                           return 0;
57                                   }
58                                   opt_gamespeed = (float)i / 100;
59                                   *arg = 0;
60                                   break;
61                 case 'l': if(sscanf(arg, "%f", &opt_max_lead) != 1) {
62                                           fprintf(stderr, "bad --max-lead (-l) value (must be a number)\n\n");
63                                           return 0;
64                                   }
65                                   opt_max_lead *= XSIZE;
66                                   *arg = 0;
67                                   break;
68                 case 'm': opt_music = 1; break;
69                 case 's': opt_sound = 0; opt_music = 0; break;
70                 case 'V':
71                                   printf("Variations on Rockdodger %s\n", VERSION);
72                                   exit(0);
73                 case '?':
74                 case 'h': return 0;
75                 default: 
76                                   fprintf(stderr, "unknown option -%c\n\n", c);
77                                   return 0;
78         }
79         return 1;
80 }
81
82 int
83 parse_short_opts(const char *s, char *arg)
84 {
85         while(s[1]) if(!short_opt(*s++, NULL)) return 0;
86         return short_opt(*s, arg);
87 }
88
89 static char *long_opts[] = {
90         "bounciness", "game-speed",
91         "full-screen", "music", "silent",
92         "help", "version"
93 };
94
95 static char short_opts[] = {
96         'b', 'g',
97         'f', 'm', 's',
98         'h', 'V'
99 };
100
101 int
102 parse_long_opt(const char *s, char *arg)
103 {
104         int i;
105         for(i=0; i<sizeof(short_opts); i++) {
106                 if(strcmp(s, long_opts[i]) == 0)
107                         return short_opt(short_opts[i], arg);
108         }
109         fprintf(stderr, "unknown long option --%s\n\n", s);
110         return 0;
111 }
112
113 void
114 init_opts(void)
115 {
116         // Gameplay Variations
117         opt_bounciness = 0.50; // lose 50% when you hit the screen edge.
118         opt_gamespeed = 1.00; // Run game at full speed.
119         opt_max_lead = 1.00*XSIZE;  // you can get 1 screen ahead.
120
121         // Look and Feel
122         opt_fullscreen = 0;
123         opt_sound = 1;
124         opt_music = 0;
125 }
126
127 int
128 parse_opts(int argc, char *argv[])
129 {
130         int i;
131         char *r;
132
133         init_opts();
134         for(i=1; i<argc; i++) {
135                 char *s, *arg;
136                 s = argv[i]; if(!*s) continue;
137                 if(*s++ != '-') {
138                         fputs("not an option\n\n", stderr);
139                         show_help();
140                         return 0;
141                 }
142
143                 arg = NULL;
144                 for(r=s; *r; r++) if(*r == '=') { *r = 0; arg = r+1; break; }
145                 if(!arg && (i+1 < argc)) arg = argv[i+1];
146
147                 if(*s == '-') {
148                         if(!parse_long_opt(s+1, arg)) { show_help(); return 0; }
149                 } else {
150                    if(!parse_short_opts(s, arg)) { show_help(); return 0; }
151                 }
152         }
153         return 1;
154 }