mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-05-15 17:28:28 +00:00
SDL_test: make argument parsing extendable
This commit is contained in:
parent
396dd16471
commit
09af4a8086
2 changed files with 655 additions and 578 deletions
|
@ -53,6 +53,27 @@ typedef Uint32 SDLTest_VerboseFlags;
|
||||||
#define VERBOSE_AUDIO 0x00000010
|
#define VERBOSE_AUDIO 0x00000010
|
||||||
#define VERBOSE_MOTION 0x00000020
|
#define VERBOSE_MOTION 0x00000020
|
||||||
|
|
||||||
|
/* !< Function pointer parsing one argument at argv[index], returning the number of parsed arguments,
|
||||||
|
* or a negative value when the argument is invalid */
|
||||||
|
typedef int (*SDLTest_ParseArgumentsFp)(void *data, char **argv, int index);
|
||||||
|
|
||||||
|
/* !< Finalize the argument parser. */
|
||||||
|
typedef void (*SDLTest_FinalizeArgumentParserFp)(void *arg);
|
||||||
|
|
||||||
|
typedef struct SDLTest_ArgumentParser
|
||||||
|
{
|
||||||
|
/* !< Parse an argument. */
|
||||||
|
SDLTest_ParseArgumentsFp parse_arguments;
|
||||||
|
/* !< Finalize this argument parser. Called once before parsing the first argument. */
|
||||||
|
SDLTest_FinalizeArgumentParserFp finalize;
|
||||||
|
/* !< Null-terminated array of arguments. Printed when running with --help. */
|
||||||
|
const char **usage;
|
||||||
|
/* !< User data, passed to all callbacks. */
|
||||||
|
void *data;
|
||||||
|
/* !< Next argument parser. */
|
||||||
|
struct SDLTest_ArgumentParser *next;
|
||||||
|
} SDLTest_ArgumentParser;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
/* SDL init flags */
|
/* SDL init flags */
|
||||||
|
@ -134,6 +155,12 @@ typedef struct
|
||||||
SDL_Rect confine;
|
SDL_Rect confine;
|
||||||
SDL_bool hide_cursor;
|
SDL_bool hide_cursor;
|
||||||
|
|
||||||
|
/* Options info */
|
||||||
|
SDLTest_ArgumentParser common_argparser;
|
||||||
|
SDLTest_ArgumentParser video_argparser;
|
||||||
|
SDLTest_ArgumentParser audio_argparser;
|
||||||
|
|
||||||
|
SDLTest_ArgumentParser *argparser;
|
||||||
} SDLTest_CommonState;
|
} SDLTest_CommonState;
|
||||||
|
|
||||||
#include <SDL3/SDL_begin_code.h>
|
#include <SDL3/SDL_begin_code.h>
|
||||||
|
|
|
@ -30,7 +30,9 @@ static const char *common_usage[] = {
|
||||||
"[-h | --help]",
|
"[-h | --help]",
|
||||||
"[--trackmem]",
|
"[--trackmem]",
|
||||||
"[--randmem]",
|
"[--randmem]",
|
||||||
|
"[--info all|video|modes|render|event|event_motion]",
|
||||||
"[--log all|error|system|audio|video|render|input]",
|
"[--log all|error|system|audio|video|render|input]",
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *video_usage[] = {
|
static const char *video_usage[] = {
|
||||||
|
@ -50,7 +52,6 @@ static const char *video_usage[] = {
|
||||||
"[--hide-cursor]",
|
"[--hide-cursor]",
|
||||||
"[--high-pixel-density]",
|
"[--high-pixel-density]",
|
||||||
"[--icon icon.bmp]",
|
"[--icon icon.bmp]",
|
||||||
"[--info all|video|modes|render|event|event_motion]",
|
|
||||||
"[--input-focus]",
|
"[--input-focus]",
|
||||||
"[--keyboard-grab]",
|
"[--keyboard-grab]",
|
||||||
"[--logical-presentation disabled|match|stretch|letterbox|overscan|integer_scale]",
|
"[--logical-presentation disabled|match|stretch|letterbox|overscan|integer_scale]",
|
||||||
|
@ -73,13 +74,17 @@ static const char *video_usage[] = {
|
||||||
"[--utility]",
|
"[--utility]",
|
||||||
"[--video driver]",
|
"[--video driver]",
|
||||||
"[--gpu driver]",
|
"[--gpu driver]",
|
||||||
"[--vsync]"
|
"[--vsync]",
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
/* !!! FIXME: Float32? Sint32? */
|
/* !!! FIXME: Float32? Sint32? */
|
||||||
static const char *audio_usage[] = {
|
static const char *audio_usage[] = {
|
||||||
"[--audio driver]", "[--rate N]", "[--format U8|S8|S16|S16LE|S16BE|S32|S32LE|S32BE|F32|F32LE|F32BE]",
|
"[--audio driver]",
|
||||||
"[--channels N]"
|
"[--rate N]",
|
||||||
|
"[--format U8|S8|S16|S16LE|S16BE|S32|S32LE|S32BE|F32|F32LE|F32BE]",
|
||||||
|
"[--channels N]",
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static void SDL_snprintfcat(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
static void SDL_snprintfcat(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
||||||
|
@ -94,67 +99,16 @@ static void SDL_snprintfcat(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDLTest_CommonState *SDLTest_CommonCreateState(char **argv, SDL_InitFlags flags)
|
static void SDLTest_CommonArgParserFinalize(void *data)
|
||||||
{
|
{
|
||||||
int i;
|
SDLTest_CommonState *state = data;
|
||||||
SDLTest_CommonState *state;
|
|
||||||
|
|
||||||
/* Do this first so we catch all allocations */
|
if (!(state->flags & SDL_INIT_VIDEO)) {
|
||||||
for (i = 1; argv[i]; ++i) {
|
state->video_argparser.usage = NULL;
|
||||||
if (SDL_strcasecmp(argv[i], "--trackmem") == 0) {
|
|
||||||
SDLTest_TrackAllocations();
|
|
||||||
} else if (SDL_strcasecmp(argv[i], "--randmem") == 0) {
|
|
||||||
SDLTest_RandFillAllocations();
|
|
||||||
}
|
}
|
||||||
|
if (!(state->flags & SDL_INIT_AUDIO)) {
|
||||||
|
state->audio_argparser.usage = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
state = (SDLTest_CommonState *)SDL_calloc(1, sizeof(*state));
|
|
||||||
if (!state) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize some defaults */
|
|
||||||
state->argv = argv;
|
|
||||||
state->flags = flags;
|
|
||||||
state->window_title = argv[0];
|
|
||||||
state->window_flags = SDL_WINDOW_HIDDEN;
|
|
||||||
state->window_x = SDL_WINDOWPOS_UNDEFINED;
|
|
||||||
state->window_y = SDL_WINDOWPOS_UNDEFINED;
|
|
||||||
state->window_w = DEFAULT_WINDOW_WIDTH;
|
|
||||||
state->window_h = DEFAULT_WINDOW_HEIGHT;
|
|
||||||
state->logical_presentation = SDL_LOGICAL_PRESENTATION_DISABLED;
|
|
||||||
state->logical_scale_mode = SDL_SCALEMODE_LINEAR;
|
|
||||||
state->num_windows = 1;
|
|
||||||
state->audio_freq = 22050;
|
|
||||||
state->audio_format = SDL_AUDIO_S16;
|
|
||||||
state->audio_channels = 2;
|
|
||||||
|
|
||||||
/* Set some very sane GL defaults */
|
|
||||||
state->gl_red_size = 8;
|
|
||||||
state->gl_green_size = 8;
|
|
||||||
state->gl_blue_size = 8;
|
|
||||||
state->gl_alpha_size = 8;
|
|
||||||
state->gl_buffer_size = 0;
|
|
||||||
state->gl_depth_size = 16;
|
|
||||||
state->gl_stencil_size = 0;
|
|
||||||
state->gl_double_buffer = 1;
|
|
||||||
state->gl_accum_red_size = 0;
|
|
||||||
state->gl_accum_green_size = 0;
|
|
||||||
state->gl_accum_blue_size = 0;
|
|
||||||
state->gl_accum_alpha_size = 0;
|
|
||||||
state->gl_stereo = 0;
|
|
||||||
state->gl_multisamplebuffers = 0;
|
|
||||||
state->gl_multisamplesamples = 0;
|
|
||||||
state->gl_retained_backing = 1;
|
|
||||||
state->gl_accelerated = -1;
|
|
||||||
state->gl_debug = 0;
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SDLTest_CommonDestroyState(SDLTest_CommonState *state) {
|
|
||||||
SDL_free(state);
|
|
||||||
SDLTest_LogAllocations();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SEARCHARG(dim) \
|
#define SEARCHARG(dim) \
|
||||||
|
@ -166,9 +120,9 @@ void SDLTest_CommonDestroyState(SDLTest_CommonState *state) {
|
||||||
} \
|
} \
|
||||||
*(dim)++ = '\0';
|
*(dim)++ = '\0';
|
||||||
|
|
||||||
int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
|
static int SDLTest_CommonStateParseCommonArguments(void *data, char **argv, int index)
|
||||||
{
|
{
|
||||||
char **argv = state->argv;
|
SDLTest_CommonState *state = data;
|
||||||
|
|
||||||
if ((SDL_strcasecmp(argv[index], "-h") == 0) || (SDL_strcasecmp(argv[index], "--help") == 0)) {
|
if ((SDL_strcasecmp(argv[index], "-h") == 0) || (SDL_strcasecmp(argv[index], "--help") == 0)) {
|
||||||
/* Print the usage message */
|
/* Print the usage message */
|
||||||
|
@ -217,29 +171,7 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (state->flags & SDL_INIT_VIDEO) {
|
|
||||||
if (SDL_strcasecmp(argv[index], "--video") == 0) {
|
|
||||||
++index;
|
|
||||||
if (!argv[index]) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
state->videodriver = argv[index];
|
|
||||||
SDL_SetHint(SDL_HINT_VIDEO_DRIVER, state->videodriver);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
if (SDL_strcasecmp(argv[index], "--renderer") == 0) {
|
|
||||||
++index;
|
|
||||||
if (!argv[index]) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
state->renderdriver = argv[index];
|
|
||||||
SDL_SetHint(SDL_HINT_RENDER_DRIVER, state->renderdriver);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
if (SDL_strcasecmp(argv[index], "--gldebug") == 0) {
|
|
||||||
state->gl_debug = 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (SDL_strcasecmp(argv[index], "--info") == 0) {
|
if (SDL_strcasecmp(argv[index], "--info") == 0) {
|
||||||
++index;
|
++index;
|
||||||
if (!argv[index]) {
|
if (!argv[index]) {
|
||||||
|
@ -273,6 +205,43 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (SDL_strcmp(argv[index], "-NSDocumentRevisionsDebugMode") == 0) {
|
||||||
|
/* Debug flag sent by Xcode */
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int SDLTest_CommonStateParseVideoArguments(void *data, char **argv, int index)
|
||||||
|
{
|
||||||
|
SDLTest_CommonState *state = data;
|
||||||
|
|
||||||
|
if (!(state->flags & SDL_INIT_VIDEO)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_strcasecmp(argv[index], "--video") == 0) {
|
||||||
|
++index;
|
||||||
|
if (!argv[index]) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
state->videodriver = argv[index];
|
||||||
|
SDL_SetHint(SDL_HINT_VIDEO_DRIVER, state->videodriver);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if (SDL_strcasecmp(argv[index], "--renderer") == 0) {
|
||||||
|
++index;
|
||||||
|
if (!argv[index]) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
state->renderdriver = argv[index];
|
||||||
|
SDL_SetHint(SDL_HINT_RENDER_DRIVER, state->renderdriver);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if (SDL_strcasecmp(argv[index], "--gldebug") == 0) {
|
||||||
|
state->gl_debug = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
if (SDL_strcasecmp(argv[index], "--display") == 0) {
|
if (SDL_strcasecmp(argv[index], "--display") == 0) {
|
||||||
++index;
|
++index;
|
||||||
if (!argv[index]) {
|
if (!argv[index]) {
|
||||||
|
@ -621,25 +590,16 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
|
||||||
SDL_SetHint(SDL_HINT_GPU_DRIVER, state->gpudriver);
|
SDL_SetHint(SDL_HINT_GPU_DRIVER, state->gpudriver);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
} else {
|
return 0;
|
||||||
if (SDL_strcasecmp(argv[index], "--info") == 0) {
|
|
||||||
++index;
|
|
||||||
if (!argv[index]) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (SDL_strcasecmp(argv[index], "all") == 0) {
|
|
||||||
state->verbose |= VERBOSE_EVENT;
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
if (SDL_strcasecmp(argv[index], "event") == 0) {
|
|
||||||
state->verbose |= VERBOSE_EVENT;
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->flags & SDL_INIT_AUDIO) {
|
static int SDLTest_CommonStateParseAudioArguments(void *data, char **argv, int index)
|
||||||
|
{
|
||||||
|
SDLTest_CommonState *state = data;
|
||||||
|
|
||||||
|
if (!(state->flags & SDL_INIT_AUDIO)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (SDL_strcasecmp(argv[index], "--audio") == 0) {
|
if (SDL_strcasecmp(argv[index], "--audio") == 0) {
|
||||||
++index;
|
++index;
|
||||||
if (!argv[index]) {
|
if (!argv[index]) {
|
||||||
|
@ -716,37 +676,127 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
|
||||||
state->audio_channels = (Uint8) SDL_atoi(argv[index]);
|
state->audio_channels = (Uint8) SDL_atoi(argv[index]);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
if (SDL_strcmp(argv[index], "-NSDocumentRevisionsDebugMode") == 0) {
|
|
||||||
/* Debug flag sent by Xcode */
|
SDLTest_CommonState *SDLTest_CommonCreateState(char **argv, SDL_InitFlags flags)
|
||||||
return 2;
|
{
|
||||||
|
int i;
|
||||||
|
SDLTest_CommonState *state;
|
||||||
|
|
||||||
|
/* Do this first so we catch all allocations */
|
||||||
|
for (i = 1; argv[i]; ++i) {
|
||||||
|
if (SDL_strcasecmp(argv[i], "--trackmem") == 0) {
|
||||||
|
SDLTest_TrackAllocations();
|
||||||
|
} else if (SDL_strcasecmp(argv[i], "--randmem") == 0) {
|
||||||
|
SDLTest_RandFillAllocations();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state = (SDLTest_CommonState *)SDL_calloc(1, sizeof(*state));
|
||||||
|
if (!state) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize some defaults */
|
||||||
|
state->argv = argv;
|
||||||
|
state->flags = flags;
|
||||||
|
state->window_title = argv[0];
|
||||||
|
state->window_flags = SDL_WINDOW_HIDDEN;
|
||||||
|
state->window_x = SDL_WINDOWPOS_UNDEFINED;
|
||||||
|
state->window_y = SDL_WINDOWPOS_UNDEFINED;
|
||||||
|
state->window_w = DEFAULT_WINDOW_WIDTH;
|
||||||
|
state->window_h = DEFAULT_WINDOW_HEIGHT;
|
||||||
|
state->logical_presentation = SDL_LOGICAL_PRESENTATION_DISABLED;
|
||||||
|
state->logical_scale_mode = SDL_SCALEMODE_LINEAR;
|
||||||
|
state->num_windows = 1;
|
||||||
|
state->audio_freq = 22050;
|
||||||
|
state->audio_format = SDL_AUDIO_S16;
|
||||||
|
state->audio_channels = 2;
|
||||||
|
|
||||||
|
/* Set some very sane GL defaults */
|
||||||
|
state->gl_red_size = 8;
|
||||||
|
state->gl_green_size = 8;
|
||||||
|
state->gl_blue_size = 8;
|
||||||
|
state->gl_alpha_size = 8;
|
||||||
|
state->gl_buffer_size = 0;
|
||||||
|
state->gl_depth_size = 16;
|
||||||
|
state->gl_stencil_size = 0;
|
||||||
|
state->gl_double_buffer = 1;
|
||||||
|
state->gl_accum_red_size = 0;
|
||||||
|
state->gl_accum_green_size = 0;
|
||||||
|
state->gl_accum_blue_size = 0;
|
||||||
|
state->gl_accum_alpha_size = 0;
|
||||||
|
state->gl_stereo = 0;
|
||||||
|
state->gl_multisamplebuffers = 0;
|
||||||
|
state->gl_multisamplesamples = 0;
|
||||||
|
state->gl_retained_backing = 1;
|
||||||
|
state->gl_accelerated = -1;
|
||||||
|
state->gl_debug = 0;
|
||||||
|
|
||||||
|
state->common_argparser.parse_arguments = SDLTest_CommonStateParseCommonArguments;
|
||||||
|
state->common_argparser.finalize = SDLTest_CommonArgParserFinalize;
|
||||||
|
state->common_argparser.usage = common_usage;
|
||||||
|
state->common_argparser.data = state;
|
||||||
|
state->common_argparser.next = &state->video_argparser;
|
||||||
|
|
||||||
|
state->video_argparser.parse_arguments = SDLTest_CommonStateParseVideoArguments;
|
||||||
|
state->video_argparser.finalize = NULL;
|
||||||
|
state->video_argparser.usage = video_usage;
|
||||||
|
state->video_argparser.data = state;
|
||||||
|
state->video_argparser.next = &state->audio_argparser;
|
||||||
|
|
||||||
|
state->audio_argparser.parse_arguments = SDLTest_CommonStateParseAudioArguments;
|
||||||
|
state->audio_argparser.finalize = NULL;
|
||||||
|
state->audio_argparser.usage = audio_usage;
|
||||||
|
state->audio_argparser.data = state;
|
||||||
|
|
||||||
|
state->argparser = &state->common_argparser;
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLTest_CommonDestroyState(SDLTest_CommonState *state) {
|
||||||
|
SDL_free(state);
|
||||||
|
SDLTest_LogAllocations();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
|
||||||
|
{
|
||||||
|
SDLTest_ArgumentParser *argparser = state->argparser;
|
||||||
|
|
||||||
|
/* Go back and parse arguments as we go */
|
||||||
|
while (argparser) {
|
||||||
|
if (argparser->parse_arguments) {
|
||||||
|
int consumed = argparser->parse_arguments(argparser->data, state->argv, index);
|
||||||
|
if (consumed != 0) {
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argparser = argparser->next;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDLTest_CommonLogUsage(SDLTest_CommonState *state, const char *argv0, const char **options)
|
void SDLTest_CommonLogUsage(SDLTest_CommonState *state, const char *argv0, const char **options)
|
||||||
{
|
{
|
||||||
int i;
|
SDLTest_ArgumentParser *argparser;
|
||||||
|
|
||||||
SDL_Log("USAGE: %s", argv0);
|
SDL_Log("USAGE: %s", argv0);
|
||||||
|
|
||||||
for (i = 0; i < SDL_arraysize(common_usage); i++) {
|
for (argparser = state->argparser; argparser; argparser = argparser->next) {
|
||||||
SDL_Log(" %s", common_usage[i]);
|
if (argparser->finalize) {
|
||||||
|
argparser->finalize(argparser->data);
|
||||||
}
|
}
|
||||||
|
if (argparser->usage) {
|
||||||
if (state->flags & SDL_INIT_VIDEO) {
|
int i;
|
||||||
for (i = 0; i < SDL_arraysize(video_usage); i++) {
|
for (i = 0; argparser->usage[i] != NULL; i++) {
|
||||||
SDL_Log(" %s", video_usage[i]);
|
SDL_Log(" %s", argparser->usage[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->flags & SDL_INIT_AUDIO) {
|
|
||||||
for (i = 0; i < SDL_arraysize(audio_usage); i++) {
|
|
||||||
SDL_Log(" %s", audio_usage[i]);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (options) {
|
if (options) {
|
||||||
|
int i;
|
||||||
for (i = 0; options[i] != NULL; i++) {
|
for (i = 0; options[i] != NULL; i++) {
|
||||||
SDL_Log(" %s", options[i]);
|
SDL_Log(" %s", options[i]);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue