summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/til_settings.c93
-rw-r--r--src/til_settings.h3
2 files changed, 89 insertions, 7 deletions
diff --git a/src/til_settings.c b/src/til_settings.c
index 907e114..eca937b 100644
--- a/src/til_settings.c
+++ b/src/til_settings.c
@@ -49,7 +49,7 @@ typedef enum til_settings_fsm_state_t {
} til_settings_fsm_state_t;
-static til_setting_t * add_setting(til_settings_t *settings, const char *key, const char *value)
+static til_setting_t * add_setting(til_settings_t *settings, const char *key, const char *value, int nocheck)
{
til_setting_t **new_entries;
til_setting_t *s;
@@ -63,6 +63,7 @@ static til_setting_t * add_setting(til_settings_t *settings, const char *key, co
s->parent = settings;
s->key = key;
s->value = value;
+ s->nocheck = nocheck;
new_entries = realloc(settings->entries, (settings->num + 1) * sizeof(til_setting_t *));
if (!new_entries) {
@@ -123,10 +124,16 @@ til_settings_t * til_settings_new(const char *prefix, const til_settings_t *pare
else if (*p == '=' || *p == ',' || *p == '\0') {
if (*p == '=') { /* key= */
- (void) add_setting(settings, til_str_to_buf(value_str, NULL), NULL);
+ (void) add_setting(settings, til_str_to_buf(value_str, NULL), NULL, 0);
state = TIL_SETTINGS_FSM_STATE_EQUAL;
} else { /* bare value */
- (void) add_setting(settings, NULL, til_str_to_buf(value_str, NULL));
+ char *v = til_str_to_buf(value_str, NULL);
+ int nocheck = v[0] == ':' ? 1 : 0;
+
+ if (nocheck)
+ v++;
+
+ (void) add_setting(settings, NULL, v, nocheck);
state = TIL_SETTINGS_FSM_STATE_COMMA;
}
} else
@@ -150,7 +157,14 @@ til_settings_t * til_settings_new(const char *prefix, const til_settings_t *pare
if (*p == '\\')
state = TIL_SETTINGS_FSM_STATE_VALUE_ESCAPED;
else if (*p == ',' || *p == '\0') {
- settings->entries[settings->num - 1]->value = til_str_to_buf(value_str, NULL);
+ char *v = til_str_to_buf(value_str, NULL);
+ int r;
+
+ r = til_setting_set_raw_value(settings->entries[settings->num - 1], v);
+ free(v);
+ if (r < 0)
+ goto _err;
+
state = TIL_SETTINGS_FSM_STATE_COMMA;
} else
til_str_appendf(value_str, "%c", *p); /* FIXME: errors */
@@ -196,7 +210,11 @@ til_settings_t * til_settings_free(til_settings_t *settings)
til_settings_free(settings->entries[i]->value_as_nested_settings);
free((void *)settings->entries[i]->key);
- free((void *)settings->entries[i]->value);
+ if (settings->entries[i]->value) {
+ if (settings->entries[i]->nocheck)
+ settings->entries[i]->value--;
+ free((void *)settings->entries[i]->value);
+ }
til_setting_desc_free((void *)settings->entries[i]->desc);
free((void *)settings->entries[i]);
}
@@ -340,11 +358,23 @@ int til_settings_get_and_describe_value(const til_settings_t *settings, const ti
/* returns the added setting, or NULL on error (ENOMEM) */
til_setting_t * til_settings_add_value(til_settings_t *settings, const char *key, const char *value)
{
+ int nocheck = 0;
+ char *v;
+
assert(settings);
assert(value);
/* XXX: ^^ non-NULL values makes til_settings_get_value_by_idx() NULL-return-for-end-of-settings OK */
- return add_setting(settings, key ? strdup(key) : NULL, strdup(value));
+ v = strdup(value);
+ if (!v)
+ return NULL;
+
+ if (v[0] == ':') {
+ nocheck = 1;
+ v++;
+ }
+
+ return add_setting(settings, key ? strdup(key) : NULL, v, nocheck);
}
@@ -572,6 +602,53 @@ int til_setting_spec_check(const til_setting_spec_t *spec, const char *value)
}
+/* helper for changing the "raw" value of a setting, maintains til_setting_t.nocheck */
+int til_setting_set_raw_value(til_setting_t *setting, const char *value)
+{
+ int nocheck = 0;
+ const char *v;
+
+ assert(setting);
+ assert(value);
+
+ v = strdup(value);
+ if (!v)
+ return -ENOMEM;
+
+ if (v[0] == ':') {
+ nocheck = 1;
+ v++;
+ }
+
+ if (setting->value) {
+ if (setting->nocheck)
+ setting->value--;
+ free((void *)setting->value);
+ }
+
+ setting->value = v;
+ setting->nocheck = nocheck;
+
+ return 0;
+}
+
+
+/* helper for accessing the "raw" value for a setting, which presently just means
+ * if a value was added as a "nocheck" value with a ':' prefix, this will return the
+ * prefixed form. Otherwise you just get the same thing as setting->value.
+ */
+const char * til_setting_get_raw_value(til_setting_t *setting)
+{
+ assert(setting);
+
+ if (setting->nocheck)
+ return setting->value - 1;
+
+ return setting->value;
+}
+
+
+
static inline void fputc_escaped(til_str_t *out, int c, unsigned depth)
{
unsigned escapes = 0;
@@ -627,7 +704,9 @@ static int settings_as_arg(const til_settings_t *settings, int unfiltered, unsig
if (settings->entries[i]->value_as_nested_settings) {
settings_as_arg(settings->entries[i]->value_as_nested_settings, unfiltered, depth + 1, out);
} else if (settings->entries[i]->value) {
- fputs_escaped(out, settings->entries[i]->value, depth);
+ const char *v = til_setting_get_raw_value(settings->entries[i]);
+
+ fputs_escaped(out, v, depth);
}
j++;
}
diff --git a/src/til_settings.h b/src/til_settings.h
index 85df105..95b2ac4 100644
--- a/src/til_settings.h
+++ b/src/til_settings.h
@@ -43,6 +43,7 @@ struct til_setting_t {
const char *value;
const til_setting_desc_t *desc;
void *user_data;
+ unsigned nocheck:1; /* set when user explicitly set the value outside the guards */
};
til_settings_t * til_settings_new(const char *prefix, const til_settings_t *parent, const char *label, const char *settings);
@@ -65,6 +66,8 @@ til_setting_desc_t * til_setting_desc_free(const til_setting_desc_t *desc);
int til_setting_desc_strprint_path(const til_setting_desc_t *desc, til_str_t *str);
int til_setting_desc_fprint_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_setting_set_raw_value(til_setting_t *setting, const char *value);
+const char * til_setting_get_raw_value(til_setting_t *setting);
int til_settings_label_setting(const til_settings_t *settings, const til_setting_t *setting, char **res_label);
int til_settings_strprint_path(const til_settings_t *settings, til_str_t *str);
int til_settings_fprint_path(const til_settings_t *settings, FILE *out);
© All Rights Reserved