From 7b26b18e69e7e1af3eeb5176e3575eb049451f44 Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Fri, 26 May 2023 18:31:42 -0700 Subject: til_settings: add some settings and desc path printers These print to a stdio FILE*, which for now is harmless since setup_interactively() will be the only consumer (... for now). If one needed the path in a buffer, they could use open_memstream() and pass that FILE* to the printers. And since commit 40feb61 there's already a dependency on the function, but it's icky to dig deeper into that portability trap. Although it seemed like rototiller actually compiled on MacOS at Gene's house, so maybe open_memstream() isn't as problematic as it once was. Anywhow, this commit only adds the path printing helpers, nothing is using them yet. --- src/til_settings.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/til_settings.h | 2 ++ 2 files changed, 72 insertions(+) (limited to 'src') diff --git a/src/til_settings.c b/src/til_settings.c index e42aae8..510dbaf 100644 --- a/src/til_settings.c +++ b/src/til_settings.c @@ -441,6 +441,36 @@ til_setting_desc_t * til_setting_desc_free(const til_setting_desc_t *desc) } +int til_setting_desc_print_path(const til_setting_desc_t *desc, FILE *out) +{ + int r; + + assert(desc); + assert(out); + + r = til_settings_print_path(desc->container, out); + if (r < 0) + return r; + + /* XXX: spec.as_label handling is done in til_settings_print_path() since it + * must apply anywhere within a path, potentially in a recurring fashion. + * So all we're dealing with here is tacking a potentially named desc onto the end, + * treating named descs as a sort of leaf of the path. Though the desc may actually + * describe a setting w/nested settings, i.e. it doesn't actually have to be a leaf + * for this to be correct. When its a parent of nested settings scenario, its key + * would have been used to label the nested settings, but this print won't traverse + * down from desc->container, only up the parents. + */ + if (desc->spec.key) { + r = fprintf(out, "/%s", desc->spec.key); + if (r < 0) + return r; + } + + return 0; +} + + /* TODO: spec checking in general needs refinement and to be less intolerant of * creative experimentation. */ @@ -579,3 +609,43 @@ int til_settings_label_setting(const til_settings_t *settings, const til_setting return -ENOENT; } + + +int til_settings_print_path(const til_settings_t *settings, FILE *out) +{ + const til_settings_t *p, *parents[64]; + size_t i, n_parents; + + assert(settings); + assert(out); + + for (p = settings, n_parents = 0; p != NULL; p = p->parent) + n_parents++; + + /* XXX: if this limitation becomes a problem we can always malloc() + * space, but I can't imagine such deep settings heirarchies being real. + */ + assert(n_parents <= nelems(parents)); + + for (i = 0, p = settings; i < n_parents; p = p->parent, i++) + parents[n_parents - i - 1] = p; + + for (i = 0; i < n_parents; i++) { + int r; + + r = fprintf(out, "/%s", parents[i]->label); + if (r < 0) + return r; + + if (parents[i]->num > 0 && + parents[i]->entries[0]->desc && + parents[i]->entries[0]->desc->spec.as_label) { + + r = fprintf(out, "/%s", parents[i]->entries[0]->value); + if (r < 0) + return r; + } + } + + return 0; +} diff --git a/src/til_settings.h b/src/til_settings.h index 2e2afe9..858ff66 100644 --- a/src/til_settings.h +++ b/src/til_settings.h @@ -56,8 +56,10 @@ int til_settings_apply_desc_generators(const til_settings_t *settings, const til 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_print_path(const til_setting_desc_t *desc, FILE *out); int til_setting_spec_check(const til_setting_spec_t *spec, const char *value); int til_settings_label_setting(const til_settings_t *settings, const til_setting_t *setting, char **res_label); +int til_settings_print_path(const til_settings_t *settings, FILE *out); #ifndef TIL_SETTINGS_STR #define _TIL_SETTINGS_STR(s) #s -- cgit v1.2.1