From 31a0147a720f2f0ef30df41512f41f43734662dd Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Tue, 9 May 2023 11:43:22 -0700 Subject: til_settings: introduce til_setting_spec_t concept vs. desc For recursive settings the individual setting being described needs to get added to a potentially different settings instance than the one being operated on at the top of the current setup_func phase. The settings instance being passed around for a setup_func to operate on is constified, mainly to try ensure modules don't start directly mucking with the settings. They're supposed to just describe what they want next and iterate back and forth, with the front-end creating the settings from the returned descs however is appropriate, eventually building up the settings to completion. But since it's the setup_func that decides which settings instance is appropriate for containing the setting.. at some point it must associate a settings instance with the desc it's producing, one that is going to be necessarily written to. So here I'm just turning the existing til_setting_desc_t to a "spec", unchanged. And introducing a new til_setting_desc_t embedding the spec, accompanied by a non-const til_settings_t* "container". Now what setup_funcs use to express settings are a spec, otherwise identically to before. Instead of cloning a desc to allocate it for returning to the front-end, the desc is created from a spec with the target settings instance passed in. This turns the desc step where we take a constified settings instance and cast it into a non-const a more formal act of going from spec->desc, binding the spec to a specific settings instance. It will also serve to isolate that hacky cast to a til_settings function, and all the accessors of til_setting_desc_t needing to operate on the containing settings instance can just do so. As of this commit, the container pointer is just sitting in the desc_t but isn't being made use of or even assigned yet. This is just to minimize the amount of churn happening in this otherwise mostly mechanical and sprawling commit. There's also been some small changes surrounding the desc generators and plumbing of the settings instance where there previously wasn't any. It's unclear to me if desc generators will stay desc generators or turn into spec generators. For now those are mostly just used by the drm_fb stuff anyways, modules haven't made use of them, so they can stay a little crufty harmlessly for now. --- src/drm_fb.c | 57 ++++++++++++----------- src/main.c | 19 ++++---- src/mem_fb.c | 2 +- src/modules/blinds/blinds.c | 4 +- src/modules/checkers/checkers.c | 14 +++--- src/modules/compose/compose.c | 4 +- src/modules/drizzle/drizzle.c | 4 +- src/modules/flui2d/flui2d.c | 10 ++--- src/modules/moire/moire.c | 2 +- src/modules/pixbounce/pixbounce.c | 4 +- src/modules/plato/plato.c | 4 +- src/modules/rkt/rkt.c | 14 +++--- src/modules/rtv/rtv.c | 12 ++--- src/modules/shapes/shapes.c | 14 +++--- src/modules/sparkler/sparkler.c | 8 ++-- src/modules/stars/stars.c | 2 +- src/modules/strobe/strobe.c | 2 +- src/modules/submit/submit.c | 2 +- src/modules/swarm/swarm.c | 2 +- src/modules/voronoi/voronoi.c | 6 +-- src/sdl_fb.c | 7 +-- src/setup.c | 40 ++++++++--------- src/til.c | 31 ++++++------- src/til_settings.c | 95 +++++++++++++++++++++------------------ src/til_settings.h | 20 ++++++--- 25 files changed, 199 insertions(+), 180 deletions(-) diff --git a/src/drm_fb.c b/src/drm_fb.c index c067b91..d23a2f7 100644 --- a/src/drm_fb.c +++ b/src/drm_fb.c @@ -69,16 +69,17 @@ static const char * connector_type_name(uint32_t type) { } -static int dev_desc_generator(til_setup_t *setup_context, const til_setting_desc_t **res_desc) +static int dev_desc_generator(const til_settings_t *settings, til_setup_t *setup_context, const til_setting_desc_t **res_desc) { - return til_setting_desc_clone(&(til_setting_desc_t){ - .name = "DRM device path", - .key = "dev", - .regex = "/dev/dri/card[0-9]", - .preferred = "/dev/dri/card0", - .values = NULL, - .annotations = NULL - }, res_desc); + return til_setting_desc_new( settings, + &(til_setting_spec_t){ + .name = "DRM device path", + .key = "dev", + .regex = "/dev/dri/card[0-9]", + .preferred = "/dev/dri/card0", + .values = NULL, + .annotations = NULL + }, res_desc); } @@ -146,7 +147,7 @@ static void free_strv(const char **strv) } -static int connector_desc_generator(til_setup_t *setup_context, const til_setting_desc_t **res_desc) +static int connector_desc_generator(const til_settings_t *settings, til_setup_t *setup_context, const til_setting_desc_t **res_desc) { drm_fb_setup_t *s = (drm_fb_setup_t *)setup_context; const char **connectors; @@ -158,14 +159,15 @@ static int connector_desc_generator(til_setup_t *setup_context, const til_settin if (r < 0) return r; - r = til_setting_desc_clone(&(til_setting_desc_t){ - .name = "DRM connector", - .key = "connector", - .regex = "[a-zA-Z0-9]+", - .preferred = connectors[0], - .values = connectors, - .annotations = NULL - }, res_desc); + r = til_setting_desc_new( settings, + &(til_setting_spec_t){ + .name = "DRM connector", + .key = "connector", + .regex = "[a-zA-Z0-9]+", + .preferred = connectors[0], + .values = connectors, + .annotations = NULL + }, res_desc); free_strv(connectors); return r; @@ -255,7 +257,7 @@ _out: } -static int mode_desc_generator(til_setup_t *setup_context, const til_setting_desc_t **res_desc) +static int mode_desc_generator(const til_settings_t *settings, til_setup_t *setup_context, const til_setting_desc_t **res_desc) { drm_fb_setup_t *s = (drm_fb_setup_t *)setup_context; const char **modes; @@ -267,14 +269,15 @@ static int mode_desc_generator(til_setup_t *setup_context, const til_setting_des if (r < 0) return r; - r = til_setting_desc_clone(&(til_setting_desc_t){ - .name = "DRM video mode", - .key = "mode", - .regex = "[0-9]+[xX][0-9]+@[0-9]+", - .preferred = modes[0], - .values = modes, - .annotations = NULL - }, res_desc); + r = til_setting_desc_new( settings, + &(til_setting_spec_t){ + .name = "DRM video mode", + .key = "mode", + .regex = "[0-9]+[xX][0-9]+@[0-9]+", + .preferred = modes[0], + .values = modes, + .annotations = NULL + }, res_desc); free_strv(modes); return r; diff --git a/src/main.c b/src/main.c index 5165d71..f99c74e 100644 --- a/src/main.c +++ b/src/main.c @@ -98,14 +98,15 @@ static int setup_video(const til_settings_t *settings, til_setting_t **res_setti }; int r; - r = til_setting_desc_clone(&(til_setting_desc_t){ - .name = "Video backend", - .key = NULL, - .regex = "[a-z]+", - .preferred = DEFAULT_VIDEO, - .values = values, - .annotations = NULL - }, res_desc); + r = til_setting_desc_new( settings, + &(til_setting_spec_t){ + .name = "Video backend", + .key = NULL, + .regex = "[a-z]+", + .preferred = DEFAULT_VIDEO, + .values = values, + .annotations = NULL + }, res_desc); if (r < 0) return r; @@ -370,7 +371,7 @@ int main(int argc, const char *argv[]) exit_if((r = setup_from_args(&rototiller.args, &setup, &failed_desc)) < 0, "unable to use args%s%s%s: %s", failed_desc ? " for setting \"" : "", - failed_desc ? failed_desc->key : "", + failed_desc ? failed_desc->spec.key : "", failed_desc ? "\"" : "", strerror(-r)); diff --git a/src/mem_fb.c b/src/mem_fb.c index c4633c5..cd65bcc 100644 --- a/src/mem_fb.c +++ b/src/mem_fb.c @@ -31,7 +31,7 @@ static int mem_fb_setup(const til_settings_t *settings, til_setting_t **res_sett int r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Virtual window size", .key = "size", .regex = "[1-9][0-9]*[xX][1-9][0-9]*", diff --git a/src/modules/blinds/blinds.c b/src/modules/blinds/blinds.c index f8c2597..6a0639b 100644 --- a/src/modules/blinds/blinds.c +++ b/src/modules/blinds/blinds.c @@ -152,7 +152,7 @@ static int blinds_setup(const til_settings_t *settings, til_setting_t **res_sett int r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Blinds orientation", .key = "orientation", .regex = "^(horizontal|vertical)", @@ -167,7 +167,7 @@ static int blinds_setup(const til_settings_t *settings, til_setting_t **res_sett return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Blinds count", .key = "count", .regex = "\\.[0-9]+", diff --git a/src/modules/checkers/checkers.c b/src/modules/checkers/checkers.c index bd651d5..a2a767d 100644 --- a/src/modules/checkers/checkers.c +++ b/src/modules/checkers/checkers.c @@ -462,7 +462,7 @@ static int checkers_setup(const til_settings_t *settings, til_setting_t **res_se int r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Checker size", .key = "size", .regex = "\\.[0-9]+", @@ -477,7 +477,7 @@ static int checkers_setup(const til_settings_t *settings, til_setting_t **res_se return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Checkers pattern", .key = "pattern", .preferred = pattern_values[0], @@ -491,7 +491,7 @@ static int checkers_setup(const til_settings_t *settings, til_setting_t **res_se return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Filled cell module (\"none\" for plain checkers)", .key = "fill_module", .preferred = fill_module_values[0], @@ -505,7 +505,7 @@ static int checkers_setup(const til_settings_t *settings, til_setting_t **res_se return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Checkers dynamics", .key = "dynamics", .preferred = dynamics_values[0], @@ -520,7 +520,7 @@ static int checkers_setup(const til_settings_t *settings, til_setting_t **res_se if (strcasecmp(dynamics, "odd") && strcasecmp(dynamics, "even")) { r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Checkers dynamics rate", .key = "dynamics_rate", .preferred = dynamics_rate_values[0], @@ -535,7 +535,7 @@ static int checkers_setup(const til_settings_t *settings, til_setting_t **res_se } r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Fill mode", .key = "fill", .preferred = fill_values[CHECKERS_DEFAULT_FILL], @@ -552,7 +552,7 @@ static int checkers_setup(const til_settings_t *settings, til_setting_t **res_se * if there's no texture or no underlay to sample, we should have a color to fallback on. */ r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Fill color", .key = "color", .preferred = TIL_SETTINGS_STR(CHECKERS_DEFAULT_COLOR), diff --git a/src/modules/compose/compose.c b/src/modules/compose/compose.c index 14a23f4..73c0181 100644 --- a/src/modules/compose/compose.c +++ b/src/modules/compose/compose.c @@ -260,7 +260,7 @@ static int compose_setup(const til_settings_t *settings, til_setting_t **res_set int r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Colon-separated list of module layers, in draw-order", .key = "layers", .preferred = "drizzle:stars:spiro:plato", @@ -274,7 +274,7 @@ static int compose_setup(const til_settings_t *settings, til_setting_t **res_set return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Module to use for source texture, \"none\" to disable", .key = "texture", .preferred = texture_values[0], diff --git a/src/modules/drizzle/drizzle.c b/src/modules/drizzle/drizzle.c index 9445da6..8a5607f 100644 --- a/src/modules/drizzle/drizzle.c +++ b/src/modules/drizzle/drizzle.c @@ -377,7 +377,7 @@ static int drizzle_setup(const til_settings_t *settings, til_setting_t **res_set int r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Puddle viscosity", .key = "viscosity", .regex = "\\.[0-9]+", @@ -392,7 +392,7 @@ static int drizzle_setup(const til_settings_t *settings, til_setting_t **res_set return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Overlay style", .key = "style", .regex = "[a-z]+", diff --git a/src/modules/flui2d/flui2d.c b/src/modules/flui2d/flui2d.c index 84306f5..f8e25d3 100644 --- a/src/modules/flui2d/flui2d.c +++ b/src/modules/flui2d/flui2d.c @@ -455,7 +455,7 @@ static int flui2d_setup(const til_settings_t *settings, til_setting_t **res_sett int r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Fluid viscosity", .key = "viscosity", .regex = "\\.[0-9]+", @@ -470,7 +470,7 @@ static int flui2d_setup(const til_settings_t *settings, til_setting_t **res_sett return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Fluid diffusion", .key = "diffusion", .regex = "\\.[0-9]+", @@ -485,7 +485,7 @@ static int flui2d_setup(const til_settings_t *settings, til_setting_t **res_sett return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Fluid decay", .key = "decay", .regex = "\\.[0-9]+", @@ -500,7 +500,7 @@ static int flui2d_setup(const til_settings_t *settings, til_setting_t **res_sett return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Fluid emitters style", .key = "emitters", .regex = "^(figure8|clockgrid)", @@ -516,7 +516,7 @@ static int flui2d_setup(const til_settings_t *settings, til_setting_t **res_sett if (!strcasecmp(emitters, "clockgrid")) { r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Fluid clockgrid emitters clock step", .key = "clockstep", .regex = "\\.[0-9]+", diff --git a/src/modules/moire/moire.c b/src/modules/moire/moire.c index 736a3bf..f7d0f3b 100644 --- a/src/modules/moire/moire.c +++ b/src/modules/moire/moire.c @@ -133,7 +133,7 @@ static int moire_setup(const til_settings_t *settings, til_setting_t **res_setti int r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Number of radial centers", .key = "centers", .regex = "\\.[0-9]+", diff --git a/src/modules/pixbounce/pixbounce.c b/src/modules/pixbounce/pixbounce.c index 7fa7f34..6f7502c 100644 --- a/src/modules/pixbounce/pixbounce.c +++ b/src/modules/pixbounce/pixbounce.c @@ -347,7 +347,7 @@ int pixbounce_setup(const til_settings_t *settings, til_setting_t **res_setting, int r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Pixmap size", .key = "pixmap_size", .regex = "(0|1|0\\.[0-9]{1,2})", @@ -362,7 +362,7 @@ int pixbounce_setup(const til_settings_t *settings, til_setting_t **res_setting, return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Pixmap", .key = "pixmap", .regex = ":[alnum]:+", diff --git a/src/modules/plato/plato.c b/src/modules/plato/plato.c index f952674..0b584c5 100644 --- a/src/modules/plato/plato.c +++ b/src/modules/plato/plato.c @@ -711,7 +711,7 @@ static int plato_setup(const til_settings_t *settings, til_setting_t **res_setti int r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Orbit rate and direction", .key = "orbit_rate", .regex = "\\.[0-9]+", /* FIXME */ @@ -726,7 +726,7 @@ static int plato_setup(const til_settings_t *settings, til_setting_t **res_setti return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Spin rate and direction", .key = "spin_rate", .regex = "\\.[0-9]+", /* FIXME */ diff --git a/src/modules/rkt/rkt.c b/src/modules/rkt/rkt.c index ac361c0..6947fbb 100644 --- a/src/modules/rkt/rkt.c +++ b/src/modules/rkt/rkt.c @@ -287,7 +287,7 @@ static int rkt_setup(const til_settings_t *settings, til_setting_t **res_setting * might work for getting full-blown demos sequenced via rocket. */ r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Module to sequence", .key = "seq_module", .preferred = "compose", @@ -300,7 +300,7 @@ static int rkt_setup(const til_settings_t *settings, til_setting_t **res_setting return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Rocket \"base\" label", .key = "base", .preferred = "tiller", @@ -313,7 +313,7 @@ static int rkt_setup(const til_settings_t *settings, til_setting_t **res_setting return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Beats per minute", .key = "bpm", .preferred = "125", @@ -326,7 +326,7 @@ static int rkt_setup(const til_settings_t *settings, til_setting_t **res_setting return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Rows per beat", .key = "rpb", .preferred = "8", @@ -339,7 +339,7 @@ static int rkt_setup(const til_settings_t *settings, til_setting_t **res_setting return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Editor connection toggle", .key = "connect", /* TODO: regex */ @@ -355,7 +355,7 @@ static int rkt_setup(const til_settings_t *settings, til_setting_t **res_setting if (!strcasecmp(connect, "on")) { r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Editor host", .key = "host", .preferred = "localhost", @@ -369,7 +369,7 @@ static int rkt_setup(const til_settings_t *settings, til_setting_t **res_setting return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Editor port", .key = "port", .preferred = TIL_SETTINGS_STR(SYNC_DEFAULT_PORT), diff --git a/src/modules/rtv/rtv.c b/src/modules/rtv/rtv.c index 661afc9..1984f30 100644 --- a/src/modules/rtv/rtv.c +++ b/src/modules/rtv/rtv.c @@ -322,7 +322,7 @@ static int rtv_setup(const til_settings_t *settings, til_setting_t **res_setting int r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Colon-separated list of channel modules, \"all\" for all", .key = "channels", .preferred = "compose", @@ -335,7 +335,7 @@ static int rtv_setup(const til_settings_t *settings, til_setting_t **res_setting return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Channel duration, in seconds", .key = "duration", .regex = "\\.[0-9]+", @@ -349,7 +349,7 @@ static int rtv_setup(const til_settings_t *settings, til_setting_t **res_setting return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Context duration, in seconds", .key = "context_duration", .regex = "\\.[0-9]+", @@ -363,7 +363,7 @@ static int rtv_setup(const til_settings_t *settings, til_setting_t **res_setting return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Caption duration, in seconds", .key = "caption_duration", .regex = "\\.[0-9]+", @@ -377,7 +377,7 @@ static int rtv_setup(const til_settings_t *settings, til_setting_t **res_setting return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Snow on channel-switch duration, in seconds", .key = "snow_duration", .regex = "\\.[0-9]+", @@ -391,7 +391,7 @@ static int rtv_setup(const til_settings_t *settings, til_setting_t **res_setting return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Module for snow (\"blank\" for blanking, \"none\" to disable)", .key = "snow_module", .preferred = RTV_DEFAULT_SNOW_MODULE, diff --git a/src/modules/shapes/shapes.c b/src/modules/shapes/shapes.c index 5073002..e0f020a 100644 --- a/src/modules/shapes/shapes.c +++ b/src/modules/shapes/shapes.c @@ -350,7 +350,7 @@ static int shapes_setup(const til_settings_t *settings, til_setting_t **res_sett int r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Shape type", .key = "type", .regex = "[a-zA-Z]+", @@ -365,7 +365,7 @@ static int shapes_setup(const til_settings_t *settings, til_setting_t **res_sett return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Scaling factor", .key = "scale", .regex = "(1|0?\\.[0-9]{1,2})", @@ -380,7 +380,7 @@ static int shapes_setup(const til_settings_t *settings, til_setting_t **res_sett return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Pinch factor", .key = "pinch", .regex = "(1|0?\\.[0-9]{1,2})", @@ -396,7 +396,7 @@ static int shapes_setup(const til_settings_t *settings, til_setting_t **res_sett if (strcasecmp(pinch, "0")) { r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Pinch spin factor", .key = "pinch_spin", .regex = "-?(0|1|0?\\.[0-9]{1,2})", @@ -411,7 +411,7 @@ static int shapes_setup(const til_settings_t *settings, til_setting_t **res_sett return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Number of pinches", .key = "pinches", .regex = "[0-9]+", @@ -428,7 +428,7 @@ static int shapes_setup(const til_settings_t *settings, til_setting_t **res_sett if (!strcasecmp(type, "star") || !strcasecmp(type, "pinwheel")) { r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Number of points", .key = "points", .regex = "[0-9]+", @@ -443,7 +443,7 @@ static int shapes_setup(const til_settings_t *settings, til_setting_t **res_sett return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Spin factor", .key = "spin", .regex = "-?(0|1|0?\\.[0-9]{1,2})", /* Derived from pixbounce, I'm sure when regexes start getting actually applied we're going to have to revisit all of these and fix them with plenty of lols. */ diff --git a/src/modules/sparkler/sparkler.c b/src/modules/sparkler/sparkler.c index 6b27813..50815e9 100644 --- a/src/modules/sparkler/sparkler.c +++ b/src/modules/sparkler/sparkler.c @@ -121,7 +121,7 @@ static int sparkler_setup(const til_settings_t *settings, til_setting_t **res_se /* TODO: return -EINVAL on parse errors? */ r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Show BSP-tree leaf-node bounding boxes", .key = "show_bsp_leafs", .preferred = "off", @@ -144,7 +144,7 @@ static int sparkler_setup(const til_settings_t *settings, til_setting_t **res_se }; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Minimum BSP-tree depth for shown leaf-nodes", .key = "show_bsp_leafs_min_depth", .preferred = "8", @@ -158,7 +158,7 @@ static int sparkler_setup(const til_settings_t *settings, til_setting_t **res_se } r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Show BSP-tree search broad-phase match candidates", .key = "show_bsp_matches", .preferred = "off", @@ -172,7 +172,7 @@ static int sparkler_setup(const til_settings_t *settings, til_setting_t **res_se if (!strcasecmp(show_bsp_matches, "on")) { r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Show only narrow-phase affected match results", .key = "show_bsp_matches_affected_only", .preferred = "off", diff --git a/src/modules/stars/stars.c b/src/modules/stars/stars.c index d57de53..8dc18b8 100644 --- a/src/modules/stars/stars.c +++ b/src/modules/stars/stars.c @@ -266,7 +266,7 @@ int stars_setup(const til_settings_t *settings, til_setting_t **res_setting, con int r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Rotation rate", .key = "rot_adj", .regex = "\\.[0-9]+", diff --git a/src/modules/strobe/strobe.c b/src/modules/strobe/strobe.c index 7d0acbf..fa245f7 100644 --- a/src/modules/strobe/strobe.c +++ b/src/modules/strobe/strobe.c @@ -114,7 +114,7 @@ static int strobe_setup(const til_settings_t *settings, til_setting_t **res_sett int r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Strobe period", .key = "period", .regex = "\\.[0-9]+", diff --git a/src/modules/submit/submit.c b/src/modules/submit/submit.c index 69e67f0..285ef92 100644 --- a/src/modules/submit/submit.c +++ b/src/modules/submit/submit.c @@ -340,7 +340,7 @@ static int submit_setup(const til_settings_t *settings, til_setting_t **res_sett int r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Bilinearly interpolate cell colors", .key = "bilerp", .regex = NULL, diff --git a/src/modules/swarm/swarm.c b/src/modules/swarm/swarm.c index e1b9640..adb8df8 100644 --- a/src/modules/swarm/swarm.c +++ b/src/modules/swarm/swarm.c @@ -430,7 +430,7 @@ static int swarm_setup(const til_settings_t *settings, til_setting_t **res_setti int r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Particle drawing style", .key = "style", .values = styles, diff --git a/src/modules/voronoi/voronoi.c b/src/modules/voronoi/voronoi.c index c258165..209310d 100644 --- a/src/modules/voronoi/voronoi.c +++ b/src/modules/voronoi/voronoi.c @@ -351,7 +351,7 @@ static int voronoi_setup(const til_settings_t *settings, til_setting_t **res_set int r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Voronoi cells quantity", .key = "cells", .regex = "^[0-9]+", @@ -366,7 +366,7 @@ static int voronoi_setup(const til_settings_t *settings, til_setting_t **res_set return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Constantly randomize cell placement", .key = "randomize", .regex = "^(on|off)", @@ -381,7 +381,7 @@ static int voronoi_setup(const til_settings_t *settings, til_setting_t **res_set return r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "Use faster, imperfect method", .key = "dirty", .regex = "^(on|off)", diff --git a/src/sdl_fb.c b/src/sdl_fb.c index 9eabbaf..24395a1 100644 --- a/src/sdl_fb.c +++ b/src/sdl_fb.c @@ -44,7 +44,7 @@ static int sdl_fb_setup(const til_settings_t *settings, til_setting_t **res_sett int r; r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "SDL fullscreen mode", .key = "fullscreen", .regex = NULL, @@ -60,7 +60,7 @@ static int sdl_fb_setup(const til_settings_t *settings, til_setting_t **res_sett if (!strcasecmp(fullscreen, "off")) { r = til_settings_get_and_describe_value(settings, - &(til_setting_desc_t){ + &(til_setting_spec_t){ .name = "SDL window size", .key = "size", .regex = "[1-9][0-9]*[xX][1-9][0-9]*", @@ -84,7 +84,8 @@ static int sdl_fb_setup(const til_settings_t *settings, til_setting_t **res_sett * describe when they're already present. It just needs something like an optional flag, * to be added in a future commit which will remove this hack. */ - r = til_setting_desc_clone( &(til_setting_desc_t){ + r = til_setting_desc_new( settings, + &(til_setting_spec_t){ .name = "SDL window size", .key = "size", .regex = "[1-9][0-9]*[xX][1-9][0-9]*", diff --git a/src/setup.c b/src/setup.c index 7c13ea0..8f9c5c1 100644 --- a/src/setup.c +++ b/src/setup.c @@ -29,16 +29,16 @@ int setup_interactively(til_settings_t *settings, int (*setup_func)(const til_se */ if (setting && !setting->desc) { /* XXX FIXME: this key as value exception is janky, make a helper to access the value or stop doing that. */ - r = til_setting_desc_check(desc, setting->value ? : setting->key); + r = til_setting_spec_check(&desc->spec, setting->value ? : setting->key); if (r < 0) { *res_failed_desc = desc; return r; } - if (desc->as_nested_settings && !setting->settings) { - setting->settings = til_settings_new(setting->key, setting->value); - if (!setting->settings) { + if (desc->spec.as_nested_settings && !setting->value_as_nested_settings) { + setting->value_as_nested_settings = til_settings_new(setting->key, setting->value); + if (!setting->value_as_nested_settings) { *res_failed_desc = desc; /* FIXME: til_settings_new() seems like it should return an errno, since it can encounter parse errors too? */ @@ -54,39 +54,39 @@ int setup_interactively(til_settings_t *settings, int (*setup_func)(const til_se if (!defaults) puts(""); - if (desc->values) { + if (desc->spec.values) { unsigned i, preferred = 0; int width = 0; - for (i = 0; desc->values[i]; i++) { + for (i = 0; desc->spec.values[i]; i++) { int len; - len = strlen(desc->values[i]); + len = strlen(desc->spec.values[i]); if (len > width) width = len; } /* multiple choice */ if (!defaults) - printf("%s:\n", desc->name); + printf("%s:\n", desc->spec.name); - for (i = 0; desc->values[i]; i++) { + for (i = 0; desc->spec.values[i]; i++) { if (!defaults) - printf("%2u: %*s%s%s\n", i, width, desc->values[i], - desc->annotations ? ": " : "", - desc->annotations ? desc->annotations[i] : ""); + printf("%2u: %*s%s%s\n", i, width, desc->spec.values[i], + desc->spec.annotations ? ": " : "", + desc->spec.annotations ? desc->spec.annotations[i] : ""); - if (!strcasecmp(desc->preferred, desc->values[i])) + if (!strcasecmp(desc->spec.preferred, desc->spec.values[i])) preferred = i; } if (!defaults) printf("Enter a value 0-%u [%u (%s)]: ", - i - 1, preferred, desc->preferred); + i - 1, preferred, desc->spec.preferred); } else { /* arbitrarily typed input */ if (!defaults) - printf("%s [%s]: ", desc->name, desc->preferred); + printf("%s [%s]: ", desc->spec.name, desc->spec.preferred); } if (!defaults) { @@ -100,11 +100,11 @@ int setup_interactively(til_settings_t *settings, int (*setup_func)(const til_se if (*buf == '\n') { /* accept preferred */ - til_settings_add_value(settings, desc->key, desc->preferred, NULL); + til_settings_add_value(settings, desc->spec.key, desc->spec.preferred, NULL); } else { buf[strlen(buf) - 1] = '\0'; - if (desc->values) { + if (desc->spec.values) { unsigned i, j, found; /* multiple choice, map numeric input to values entry */ @@ -114,9 +114,9 @@ int setup_interactively(til_settings_t *settings, int (*setup_func)(const til_se goto _next; } - for (found = i = 0; desc->values[i]; i++) { + for (found = i = 0; desc->spec.values[i]; i++) { if (i == j) { - til_settings_add_value(settings, desc->key, desc->values[i], NULL); + til_settings_add_value(settings, desc->spec.key, desc->spec.values[i], NULL); found = 1; break; } @@ -131,7 +131,7 @@ int setup_interactively(til_settings_t *settings, int (*setup_func)(const til_se } else { /* use typed input as setting, TODO: apply regex */ - til_settings_add_value(settings, desc->key, buf, NULL); + til_settings_add_value(settings, desc->spec.key, buf, NULL); } } _next: diff --git a/src/til.c b/src/til.c index 6c40207..e1b4907 100644 --- a/src/til.c +++ b/src/til.c @@ -285,14 +285,15 @@ int til_module_setup(const til_settings_t *settings, til_setting_t **res_setting annotations[i] = modules[i]->description; } - r = til_setting_desc_clone(&(til_setting_desc_t){ - .name = "Renderer module", - .key = NULL, - .regex = "[a-zA-Z0-9]+", - .preferred = DEFAULT_MODULE, - .values = values, - .annotations = annotations - }, res_desc); + r = til_setting_desc_new( settings, + &(til_setting_spec_t){ + .name = "Renderer module", + .key = NULL, + .regex = "[a-zA-Z0-9]+", + .preferred = DEFAULT_MODULE, + .values = values, + .annotations = annotations + }, res_desc); if (r < 0) return r; @@ -332,22 +333,22 @@ int til_module_randomize_setup(const til_module_t *module, unsigned seed, til_se return -ENOMEM; while (module->setup(settings, &setting, &desc, res_setup) > 0) { - if (desc->random) { + if (desc->spec.random) { char *value; - value = desc->random(rand_r(&seed)); - til_settings_add_value(settings, desc->key, value, desc); + value = desc->spec.random(rand_r(&seed)); + til_settings_add_value(settings, desc->spec.key, value, desc); free(value); - } else if (desc->values) { + } else if (desc->spec.values) { int n; - for (n = 0; desc->values[n]; n++); + for (n = 0; desc->spec.values[n]; n++); n = rand_r(&seed) % n; - til_settings_add_value(settings, desc->key, desc->values[n], desc); + til_settings_add_value(settings, desc->spec.key, desc->spec.values[n], desc); } else { - til_settings_add_value(settings, desc->key, desc->preferred, desc); + til_settings_add_value(settings, desc->spec.key, desc->spec.preferred, desc); } } diff --git a/src/til_settings.c b/src/til_settings.c index 84feed4..0328475 100644 --- a/src/til_settings.c +++ b/src/til_settings.c @@ -243,23 +243,23 @@ const char * til_settings_get_value_by_idx(const til_settings_t *settings, unsig * 0 when setting is present and described, res_value and res_setting will be populated w/non-NULL, and res_desc NULL in this case. * 1 when setting is either present but undescribed, or absent (and undescribed), res_* will be populated but res_{value,setting} may be NULL if absent and simply described. */ -int til_settings_get_and_describe_value(const til_settings_t *settings, const til_setting_desc_t *desc, const char **res_value, til_setting_t **res_setting, const til_setting_desc_t **res_desc) +int til_settings_get_and_describe_value(const til_settings_t *settings, const til_setting_spec_t *spec, const char **res_value, til_setting_t **res_setting, const til_setting_desc_t **res_desc) { til_setting_t *setting; const char *value; assert(settings); - assert(desc); + assert(spec); assert(res_value); - value = til_settings_get_value_by_key(settings, desc->key, &setting); + value = til_settings_get_value_by_key(settings, spec->key, &setting); if (!value || !setting->desc) { int r; assert(res_setting); assert(res_desc); - r = til_setting_desc_clone(desc, res_desc); + r = til_setting_desc_new(settings, spec, res_desc); if (r < 0) return r; @@ -318,11 +318,11 @@ int til_settings_apply_desc_generators(const til_settings_t *settings, const til const til_setting_desc_t *desc; int r; - r = g->func(setup, &desc); + r = g->func(settings, setup, &desc); if (r < 0) return r; - r = til_settings_get_and_describe_value(settings, desc, g->value_ptr, res_setting, res_desc); + r = til_settings_get_and_describe_value(settings, &desc->spec, g->value_ptr, res_setting, res_desc); til_setting_desc_free(desc); /* always need to cleanup the desc from g->func(), res_desc gets its own copy */ if (r) return r; @@ -338,49 +338,56 @@ int til_settings_apply_desc_generators(const til_settings_t *settings, const til /* convenience helper for creating a new setting description */ /* copies of everything supplied are made in newly allocated memory, stored @ res_desc */ /* returns < 0 on error */ -int til_setting_desc_clone(const til_setting_desc_t *desc, const til_setting_desc_t **res_desc) +int til_setting_desc_new(const til_settings_t *settings, const til_setting_spec_t *spec, const til_setting_desc_t **res_desc) { til_setting_desc_t *d; - assert(desc); - assert(desc->name); - assert(desc->preferred); /* XXX: require a preferred default? */ - assert(!desc->annotations || desc->values); + assert(settings); + assert(spec); + if (!spec->as_nested_settings) { /* this feels dirty, but sometimes you just need a bare nested settings created */ + assert(spec->name); + assert(spec->preferred); /* XXX: require a preferred default? */ + } + assert((!spec->annotations || spec->values) || spec->as_nested_settings); assert(res_desc); d = calloc(1, sizeof(til_setting_desc_t)); if (!d) return -ENOMEM; - d->name = strdup(desc->name); - if (desc->key) /* This is inappropriately subtle, but when key is NULL, the value will be the key, and there will be no value side at all. */ - d->key = strdup(desc->key); - if (desc->regex) - d->regex = strdup(desc->regex); - d->preferred = strdup(desc->preferred); + if (spec->name) + d->spec.name = strdup(spec->name); + if (spec->key) /* This is inappropriately subtle, but when key is NULL, the value will be the key, and there will be no value side at all. */ + d->spec.key = strdup(spec->key); + if (spec->regex) + d->spec.regex = strdup(spec->regex); + + if (spec->preferred) + d->spec.preferred = strdup(spec->preferred); - if (desc->values) { + if (spec->values) { unsigned i; - for (i = 0; desc->values[i]; i++); + for (i = 0; spec->values[i]; i++); - d->values = calloc(i + 1, sizeof(*desc->values)); + d->spec.values = calloc(i + 1, sizeof(*spec->values)); - if (desc->annotations) - d->annotations = calloc(i + 1, sizeof(*desc->annotations)); + if (spec->annotations) + d->spec.annotations = calloc(i + 1, sizeof(*spec->annotations)); - for (i = 0; desc->values[i]; i++) { - d->values[i] = strdup(desc->values[i]); + for (i = 0; spec->values[i]; i++) { + d->spec.values[i] = strdup(spec->values[i]); - if (desc->annotations) { - assert(desc->annotations[i]); - d->annotations[i] = strdup(desc->annotations[i]); + if (spec->annotations) { + assert(spec->annotations[i]); + d->spec.annotations[i] = strdup(spec->annotations[i]); } } } - d->random = desc->random; + d->spec.random = spec->random; + d->spec.as_nested_settings = spec->as_nested_settings; /* TODO: handle allocation errors above... */ *res_desc = d; @@ -392,21 +399,21 @@ int til_setting_desc_clone(const til_setting_desc_t *desc, const til_setting_des til_setting_desc_t * til_setting_desc_free(const til_setting_desc_t *desc) { if (desc) { - free((void *)desc->name); - free((void *)desc->key); - free((void *)desc->regex); - free((void *)desc->preferred); + free((void *)desc->spec.name); + free((void *)desc->spec.key); + free((void *)desc->spec.regex); + free((void *)desc->spec.preferred); - if (desc->values) { - for (unsigned i = 0; desc->values[i]; i++) { - free((void *)desc->values[i]); + if (desc->spec.values) { + for (unsigned i = 0; desc->spec.values[i]; i++) { + free((void *)desc->spec.values[i]); - if (desc->annotations) - free((void *)desc->annotations[i]); + if (desc->spec.annotations) + free((void *)desc->spec.annotations[i]); } - free((void *)desc->values); - free((void *)desc->annotations); + free((void *)desc->spec.values); + free((void *)desc->spec.annotations); } free((void *)desc); @@ -416,15 +423,15 @@ til_setting_desc_t * til_setting_desc_free(const til_setting_desc_t *desc) } -int til_setting_desc_check(const til_setting_desc_t *desc, const char *value) +int til_setting_spec_check(const til_setting_spec_t *spec, const char *value) { - assert(desc); + assert(spec); assert(value); - if (desc->values) { + if (spec->values) { - for (int i = 0; desc->values[i]; i++) { - if (!strcasecmp(desc->values[i], value)) + for (int i = 0; spec->values[i]; i++) { + if (!strcasecmp(spec->values[i], value)) return 0; } diff --git a/src/til_settings.h b/src/til_settings.h index c9da235..4cfddf3 100644 --- a/src/til_settings.h +++ b/src/til_settings.h @@ -7,8 +7,8 @@ typedef struct til_setting_t til_setting_t; typedef struct til_settings_t til_settings_t; typedef struct til_setup_t til_setup_t; -/* Individual setting description */ -typedef struct til_setting_desc_t { +/* Individual setting specification */ +typedef struct til_setting_spec_t { const char *name; /* long-form/human name for setting */ const char *key; /* short-form/key for setting, used as left side of =value in settings string */ const char *regex; /* value must conform to this regex */ @@ -16,14 +16,20 @@ typedef struct til_setting_desc_t { const char **values; /* if a set of values is provided, listed here */ const char **annotations; /* if a set of values is provided, annotations for those values may be listed here */ char * (*random)(unsigned seed);/* if set, returns a valid random value for this setting */ - unsigned as_nested_settings:1; /* if set, this setting expects a settings string for its value and wants a nested til_setting_t.settings instance created for it */ + unsigned as_nested_settings:1; /* if set, this setting expects a settings string for its value and wants a til_setting_t.value_as_nested_settings instance created for it */ +} til_setting_spec_t; + +/* a setting_desc is a setting_spec that's been described to a specific containing settings instance via desc_new(), though desc_new() takes a const settings it's cast away when placed into the allocated desc. */ +typedef struct til_setting_desc_t { + til_settings_t *container; + til_setting_spec_t spec; } til_setting_desc_t; /* For conveniently representing setting description generators */ typedef struct til_setting_desc_generator_t { const char *key; /* key this generator applies to */ const char **value_ptr; /* where to put the value */ - int (*func)(til_setup_t *setup_context, const til_setting_desc_t **res_desc); + int (*func)(const til_settings_t *settings, til_setup_t *setup_context, const til_setting_desc_t **res_desc); } til_setting_desc_generator_t; /* Encapsulates a single til_settings_t.settings[] entry */ @@ -41,13 +47,13 @@ const char * til_settings_get_value_by_key(const til_settings_t *settings, const const char * til_settings_get_value_by_idx(const til_settings_t *settings, unsigned idx, til_setting_t **res_setting); til_setting_t * til_settings_add_value(til_settings_t *settings, const char *key, const char *value, const til_setting_desc_t *desc); void til_settings_reset_descs(til_settings_t *settings); -int til_settings_get_and_describe_value(const til_settings_t *settings, const til_setting_desc_t *desc, const char **res_value, til_setting_t **res_setting, const til_setting_desc_t **res_desc); +int til_settings_get_and_describe_value(const til_settings_t *settings, const til_setting_spec_t *spec, const char **res_value, til_setting_t **res_setting, const til_setting_desc_t **res_desc); char * til_settings_as_arg(const til_settings_t *settings); int til_settings_apply_desc_generators(const til_settings_t *settings, const til_setting_desc_generator_t generators[], unsigned n_generators, til_setup_t *setup, til_setting_t **res_setting, const til_setting_desc_t **res_desc, til_setup_t **res_setup); -int til_setting_desc_clone(const til_setting_desc_t *desc, const til_setting_desc_t **res_desc); +int til_setting_desc_new(const til_settings_t *settings, const til_setting_spec_t *spec, const til_setting_desc_t **res_desc); til_setting_desc_t * til_setting_desc_free(const til_setting_desc_t *desc); -int til_setting_desc_check(const til_setting_desc_t *desc, const char *value); +int til_setting_spec_check(const til_setting_spec_t *spec, const char *value); #ifndef TIL_SETTINGS_STR #define _TIL_SETTINGS_STR(s) #s -- cgit v1.2.3