Use subparsers instead of stuffing everything into one parser
Jeffrey Pfau jeffrey@endrift.com
Sat, 26 Apr 2014 16:05:09 -0700
5 files changed,
129 insertions(+),
65 deletions(-)
M
src/platform/commandline.c
→
src/platform/commandline.c
@@ -13,6 +13,14 @@
#include <fcntl.h> #include <getopt.h> +#define GRAPHICS_OPTIONS "234f" +#define GRAPHICS_USAGE \ + "\nGraphics options:\n" \ + " -2 2x viewport\n" \ + " -3 3x viewport\n" \ + " -4 4x viewport\n" \ + " -f Sart full-screen" + static const char* _defaultFilename = "test.rom"; static const struct option _options[] = {@@ -27,14 +35,13 @@ #endif
{ 0, 0, 0, 0 } }; -int parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, const char* extraOptions) { +int _parseGraphicsArg(struct SubParser* parser, int option, const char* arg); + +int parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, struct SubParser* subparser) { memset(opts, 0, sizeof(*opts)); opts->fd = -1; opts->biosFd = -1; - opts->width = 240; - opts->height = 160; - int multiplier = 1; int ch; char options[64] = "b:s:"@@ -45,9 +52,9 @@ #ifdef USE_GDB_STUB
"g" #endif ; - if (extraOptions) { + if (subparser->extraOptions) { // TODO: modularize options to subparsers - strncat(options, extraOptions, sizeof(options) - strlen(options) - 1); + strncat(options, subparser->extraOptions, sizeof(options) - strlen(options) - 1); } while ((ch = getopt_long(argc, argv, options, _options, 0)) != -1) { switch (ch) {@@ -62,9 +69,6 @@ }
opts->debuggerType = DEBUGGER_CLI; break; #endif - case 'f': - opts->fullscreen = 1; - break; #ifdef USE_GDB_STUB case 'g': if (opts->debuggerType != DEBUGGER_NONE) {@@ -76,29 +80,13 @@ #endif
case 's': opts->frameskip = atoi(optarg); break; - case 'S': - opts->perfDuration = atoi(optarg); - break; - case '2': - if (multiplier != 1) { - return 0; - } - multiplier = 2; - break; - case '3': - if (multiplier != 1) { - return 0; - } - multiplier = 3; - break; - case '4': - if (multiplier != 1) { - return 0; + default: + if (subparser) { + if (!subparser->parse(subparser, ch, optarg)) { + return 0; + } } - multiplier = 4; break; - default: - return 0; } } argc -= optind;@@ -111,9 +99,53 @@ } else {
return 0; } opts->fd = open(opts->fname, O_RDONLY); - opts->width *= multiplier; - opts->height *= multiplier; return 1; +} + +void initParserForGraphics(struct SubParser* parser, struct GraphicsOpts* opts) { + parser->usage = GRAPHICS_USAGE; + parser->opts = opts; + parser->parse = _parseGraphicsArg; + parser->extraOptions = GRAPHICS_OPTIONS; + opts->multiplier = 1; + opts->fullscreen = 0; + opts->width = 240; + opts->height = 160; +} + +int _parseGraphicsArg(struct SubParser* parser, int option, const char* arg) { + struct GraphicsOpts* graphicsOpts = parser->opts; + switch (option) { + case 'f': + graphicsOpts->fullscreen = 1; + return 1; + case '2': + if (graphicsOpts->multiplier != 1) { + return 0; + } + graphicsOpts->multiplier = 2; + graphicsOpts->width *= graphicsOpts->multiplier; + graphicsOpts->height *= graphicsOpts->multiplier; + return 1; + case '3': + if (graphicsOpts->multiplier != 1) { + return 0; + } + graphicsOpts->multiplier = 3; + graphicsOpts->width *= graphicsOpts->multiplier; + graphicsOpts->height *= graphicsOpts->multiplier; + return 1; + case '4': + if (graphicsOpts->multiplier != 1) { + return 0; + } + graphicsOpts->multiplier = 4; + graphicsOpts->width *= graphicsOpts->multiplier; + graphicsOpts->height *= graphicsOpts->multiplier; + return 1; + default: + return 0; + } } struct ARMDebugger* createDebugger(struct StartupOptions* opts) {
M
src/platform/commandline.h
→
src/platform/commandline.h
@@ -14,19 +14,6 @@ #endif
DEBUGGER_MAX }; -#define GRAPHICS_OPTIONS "234f" -#define GRAPHICS_USAGE \ - "\nGraphics options:\n" \ - " -2 2x viewport\n" \ - " -3 3x viewport\n" \ - " -4 4x viewport\n" \ - " -f Sart full-screen" - -#define PERF_OPTIONS "S:" -#define PERF_USAGE \ - "\nBenchmark options:\n" \ - " -S SEC Run for SEC in-game seconds before exiting" - struct StartupOptions { int fd; const char* fname;@@ -35,19 +22,28 @@ int frameskip;
int rewindBufferCapacity; int rewindBufferInterval; - int width; - int height; - int fullscreen; - - int perfDuration; - enum DebuggerType debuggerType; int debugAtStart; }; -int parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, const char* extraOptions); +struct SubParser { + const char* usage; + int (*parse)(struct SubParser* parser, int option, const char* arg); + const char* extraOptions; + void* opts; +}; + +struct GraphicsOpts { + int multiplier; + int fullscreen; + int width; + int height; +}; + +int parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, struct SubParser* subparser); void usage(const char* arg0, const char* extraOptions); +void initParserForGraphics(struct SubParser* parser, struct GraphicsOpts* opts); struct ARMDebugger* createDebugger(struct StartupOptions* opts); #endif
M
src/platform/perf-main.c
→
src/platform/perf-main.c
@@ -2,12 +2,23 @@ #include "gba-thread.h"
#include "gba.h" #include "renderers/video-software.h" +#include <errno.h> #include <fcntl.h> #include <signal.h> #include <sys/time.h> +#define PERF_OPTIONS "S:" +#define PERF_USAGE \ + "\nBenchmark options:\n" \ + " -S SEC Run for SEC in-game seconds before exiting" + +struct PerfOpts { + int duration; +}; + static void _GBAPerfRunloop(struct GBAThread* context, int* frames); static void _GBAPerfShutdown(int signal); +static int _parsePerfOpts(struct SubParser* parser, int option, const char* arg); static struct GBAThread* _thread;@@ -17,8 +28,16 @@
struct GBAVideoSoftwareRenderer renderer; GBAVideoSoftwareRendererCreate(&renderer); + struct PerfOpts perfOpts = {}; + struct SubParser subparser = { + .usage = PERF_USAGE, + .parse = _parsePerfOpts, + .extraOptions = PERF_OPTIONS, + .opts = &perfOpts + }; + struct StartupOptions opts; - if (!parseCommandArgs(&opts, argc, argv, PERF_OPTIONS)) { + if (!parseCommandArgs(&opts, argc, argv, &subparser)) { usage(argv[0], PERF_USAGE); return 1; }@@ -39,7 +58,7 @@ GBAMapOptionsToContext(&opts, &context);
GBAThreadStart(&context); - int frames = opts.perfDuration; + int frames = perfOpts.duration; time_t start = time(0); _GBAPerfRunloop(&context, &frames); time_t end = time(0);@@ -96,3 +115,14 @@ pthread_mutex_lock(&_thread->stateMutex);
_thread->state = THREAD_EXITING; pthread_mutex_unlock(&_thread->stateMutex); } + +static int _parsePerfOpts(struct SubParser* parser, int option, const char* arg) { + struct PerfOpts* opts = parser->opts; + switch (option) { + case 'S': + opts->duration = strtol(arg, 0, 10); + return !errno; + default: + return 0; + } +}
M
src/platform/sdl/gl-main.c
→
src/platform/sdl/gl-main.c
@@ -62,15 +62,18 @@ struct GLSoftwareRenderer renderer;
GBAVideoSoftwareRendererCreate(&renderer.d); struct StartupOptions opts; - if (!parseCommandArgs(&opts, argc, argv, GRAPHICS_OPTIONS)) { - usage(argv[0], GRAPHICS_USAGE); + struct SubParser subparser; + struct GraphicsOpts graphicsOpts; + initParserForGraphics(&subparser, &graphicsOpts); + if (!parseCommandArgs(&opts, argc, argv, &subparser)) { + usage(argv[0], subparser.usage); return 1; } - renderer.viewportWidth = opts.width; - renderer.viewportHeight = opts.height; + renderer.viewportWidth = graphicsOpts.width; + renderer.viewportHeight = graphicsOpts.height; #if SDL_VERSION_ATLEAST(2, 0, 0) - renderer.events.fullscreen = opts.fullscreen; + renderer.events.fullscreen = graphicsOpts.fullscreen; #endif if (!_GBASDLInit(&renderer)) {
M
src/platform/sdl/sw-main.c
→
src/platform/sdl/sw-main.c
@@ -49,13 +49,16 @@ struct SoftwareRenderer renderer;
GBAVideoSoftwareRendererCreate(&renderer.d); struct StartupOptions opts; - if (!parseCommandArgs(&opts, argc, argv, GRAPHICS_OPTIONS)) { - usage(argv[0], GRAPHICS_USAGE); + struct SubParser subparser; + struct GraphicsOpts graphicsOpts; + initParserForGraphics(&subparser, &graphicsOpts); + if (!parseCommandArgs(&opts, argc, argv, &subparser)) { + usage(argv[0], subparser.usage); return 1; } - renderer.viewportWidth = opts.width; - renderer.viewportHeight = opts.height; + renderer.viewportWidth = graphicsOpts.width; + renderer.viewportHeight = graphicsOpts.height; if (!_GBASDLInit(&renderer)) { return 1;@@ -75,7 +78,7 @@
GBAMapOptionsToContext(&opts, &context); #if SDL_VERSION_ATLEAST(2, 0, 0) - renderer.events.fullscreen = opts.fullscreen; + renderer.events.fullscreen = graphicsOpts.fullscreen; renderer.window = SDL_CreateWindow("GBAc", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, renderer.viewportWidth, renderer.viewportHeight, SDL_WINDOW_OPENGL | (SDL_WINDOW_FULLSCREEN_DESKTOP * renderer.events.fullscreen)); SDL_GetWindowSize(renderer.window, &renderer.viewportWidth, &renderer.viewportHeight); renderer.events.window = renderer.window;@@ -100,7 +103,7 @@ #else
SDL_Surface* surface = SDL_GetVideoSurface(); SDL_LockSurface(surface); - renderer.ratio = renderer.viewportWidth / VIDEO_HORIZONTAL_PIXELS; + renderer.ratio = graphicsOpts.multiplier; if (renderer.ratio == 1) { renderer.d.outputBuffer = surface->pixels; #ifdef COLOR_16_BIT