SDL_test: make argument parsing extendable

This commit is contained in:
Anonymous Maarten 2024-06-22 00:51:56 +02:00 committed by Anonymous Maarten
parent 396dd16471
commit 09af4a8086
2 changed files with 655 additions and 578 deletions

View File

@ -53,6 +53,27 @@ typedef Uint32 SDLTest_VerboseFlags;
#define VERBOSE_AUDIO 0x00000010
#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
{
/* SDL init flags */
@ -134,6 +155,12 @@ typedef struct
SDL_Rect confine;
SDL_bool hide_cursor;
/* Options info */
SDLTest_ArgumentParser common_argparser;
SDLTest_ArgumentParser video_argparser;
SDLTest_ArgumentParser audio_argparser;
SDLTest_ArgumentParser *argparser;
} SDLTest_CommonState;
#include <SDL3/SDL_begin_code.h>

View File

@ -30,7 +30,9 @@ static const char *common_usage[] = {
"[-h | --help]",
"[--trackmem]",
"[--randmem]",
"[--info all|video|modes|render|event|event_motion]",
"[--log all|error|system|audio|video|render|input]",
NULL
};
static const char *video_usage[] = {
@ -50,7 +52,6 @@ static const char *video_usage[] = {
"[--hide-cursor]",
"[--high-pixel-density]",
"[--icon icon.bmp]",
"[--info all|video|modes|render|event|event_motion]",
"[--input-focus]",
"[--keyboard-grab]",
"[--logical-presentation disabled|match|stretch|letterbox|overscan|integer_scale]",
@ -73,13 +74,17 @@ static const char *video_usage[] = {
"[--utility]",
"[--video driver]",
"[--gpu driver]",
"[--vsync]"
"[--vsync]",
NULL
};
/* !!! FIXME: Float32? Sint32? */
static const char *audio_usage[] = {
"[--audio driver]", "[--rate N]", "[--format U8|S8|S16|S16LE|S16BE|S32|S32LE|S32BE|F32|F32LE|F32BE]",
"[--channels N]"
"[--audio driver]",
"[--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, ...)
@ -94,67 +99,16 @@ static void SDL_snprintfcat(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL
va_end(ap);
}
SDLTest_CommonState *SDLTest_CommonCreateState(char **argv, SDL_InitFlags flags)
static void SDLTest_CommonArgParserFinalize(void *data)
{
int i;
SDLTest_CommonState *state;
SDLTest_CommonState *state = data;
/* 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();
if (!(state->flags & SDL_INIT_VIDEO)) {
state->video_argparser.usage = NULL;
}
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) \
@ -166,9 +120,9 @@ void SDLTest_CommonDestroyState(SDLTest_CommonState *state) {
} \
*(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)) {
/* Print the usage message */
@ -217,29 +171,7 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
}
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) {
++index;
if (!argv[index]) {
@ -273,6 +205,43 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
}
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) {
++index;
if (!argv[index]) {
@ -621,25 +590,16 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
SDL_SetHint(SDL_HINT_GPU_DRIVER, state->gpudriver);
return 2;
}
} else {
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;
}
return 0;
}
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) {
++index;
if (!argv[index]) {
@ -716,37 +676,127 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
state->audio_channels = (Uint8) SDL_atoi(argv[index]);
return 2;
}
return 0;
}
if (SDL_strcmp(argv[index], "-NSDocumentRevisionsDebugMode") == 0) {
/* Debug flag sent by Xcode */
return 2;
SDLTest_CommonState *SDLTest_CommonCreateState(char **argv, SDL_InitFlags flags)
{
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;
}
void SDLTest_CommonLogUsage(SDLTest_CommonState *state, const char *argv0, const char **options)
{
int i;
SDLTest_ArgumentParser *argparser;
SDL_Log("USAGE: %s", argv0);
for (i = 0; i < SDL_arraysize(common_usage); i++) {
SDL_Log(" %s", common_usage[i]);
for (argparser = state->argparser; argparser; argparser = argparser->next) {
if (argparser->finalize) {
argparser->finalize(argparser->data);
}
if (state->flags & SDL_INIT_VIDEO) {
for (i = 0; i < SDL_arraysize(video_usage); i++) {
SDL_Log(" %s", video_usage[i]);
if (argparser->usage) {
int i;
for (i = 0; argparser->usage[i] != NULL; 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) {
int i;
for (i = 0; options[i] != NULL; i++) {
SDL_Log(" %s", options[i]);
}