summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2023-05-09 11:43:22 -0700
committerVito Caputo <vcaputo@pengaru.com>2023-05-11 15:18:34 -0700
commit31a0147a720f2f0ef30df41512f41f43734662dd (patch)
treec381b2905eaf5cde93b83b2ee93adc148400b488 /src
parent1a8abe80dabd6b723897fc507808db30b126b3a4 (diff)
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.
Diffstat (limited to 'src')
-rw-r--r--src/drm_fb.c57
-rw-r--r--src/main.c19
-rw-r--r--src/mem_fb.c2
-rw-r--r--src/modules/blinds/blinds.c4
-rw-r--r--src/modules/checkers/checkers.c14
-rw-r--r--src/modules/compose/compose.c4
-rw-r--r--src/modules/drizzle/drizzle.c4
-rw-r--r--src/modules/flui2d/flui2d.c10
-rw-r--r--src/modules/moire/moire.c2
-rw-r--r--src/modules/pixbounce/pixbounce.c4
-rw-r--r--src/modules/plato/plato.c4
-rw-r--r--src/modules/rkt/rkt.c14
-rw-r--r--src/modules/rtv/rtv.c12
-rw-r--r--src/modules/shapes/shapes.c14
-rw-r--r--src/modules/sparkler/sparkler.c8
-rw-r--r--src/modules/stars/stars.c2
-rw-r--r--src/modules/strobe/strobe.c2
-rw-r--r--src/modules/submit/submit.c2
-rw-r--r--src/modules/swarm/swarm.c2
-rw-r--r--src/modules/voronoi/voronoi.c6
-rw-r--r--src/sdl_fb.c7
-rw-r--r--src/setup.c40
-rw-r--r--src/til.c31
-rw-r--r--src/til_settings.c95
-rw-r--r--src/til_settings.h20
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
© All Rights Reserved