diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2022-07-20 23:33:55 -0700 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2022-07-20 23:33:55 -0700 |
commit | cbfe780b20ced576c2e3d41361a9036210ab5c9b (patch) | |
tree | 1f742aad1d71b39de9d1c87b500953fc6f28c3a1 /src | |
parent | c69917862a58cac01d9deca2b91255f0510b243c (diff) |
til_settings: support rudimentary =value escaping
This is a step towards properly handling nested settings, so we
can do stuff like:
--module=rtv,channels=compose\,layers=checkers\\\,fill_module=shapes\\\,size=64\,texture=plasma
and have rtv actually cycle through just compose with
checkers+plasma layers but holding the specified checkers
settings to shapes filler with a size of 64, randomizing the
rest.
There's more work to do before that can actually happen, but
first thing is to just support escaping the settings values.
Diffstat (limited to 'src')
-rw-r--r-- | src/til_settings.c | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/src/til_settings.c b/src/til_settings.c index 01b27b7..3e26686 100644 --- a/src/til_settings.c +++ b/src/til_settings.c @@ -1,6 +1,7 @@ #include <assert.h> #include <errno.h> #include <stdarg.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> @@ -38,6 +39,7 @@ typedef enum til_settings_fsm_state_t { TIL_SETTINGS_FSM_STATE_KEY, TIL_SETTINGS_FSM_STATE_EQUAL, TIL_SETTINGS_FSM_STATE_VALUE, + TIL_SETTINGS_FSM_STATE_VALUE_ESCAPED, TIL_SETTINGS_FSM_STATE_COMMA, } til_settings_fsm_state_t; @@ -65,6 +67,9 @@ til_settings_t * til_settings_new(const char *settings_string) til_settings_fsm_state_t state = TIL_SETTINGS_FSM_STATE_KEY; const char *p, *token; til_settings_t *settings; + FILE *value_fp; + char *value_buf; + size_t value_sz; settings = calloc(1, sizeof(til_settings_t)); if (!settings) @@ -73,7 +78,6 @@ til_settings_t * til_settings_new(const char *settings_string) if (!settings_string) return settings; - /* TODO: unescaping? */ for (token = p = settings_string; ;p++) { switch (state) { @@ -94,15 +98,29 @@ til_settings_t * til_settings_new(const char *settings_string) break; case TIL_SETTINGS_FSM_STATE_EQUAL: + value_fp = open_memstream(&value_buf, &value_sz); + if (!value_fp) + goto _err; + token = p; state = TIL_SETTINGS_FSM_STATE_VALUE; /* fallthrough, necessary to not leave NULL values for empty "key=\0" settings */ case TIL_SETTINGS_FSM_STATE_VALUE: - if (*p == ',' || *p == '\0') { - settings->settings[settings->num - 1]->value = strndup(token, p - token); + if (*p == '\\') + state = TIL_SETTINGS_FSM_STATE_VALUE_ESCAPED; + else if (*p == ',' || *p == '\0') { + fclose(value_fp); + settings->settings[settings->num - 1]->value = value_buf; state = TIL_SETTINGS_FSM_STATE_COMMA; - } + } else + fputc(*p, value_fp); + + break; + + case TIL_SETTINGS_FSM_STATE_VALUE_ESCAPED: + fputc(*p, value_fp); + state = TIL_SETTINGS_FSM_STATE_VALUE; break; default: @@ -116,6 +134,9 @@ til_settings_t * til_settings_new(const char *settings_string) /* FIXME: this should probably never leave a value or key entry NULL */ return settings; + +_err: + return til_settings_free(settings); } |