aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2022-08-14 18:03:18 +0200
committerPřemysl Eric Janouch <p@janouch.name>2022-08-14 18:14:21 +0200
commitf545be725df9195a5b5897ad95a0220acf10f148 (patch)
treeb30aab92bcf23e94ca2c74fca0c6f5573d5745c2
parent7e8e085c97311b52db4d6739b6ef2a1b26a2319f (diff)
downloadliberty-f545be725df9195a5b5897ad95a0220acf10f148.tar.gz
liberty-f545be725df9195a5b5897ad95a0220acf10f148.tar.xz
liberty-f545be725df9195a5b5897ad95a0220acf10f148.zip
Extend string syntax in config
And actually test the results of string parsing.
-rw-r--r--LICENSE2
-rw-r--r--liberty.c52
-rw-r--r--tests/liberty.c7
3 files changed, 52 insertions, 9 deletions
diff --git a/LICENSE b/LICENSE
index b60d4d9..4b31682 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2014 - 2020, Přemysl Eric Janouch <p@janouch.name>
+Copyright (c) 2014 - 2022, Přemysl Eric Janouch <p@janouch.name>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
diff --git a/liberty.c b/liberty.c
index 1655bfa..df7b744 100644
--- a/liberty.c
+++ b/liberty.c
@@ -1,7 +1,7 @@
/*
* liberty.c: the ultimate C unlibrary
*
- * Copyright (c) 2014 - 2020, Přemysl Eric Janouch <p@janouch.name>
+ * Copyright (c) 2014 - 2022, Přemysl Eric Janouch <p@janouch.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
@@ -4412,7 +4412,9 @@ socket_io_try_write (int socket_fd, struct str *wb)
// object = lws '{' entries endobj
// endobj = lws '}'
//
-// string = lws '"' ('\\' escape / ![\\"] char)* '"'
+// quoted = lws '"' ('\\' escape / ![\\"] char)* '"'
+// / lws '`' ![`]* '`'
+// string = (quoted)+
// char = [\0-\177] # or any Unicode codepoint in the UTF-8 encoding
// escape = [\\"abfnrtv] / [xX][0-9A-Fa-f][0-9A-Fa-f]? / [0-7][0-7]?[0-7]?
//
@@ -5039,10 +5041,10 @@ config_tokenizer_escape_sequence
}
static bool
-config_tokenizer_string
- (struct config_tokenizer *self, struct str *output, struct error **e)
+config_tokenizer_dq_string (struct config_tokenizer *self, struct str *output,
+ struct error **e)
{
- unsigned char c;
+ unsigned char c = config_tokenizer_advance (self);
while (self->len)
{
if ((c = config_tokenizer_advance (self)) == '"')
@@ -5056,6 +5058,44 @@ config_tokenizer_string
return false;
}
+static bool
+config_tokenizer_bt_string (struct config_tokenizer *self, struct str *output,
+ struct error **e)
+{
+ unsigned char c = config_tokenizer_advance (self);
+ while (self->len)
+ {
+ if ((c = config_tokenizer_advance (self)) == '`')
+ return true;
+ str_append_c (output, c);
+ }
+ config_tokenizer_error (self, e, "premature end of string");
+ return false;
+}
+
+static bool
+config_tokenizer_string (struct config_tokenizer *self, struct str *output,
+ struct error **e)
+{
+ // Go-like strings, with C/AWK-like automatic concatenation
+ while (self->len)
+ {
+ bool ok = true;
+ if (isspace_ascii (*self->p) && *self->p != '\n')
+ config_tokenizer_advance (self);
+ else if (*self->p == '"')
+ ok = config_tokenizer_dq_string (self, output, e);
+ else if (*self->p == '`')
+ ok = config_tokenizer_bt_string (self, output, e);
+ else
+ break;
+
+ if (!ok)
+ return false;
+ }
+ return true;
+}
+
static enum config_token
config_tokenizer_next (struct config_tokenizer *self, struct error **e)
{
@@ -5080,7 +5120,7 @@ config_tokenizer_next (struct config_tokenizer *self, struct error **e)
return CONFIG_T_ABORT;
case '"':
- config_tokenizer_advance (self);
+ case '`':
str_reset (&self->string);
if (!config_tokenizer_string (self, &self->string, e))
return CONFIG_T_ABORT;
diff --git a/tests/liberty.c b/tests/liberty.c
index dc445d8..3d932d5 100644
--- a/tests/liberty.c
+++ b/tests/liberty.c
@@ -1,7 +1,7 @@
/*
* tests/liberty.c
*
- * Copyright (c) 2015 - 2016, Přemysl Eric Janouch <p@janouch.name>
+ * Copyright (c) 2015 - 2022, Přemysl Eric Janouch <p@janouch.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
@@ -649,7 +649,7 @@ static struct config_schema g_config_test[] =
.default_ = "1" },
{ .name = "foobar",
.type = CONFIG_ITEM_STRING,
- .default_ = "\"qux\\x01\"" },
+ .default_ = "\"qux\\x01`\" \"\"`a`" },
{}
};
@@ -675,6 +675,9 @@ test_config (void)
"top.bar", NULL), invalid, NULL));
config_item_destroy (invalid);
+ hard_assert (!strcmp ("qux\001`a",
+ config_item_get (config.root, "top.foobar", NULL)->value.string.str));
+
struct str s = str_make ();
config_item_write (config.root, true, &s);
struct config_item *parsed = config_item_parse (s.str, s.len, false, NULL);