Compare commits

...

3 Commits

Author SHA1 Message Date
63aed8f0fd Fix up the PEG change from the last commit
This is not a regular expression.
2022-08-14 19:09:52 +02:00
f545be725d Extend string syntax in config
And actually test the results of string parsing.
2022-08-14 18:14:21 +02:00
7e8e085c97 Remove pointless, wrong constant
C99 allows trailing commas.
2021-12-18 00:25:13 +01:00
4 changed files with 52 additions and 10 deletions

View File

@@ -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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted. purpose with or without fee is hereby granted.

View File

@@ -1321,7 +1321,6 @@ enum mpd_subsystem
#define XX(a, b, c) MPD_SUBSYSTEM_ ## a = (1 << b), #define XX(a, b, c) MPD_SUBSYSTEM_ ## a = (1 << b),
MPD_SUBSYSTEM_TABLE (XX) MPD_SUBSYSTEM_TABLE (XX)
#undef XX #undef XX
MPD_SUBSYSTEM_MAX
}; };
static const char *mpd_subsystem_names[] = static const char *mpd_subsystem_names[] =

View File

@@ -1,7 +1,7 @@
/* /*
* liberty.c: the ultimate C unlibrary * 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 * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted. * 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 // object = lws '{' entries endobj
// endobj = lws '}' // endobj = lws '}'
// //
// string = lws '"' ('\\' escape / ![\\"] char)* '"' // quoted = lws '"' (!["\\] char / '\\' escape)* '"'
// / lws '`' (![`] char)* '`'
// string = (quoted)+
// char = [\0-\177] # or any Unicode codepoint in the UTF-8 encoding // 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]? // 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 static bool
config_tokenizer_string config_tokenizer_dq_string (struct config_tokenizer *self, struct str *output,
(struct config_tokenizer *self, struct str *output, struct error **e) struct error **e)
{ {
unsigned char c; unsigned char c = config_tokenizer_advance (self);
while (self->len) while (self->len)
{ {
if ((c = config_tokenizer_advance (self)) == '"') if ((c = config_tokenizer_advance (self)) == '"')
@@ -5056,6 +5058,44 @@ config_tokenizer_string
return false; 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 static enum config_token
config_tokenizer_next (struct config_tokenizer *self, struct error **e) 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; return CONFIG_T_ABORT;
case '"': case '"':
config_tokenizer_advance (self); case '`':
str_reset (&self->string); str_reset (&self->string);
if (!config_tokenizer_string (self, &self->string, e)) if (!config_tokenizer_string (self, &self->string, e))
return CONFIG_T_ABORT; return CONFIG_T_ABORT;

View File

@@ -1,7 +1,7 @@
/* /*
* tests/liberty.c * 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 * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted. * purpose with or without fee is hereby granted.
@@ -649,7 +649,7 @@ static struct config_schema g_config_test[] =
.default_ = "1" }, .default_ = "1" },
{ .name = "foobar", { .name = "foobar",
.type = CONFIG_ITEM_STRING, .type = CONFIG_ITEM_STRING,
.default_ = "\"qux\\x01\"" }, .default_ = "\"qux\\x01`\" \"\"`a`" },
{} {}
}; };
@@ -675,6 +675,9 @@ test_config (void)
"top.bar", NULL), invalid, NULL)); "top.bar", NULL), invalid, NULL));
config_item_destroy (invalid); 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 (); struct str s = str_make ();
config_item_write (config.root, true, &s); config_item_write (config.root, true, &s);
struct config_item *parsed = config_item_parse (s.str, s.len, false, NULL); struct config_item *parsed = config_item_parse (s.str, s.len, false, NULL);