summaryrefslogtreecommitdiff
path: root/src/libstrongswan/settings
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/settings')
-rw-r--r--src/libstrongswan/settings/settings.c452
-rw-r--r--src/libstrongswan/settings/settings.h26
-rw-r--r--src/libstrongswan/settings/settings_lexer.c466
-rw-r--r--src/libstrongswan/settings/settings_lexer.l46
-rw-r--r--src/libstrongswan/settings/settings_parser.c224
-rw-r--r--src/libstrongswan/settings/settings_parser.h19
-rw-r--r--src/libstrongswan/settings/settings_parser.y47
-rw-r--r--src/libstrongswan/settings/settings_types.c90
-rw-r--r--src/libstrongswan/settings/settings_types.h33
9 files changed, 942 insertions, 461 deletions
diff --git a/src/libstrongswan/settings/settings.c b/src/libstrongswan/settings/settings.c
index a4c5060fa..44d035fac 100644
--- a/src/libstrongswan/settings/settings.c
+++ b/src/libstrongswan/settings/settings.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2014 Tobias Brunner
+ * Copyright (C) 2010-2018 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* HSR Hochschule fuer Technik Rapperswil
*
@@ -73,6 +73,7 @@ struct private_settings_t {
/**
* Print a format key, but consume already processed arguments
+ * Note that key and start point into the same string
*/
static bool print_key(char *buf, int len, char *start, char *key, va_list args)
{
@@ -115,6 +116,25 @@ static bool print_key(char *buf, int len, char *start, char *key, va_list args)
}
/**
+ * Check if the given section is contained in the given array.
+ */
+static bool has_section(array_t *array, section_t *section)
+{
+ section_t *current;
+ int i;
+
+ for (i = 0; i < array_count(array); i++)
+ {
+ array_get(array, i, &current);
+ if (current == section)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
* Find a section by a given key, using buffered key, reusable buffer.
* If "ensure" is TRUE, the sections are created if they don't exist.
*/
@@ -160,15 +180,39 @@ static section_t *find_section_buffered(section_t *section,
}
/**
- * Find all sections via a given key considering fallbacks, using buffered key,
+ * Forward declaration
+ */
+static array_t *find_sections(private_settings_t *this, section_t *section,
+ char *key, va_list args, array_t **sections);
+
+/**
+ * Resolve the given reference. Not thread-safe.
+ * Only a vararg function to get an empty va_list.
+ */
+static void resolve_reference(private_settings_t *this, section_ref_t *ref,
+ array_t **sections, ...)
+{
+ va_list args;
+
+ va_start(args, sections);
+ find_sections(this, this->top, ref->name, args, sections);
+ va_end(args);
+}
+
+/**
+ * Find all sections via a given key considering references, using buffered key,
* reusable buffer.
*/
-static void find_sections_buffered(section_t *section, char *start, char *key,
- va_list args, char *buf, int len, array_t **sections)
+static void find_sections_buffered(private_settings_t *this, section_t *section,
+ char *start, char *key, va_list args,
+ char *buf, int len, bool ignore_refs,
+ array_t **sections)
{
- section_t *found = NULL, *fallback;
+ section_t *found = NULL, *reference;
+ array_t *references;
+ section_ref_t *ref;
char *pos;
- int i;
+ int i, j;
if (!section)
{
@@ -184,7 +228,7 @@ static void find_sections_buffered(section_t *section, char *start, char *key,
return;
}
if (pos)
- { /* restore so we can follow fallbacks */
+ { /* restore so we can follow references */
*pos = '.';
}
if (!strlen(buf))
@@ -199,147 +243,100 @@ static void find_sections_buffered(section_t *section, char *start, char *key,
{
if (pos)
{
- find_sections_buffered(found, start, pos+1, args, buf, len,
- sections);
+ find_sections_buffered(this, found, start, pos+1, args, buf, len,
+ FALSE, sections);
}
- else
+ else if (!has_section(*sections, found))
{
+ /* ignore if already added to avoid loops */
array_insert_create(sections, ARRAY_TAIL, found);
- for (i = 0; i < array_count(found->fallbacks); i++)
+ /* add all sections that are referenced here (also resolves
+ * references in parent sections of the referenced section) */
+ for (i = 0; i < array_count(found->references); i++)
{
- array_get(found->fallbacks, i, &fallback);
- array_insert_create(sections, ARRAY_TAIL, fallback);
+ array_get(found->references, i, &ref);
+ resolve_reference(this, ref, sections);
}
}
}
- if (section->fallbacks)
+ if (!ignore_refs && section != found && section->references)
{
- for (i = 0; i < array_count(section->fallbacks); i++)
+ /* find matching sub-sections relative to the referenced sections */
+ for (i = 0; i < array_count(section->references); i++)
{
- array_get(section->fallbacks, i, &fallback);
- find_sections_buffered(fallback, start, key, args, buf, len,
- sections);
+ array_get(section->references, i, &ref);
+ references = NULL;
+ resolve_reference(this, ref, &references);
+ for (j = 0; j < array_count(references); j++)
+ {
+ array_get(references, j, &reference);
+ /* ignore references in this referenced section, they were
+ * resolved via resolve_reference() */
+ find_sections_buffered(this, reference, start, key, args,
+ buf, len, TRUE, sections);
+ }
+ array_destroy(references);
}
}
}
/**
- * Ensure that the section with the given key exists (thread-safe).
+ * Ensure that the section with the given key exists (not thread-safe).
*/
static section_t *ensure_section(private_settings_t *this, section_t *section,
const char *key, va_list args)
{
char buf[128], keybuf[512];
- section_t *found;
if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
{
return NULL;
}
- /* we might have to change the tree */
- this->lock->write_lock(this->lock);
- found = find_section_buffered(section, keybuf, keybuf, args, buf,
- sizeof(buf), TRUE);
- this->lock->unlock(this->lock);
- return found;
+ return find_section_buffered(section, keybuf, keybuf, args, buf,
+ sizeof(buf), TRUE);
}
/**
- * Find a section by a given key with its fallbacks (not thread-safe!).
- * Sections are returned in depth-first order (array is allocated). NULL is
- * returned if no sections are found.
+ * Find a section by a given key with resolved references (not thread-safe!).
+ * The array is allocated. NULL is returned if no sections are found.
*/
static array_t *find_sections(private_settings_t *this, section_t *section,
- char *key, va_list args)
+ char *key, va_list args, array_t **sections)
{
char buf[128], keybuf[512];
- array_t *sections = NULL;
if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
{
return NULL;
}
- find_sections_buffered(section, keybuf, keybuf, args, buf,
- sizeof(buf), &sections);
- return sections;
-}
-
-/**
- * Check if the given fallback section already exists
- */
-static bool fallback_exists(section_t *section, section_t *fallback)
-{
- if (section == fallback)
- {
- return TRUE;
- }
- else if (section->fallbacks)
- {
- section_t *existing;
- int i;
-
- for (i = 0; i < array_count(section->fallbacks); i++)
- {
- array_get(section->fallbacks, i, &existing);
- if (existing == fallback)
- {
- return TRUE;
- }
- }
- }
- return FALSE;
-}
-
-/**
- * Ensure that the section with the given key exists and add the given fallback
- * section (thread-safe).
- */
-static void add_fallback_to_section(private_settings_t *this,
- section_t *section, const char *key, va_list args,
- section_t *fallback)
-{
- char buf[128], keybuf[512];
- section_t *found;
-
- if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
- {
- return;
- }
- this->lock->write_lock(this->lock);
- found = find_section_buffered(section, keybuf, keybuf, args, buf,
- sizeof(buf), TRUE);
- if (!fallback_exists(found, fallback))
- {
- /* to ensure sections referred to as fallback are not purged, we create
- * the array there too */
- if (!fallback->fallbacks)
- {
- fallback->fallbacks = array_create(0, 0);
- }
- array_insert_create(&found->fallbacks, ARRAY_TAIL, fallback);
- }
- this->lock->unlock(this->lock);
+ find_sections_buffered(this, section, keybuf, keybuf, args, buf,
+ sizeof(buf), FALSE, sections);
+ return *sections;
}
/**
* Find the key/value pair for a key, using buffered key, reusable buffer
- * If "ensure" is TRUE, the sections (and key/value pair) are created if they
- * don't exist.
- * Fallbacks are only considered if "ensure" is FALSE.
+ * There are two modes: 1. To find a key at an exact location and create the
+ * sections (and key/value pair) if necessary, don't pass an array for sections.
+ * 2. To find a key and follow references pass a pointer to an array to store
+ * visited sections. NULL is returned in this case if the key is not found.
*/
-static kv_t *find_value_buffered(section_t *section, char *start, char *key,
- va_list args, char *buf, int len, bool ensure)
+static kv_t *find_value_buffered(private_settings_t *this, section_t *section,
+ char *start, char *key, va_list args,
+ char *buf, int len, bool ignore_refs,
+ array_t **sections)
{
- int i;
- char *pos;
- kv_t *kv = NULL;
section_t *found = NULL;
+ kv_t *kv = NULL;
+ section_ref_t *ref;
+ array_t *references;
+ char *pos;
+ int i, j;
- if (section == NULL)
+ if (!section)
{
return NULL;
}
-
pos = strchr(key, '.');
if (pos)
{
@@ -348,7 +345,7 @@ static kv_t *find_value_buffered(section_t *section, char *start, char *key,
{
return NULL;
}
- /* restore so we can retry for fallbacks */
+ /* restore so we can follow references */
*pos = '.';
if (!strlen(buf))
{
@@ -357,7 +354,7 @@ static kv_t *find_value_buffered(section_t *section, char *start, char *key,
else if (array_bsearch(section->sections, buf, settings_section_find,
&found) == -1)
{
- if (ensure)
+ if (!sections)
{
found = settings_section_create(strdup(buf));
settings_section_add(section, found, NULL);
@@ -365,53 +362,144 @@ static kv_t *find_value_buffered(section_t *section, char *start, char *key,
}
if (found)
{
- kv = find_value_buffered(found, start, pos+1, args, buf, len,
- ensure);
- }
- if (!kv && !ensure && section->fallbacks)
- {
- for (i = 0; !kv && i < array_count(section->fallbacks); i++)
- {
- array_get(section->fallbacks, i, &found);
- kv = find_value_buffered(found, start, key, args, buf, len,
- ensure);
- }
+ kv = find_value_buffered(this, found, start, pos+1, args, buf, len,
+ FALSE, sections);
}
}
else
{
+ if (sections)
+ {
+ array_insert_create(sections, ARRAY_TAIL, section);
+ }
if (!print_key(buf, len, start, key, args))
{
return NULL;
}
if (array_bsearch(section->kv, buf, settings_kv_find, &kv) == -1)
{
- if (ensure)
+ if (!sections)
{
kv = settings_kv_create(strdup(buf), NULL);
settings_kv_add(section, kv, NULL);
}
- else if (section->fallbacks)
+ }
+ }
+ if (!kv && !ignore_refs && sections && section->references)
+ {
+ /* find key relative to the referenced sections */
+ for (i = 0; !kv && i < array_count(section->references); i++)
+ {
+ array_get(section->references, i, &ref);
+ references = NULL;
+ resolve_reference(this, ref, &references);
+ for (j = 0; !kv && j < array_count(references); j++)
{
- for (i = 0; !kv && i < array_count(section->fallbacks); i++)
+ array_get(references, j, &found);
+ /* ignore if already added to avoid loops */
+ if (!has_section(*sections, found))
{
- array_get(section->fallbacks, i, &found);
- kv = find_value_buffered(found, start, key, args, buf, len,
- ensure);
+ /* ignore references in this referenced section, they were
+ * resolved via resolve_reference() */
+ kv = find_value_buffered(this, found, start, key, args,
+ buf, len, TRUE, sections);
}
}
+ array_destroy(references);
}
}
return kv;
}
/**
+ * Remove the key/value pair for a key, using buffered key, reusable buffer
+ */
+static void remove_value_buffered(private_settings_t *this, section_t *section,
+ char *start, char *key, va_list args,
+ char *buf, int len)
+{
+ section_t *found = NULL;
+ kv_t *kv = NULL, *ordered = NULL;
+ char *pos;
+ int idx, i;
+
+ if (!section)
+ {
+ return;
+ }
+ pos = strchr(key, '.');
+ if (pos)
+ {
+ *pos = '\0';
+ pos++;
+ }
+ if (!print_key(buf, len, start, key, args))
+ {
+ return;
+ }
+ if (!strlen(buf))
+ {
+ found = section;
+ }
+ if (pos)
+ {
+ if (array_bsearch(section->sections, buf, settings_section_find,
+ &found) != -1)
+ {
+ remove_value_buffered(this, found, start, pos, args, buf, len);
+ }
+ }
+ else
+ {
+ idx = array_bsearch(section->kv, buf, settings_kv_find, &kv);
+ if (idx != -1)
+ {
+ array_remove(section->kv, idx, NULL);
+ for (i = 0; i < array_count(section->kv_order); i++)
+ {
+ array_get(section->kv_order, i, &ordered);
+ if (kv == ordered)
+ {
+ array_remove(section->kv_order, i, NULL);
+ settings_kv_destroy(kv, this->contents);
+ break;
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Described in header
+ */
+void settings_remove_value(settings_t *settings, char *key, ...)
+{
+ private_settings_t *this = (private_settings_t*)settings;
+ char buf[128], keybuf[512];
+ va_list args;
+
+ if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
+ {
+ return;
+ }
+ va_start(args, key);
+
+ this->lock->read_lock(this->lock);
+ remove_value_buffered(this, this->top, keybuf, keybuf, args, buf,
+ sizeof(buf));
+ this->lock->unlock(this->lock);
+
+ va_end(args);
+}
+
+/**
* Find the string value for a key (thread-safe).
*/
static char *find_value(private_settings_t *this, section_t *section,
char *key, va_list args)
{
char buf[128], keybuf[512], *value = NULL;
+ array_t *sections = NULL;
kv_t *kv;
if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
@@ -419,13 +507,14 @@ static char *find_value(private_settings_t *this, section_t *section,
return NULL;
}
this->lock->read_lock(this->lock);
- kv = find_value_buffered(section, keybuf, keybuf, args, buf, sizeof(buf),
- FALSE);
+ kv = find_value_buffered(this, section, keybuf, keybuf, args,
+ buf, sizeof(buf), FALSE, &sections);
if (kv)
{
value = kv->value;
}
this->lock->unlock(this->lock);
+ array_destroy(sections);
return value;
}
@@ -443,8 +532,8 @@ static void set_value(private_settings_t *this, section_t *section,
return;
}
this->lock->write_lock(this->lock);
- kv = find_value_buffered(section, keybuf, keybuf, args, buf, sizeof(buf),
- TRUE);
+ kv = find_value_buffered(this, section, keybuf, keybuf, args,
+ buf, sizeof(buf), FALSE, NULL);
if (kv)
{
settings_kv_set(kv, strdupnull(value), this->contents);
@@ -761,12 +850,12 @@ METHOD(settings_t, create_section_enumerator, enumerator_t*,
private_settings_t *this, char *key, ...)
{
enumerator_data_t *data;
- array_t *sections;
+ array_t *sections = NULL;
va_list args;
this->lock->read_lock(this->lock);
va_start(args, key);
- sections = find_sections(this, this->top, key, args);
+ sections = find_sections(this, this->top, key, args, &sections);
va_end(args);
if (!sections)
@@ -793,13 +882,17 @@ CALLBACK(kv_filter, bool,
while (orig->enumerate(orig, &kv))
{
- if (seen->get(seen, kv->key) || !kv->value)
+ if (seen->get(seen, kv->key))
+ {
+ continue;
+ }
+ seen->put(seen, kv->key, kv->key);
+ if (!kv->value)
{
continue;
}
*key = kv->key;
*value = kv->value;
- seen->put(seen, kv->key, kv->key);
return TRUE;
}
return FALSE;
@@ -818,12 +911,12 @@ METHOD(settings_t, create_key_value_enumerator, enumerator_t*,
private_settings_t *this, char *key, ...)
{
enumerator_data_t *data;
- array_t *sections;
+ array_t *sections = NULL;
va_list args;
this->lock->read_lock(this->lock);
va_start(args, key);
- sections = find_sections(this, this->top, key, args);
+ sections = find_sections(this, this->top, key, args, &sections);
va_end(args);
if (!sections)
@@ -845,33 +938,34 @@ METHOD(settings_t, add_fallback, void,
{
section_t *section;
va_list args;
+ char buf[512];
- /* find/create the fallback */
+ this->lock->write_lock(this->lock);
va_start(args, fallback);
- section = ensure_section(this, this->top, fallback, args);
+ section = ensure_section(this, this->top, key, args);
va_end(args);
va_start(args, fallback);
- add_fallback_to_section(this, this->top, key, args, section);
+ if (section && vsnprintf(buf, sizeof(buf), fallback, args) < sizeof(buf))
+ {
+ settings_reference_add(section, strdup(buf), TRUE);
+ }
va_end(args);
+ this->lock->unlock(this->lock);
}
/**
* Load settings from files matching the given file pattern or from a string.
- * All sections and values are added relative to "parent".
* All files (even included ones) have to be loaded successfully.
- * If merge is FALSE the contents of parent are replaced with the parsed
- * contents, otherwise they are merged together.
*/
-static bool load_internal(private_settings_t *this, section_t *parent,
- char *pattern, bool merge, bool string)
+static section_t *load_internal(char *pattern, bool string)
{
section_t *section;
bool loaded;
if (pattern == NULL || !pattern[0])
- { /* TODO: Clear parent if merge is FALSE? */
- return TRUE;
+ {
+ return settings_section_create(NULL);
}
section = settings_section_create(NULL);
@@ -880,61 +974,101 @@ static bool load_internal(private_settings_t *this, section_t *parent,
if (!loaded)
{
settings_section_destroy(section, NULL);
- return FALSE;
+ section = NULL;
}
+ return section;
+}
- this->lock->write_lock(this->lock);
- settings_section_extend(parent, section, this->contents, !merge);
+/**
+ * Add sections and values in "section" relative to "parent".
+ * If merge is FALSE the contents of parent are replaced with the parsed
+ * contents, otherwise they are merged together.
+ *
+ * Releases the write lock and destroys the given section.
+ * If parent is NULL this is all that happens.
+ */
+static bool extend_section(private_settings_t *this, section_t *parent,
+ section_t *section, bool merge)
+{
+ if (parent)
+ {
+ settings_section_extend(parent, section, this->contents, !merge);
+ }
this->lock->unlock(this->lock);
-
settings_section_destroy(section, NULL);
- return TRUE;
+ return parent != NULL;
}
METHOD(settings_t, load_files, bool,
private_settings_t *this, char *pattern, bool merge)
{
- return load_internal(this, this->top, pattern, merge, FALSE);
+ section_t *section;
+
+ section = load_internal(pattern, FALSE);
+ if (!section)
+ {
+ return FALSE;
+ }
+
+ this->lock->write_lock(this->lock);
+ return extend_section(this, this->top, section, merge);
}
METHOD(settings_t, load_files_section, bool,
private_settings_t *this, char *pattern, bool merge, char *key, ...)
{
- section_t *section;
+ section_t *section, *parent;
va_list args;
- va_start(args, key);
- section = ensure_section(this, this->top, key, args);
- va_end(args);
-
+ section = load_internal(pattern, FALSE);
if (!section)
{
return FALSE;
}
- return load_internal(this, section, pattern, merge, FALSE);
+
+ this->lock->write_lock(this->lock);
+
+ va_start(args, key);
+ parent = ensure_section(this, this->top, key, args);
+ va_end(args);
+
+ return extend_section(this, parent, section, merge);
}
METHOD(settings_t, load_string, bool,
private_settings_t *this, char *settings, bool merge)
{
- return load_internal(this, this->top, settings, merge, TRUE);
+ section_t *section;
+
+ section = load_internal(settings, TRUE);
+ if (!section)
+ {
+ return FALSE;
+ }
+
+ this->lock->write_lock(this->lock);
+ return extend_section(this, this->top, section, merge);
}
METHOD(settings_t, load_string_section, bool,
private_settings_t *this, char *settings, bool merge, char *key, ...)
{
- section_t *section;
+ section_t *section, *parent;
va_list args;
- va_start(args, key);
- section = ensure_section(this, this->top, key, args);
- va_end(args);
-
+ section = load_internal(settings, TRUE);
if (!section)
{
return FALSE;
}
- return load_internal(this, section, settings, merge, TRUE);
+
+ this->lock->write_lock(this->lock);
+
+ va_start(args, key);
+ parent = ensure_section(this, this->top, key, args);
+ va_end(args);
+
+ return extend_section(this, parent, section, merge);
}
METHOD(settings_t, destroy, void,
diff --git a/src/libstrongswan/settings/settings.h b/src/libstrongswan/settings/settings.h
index e25c9da38..814cf32e5 100644
--- a/src/libstrongswan/settings/settings.h
+++ b/src/libstrongswan/settings/settings.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Tobias Brunner
+ * Copyright (C) 2010-2018 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* HSR Hochschule fuer Technik Rapperswil
*
@@ -288,15 +288,9 @@ struct settings_t {
* 'section-one.two' will result in a lookup for the same section/key
* in 'section-two'.
*
- * @note Lookups are depth-first and currently strictly top-down.
- * For instance, if app.sec had lib1.sec as fallback and lib1 had lib2 as
- * fallback the keys/sections in lib2.sec would not be considered. But if
- * app had lib3 as fallback the contents of lib3.sec would (as app is passed
- * during the initial lookup). In the last example the order during
- * enumerations would be app.sec, lib1.sec, lib3.sec.
- *
* @note Additional arguments will be applied to both section format
- * strings so they must be compatible.
+ * strings so they must be compatible. And they are evaluated immediately,
+ * so arguments can't contain dots.
*
* @param section section for which a fallback is configured, printf style
* @param fallback fallback section, printf style
@@ -413,4 +407,18 @@ settings_t *settings_create(char *file);
*/
settings_t *settings_create_string(char *settings);
+/**
+ * Remove the given key/value.
+ *
+ * Compared to setting a key to NULL, which makes it appear to be unset (i.e.
+ * default values will apply) this removes the given key (if found) and
+ * references/fallbacks will apply when looking for that key. This is mainly
+ * usefuls for the unit tests.
+ *
+ * @param settings settings to remove key/value from
+ * @param key key including sections, printf style format
+ * @param ... argument list for key
+ */
+void settings_remove_value(settings_t *settings, char *key, ...);
+
#endif /** SETTINGS_H_ @}*/
diff --git a/src/libstrongswan/settings/settings_lexer.c b/src/libstrongswan/settings/settings_lexer.c
index b13ff8009..c29dfa57b 100644
--- a/src/libstrongswan/settings/settings_lexer.c
+++ b/src/libstrongswan/settings/settings_lexer.c
@@ -468,8 +468,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
yyg->yy_c_buf_p = yy_cp;
/* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */
-#define YY_NUM_RULES 30
-#define YY_END_OF_BUFFER 31
+#define YY_NUM_RULES 39
+#define YY_END_OF_BUFFER 40
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -477,15 +477,17 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[63] =
+static yyconst flex_int16_t yy_accept[85] =
{ 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 31, 9,
- 2, 3, 2, 8, 1, 6, 9, 4, 5, 14,
- 11, 12, 10, 13, 20, 16, 15, 17, 18, 29,
- 21, 22, 23, 9, 2, 2, 1, 1, 3, 0,
- 9, 14, 11, 20, 19, 29, 28, 27, 28, 24,
- 25, 26, 1, 9, 9, 9, 9, 9, 0, 7,
- 7, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 40, 12, 2, 3, 2, 11, 1, 7, 6, 8,
+ 9, 12, 4, 5, 17, 14, 15, 14, 18, 13,
+ 16, 23, 20, 21, 19, 22, 29, 25, 24, 26,
+ 27, 38, 30, 31, 32, 12, 2, 2, 1, 1,
+ 3, 0, 12, 17, 0, 14, 14, 13, 13, 15,
+ 0, 23, 20, 29, 28, 38, 37, 36, 37, 33,
+ 34, 35, 1, 12, 17, 13, 12, 12, 12, 12,
+ 0, 10, 10, 0
} ;
static yyconst YY_CHAR yy_ec[256] =
@@ -494,16 +496,16 @@ static yyconst YY_CHAR yy_ec[256] =
1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 5, 1, 6, 7, 1, 1, 1, 1, 1,
+ 1, 1, 1, 8, 1, 9, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 10, 1, 1,
+ 11, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 8, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 9, 1, 1, 1, 1, 1, 1, 10, 11,
+ 1, 12, 1, 1, 1, 1, 1, 1, 13, 14,
- 12, 1, 1, 1, 13, 1, 1, 14, 1, 15,
- 1, 1, 1, 16, 1, 17, 18, 1, 1, 1,
- 1, 1, 19, 1, 20, 1, 1, 1, 1, 1,
+ 15, 1, 1, 1, 16, 1, 1, 17, 1, 18,
+ 1, 1, 1, 19, 1, 20, 21, 1, 1, 1,
+ 1, 1, 22, 1, 23, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -520,113 +522,144 @@ static yyconst YY_CHAR yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst YY_CHAR yy_meta[21] =
+static yyconst YY_CHAR yy_meta[24] =
{ 0,
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 10, 7
+ 1, 2, 3, 4, 5, 6, 5, 7, 8, 7,
+ 9, 10, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 7, 5
} ;
-static yyconst flex_uint16_t yy_base[77] =
+static yyconst flex_uint16_t yy_base[103] =
{ 0,
- 0, 0, 19, 38, 57, 76, 23, 24, 70, 0,
- 95, 244, 0, 244, 31, 244, 54, 244, 244, 0,
- 44, 244, 244, 244, 0, 244, 244, 244, 0, 0,
- 244, 244, 100, 0, 0, 0, 0, 33, 244, 65,
- 57, 0, 45, 0, 244, 0, 244, 244, 62, 244,
- 244, 244, 0, 43, 36, 27, 19, 46, 50, 244,
- 51, 244, 117, 127, 137, 147, 155, 160, 170, 180,
- 186, 193, 203, 213, 223, 233
+ 0, 0, 23, 0, 45, 67, 89, 111, 49, 50,
+ 124, 0, 133, 335, 55, 335, 60, 335, 335, 335,
+ 335, 104, 335, 335, 112, 139, 335, 73, 335, 62,
+ 335, 0, 74, 335, 335, 335, 0, 335, 335, 335,
+ 0, 0, 335, 335, 144, 0, 0, 78, 0, 81,
+ 335, 117, 106, 102, 0, 0, 84, 0, 94, 335,
+ 107, 0, 97, 0, 335, 0, 335, 335, 106, 335,
+ 335, 335, 0, 89, 78, 0, 60, 53, 43, 98,
+ 102, 335, 103, 335, 164, 174, 184, 194, 204, 214,
+ 224, 234, 244, 249, 255, 264, 274, 284, 294, 304,
+
+ 314, 324
} ;
-static yyconst flex_int16_t yy_def[77] =
+static yyconst flex_int16_t yy_def[103] =
{ 0,
- 62, 1, 63, 63, 64, 64, 65, 65, 62, 66,
- 62, 62, 67, 62, 68, 62, 66, 62, 62, 69,
- 62, 62, 62, 62, 70, 62, 62, 62, 71, 72,
- 62, 62, 73, 66, 11, 67, 74, 68, 62, 75,
- 66, 69, 62, 70, 62, 72, 62, 62, 62, 62,
- 62, 62, 74, 66, 66, 66, 66, 66, 76, 62,
- 76, 0, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62
+ 84, 1, 84, 3, 85, 85, 86, 86, 87, 87,
+ 84, 88, 84, 84, 84, 84, 89, 84, 84, 84,
+ 84, 88, 84, 84, 90, 84, 84, 84, 84, 91,
+ 84, 92, 84, 84, 84, 84, 93, 84, 84, 84,
+ 94, 95, 84, 84, 96, 88, 13, 84, 97, 89,
+ 84, 98, 88, 90, 99, 26, 84, 100, 91, 84,
+ 101, 92, 84, 93, 84, 95, 84, 84, 84, 84,
+ 84, 84, 97, 88, 99, 100, 88, 88, 88, 88,
+ 102, 84, 102, 0, 84, 84, 84, 84, 84, 84,
+ 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+
+ 84, 84
} ;
-static yyconst flex_uint16_t yy_nxt[265] =
+static yyconst flex_uint16_t yy_nxt[359] =
{ 0,
- 10, 11, 12, 13, 11, 14, 15, 16, 10, 10,
- 10, 10, 17, 10, 10, 10, 10, 10, 18, 19,
- 21, 22, 23, 21, 24, 22, 31, 31, 32, 32,
- 58, 33, 33, 39, 40, 39, 40, 57, 22, 21,
- 22, 23, 21, 24, 22, 43, 43, 59, 43, 43,
- 59, 61, 61, 56, 61, 61, 55, 22, 26, 26,
- 27, 26, 28, 26, 48, 29, 54, 39, 41, 62,
- 62, 62, 62, 62, 62, 62, 26, 26, 26, 27,
- 26, 28, 26, 62, 29, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 26, 35, 62, 36, 35,
-
- 62, 37, 48, 49, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 50, 51, 52, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 34, 62, 62,
- 62, 62, 62, 62, 62, 34, 36, 62, 36, 36,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 42, 62, 62, 62, 62, 62, 62, 42, 42, 42,
- 44, 62, 62, 62, 62, 62, 62, 44, 62, 44,
- 45, 45, 45, 46, 46, 46, 62, 46, 62, 46,
-
- 46, 62, 46, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 53, 53, 62, 62, 53, 53, 53,
- 53, 53, 53, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 40, 60, 60, 60, 60, 60, 60, 60,
- 62, 60, 60, 9, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62
+ 12, 13, 14, 15, 13, 16, 17, 18, 19, 20,
+ 21, 12, 12, 12, 12, 22, 12, 12, 12, 12,
+ 12, 23, 24, 25, 26, 27, 28, 26, 29, 30,
+ 31, 29, 29, 29, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 29, 29, 33, 34, 35, 33,
+ 36, 34, 43, 43, 44, 44, 48, 80, 48, 48,
+ 45, 45, 51, 52, 60, 61, 79, 34, 33, 34,
+ 35, 33, 36, 34, 57, 63, 57, 57, 63, 48,
+ 78, 48, 48, 51, 52, 57, 55, 57, 57, 34,
+ 38, 38, 39, 38, 40, 38, 60, 61, 63, 81,
+
+ 41, 63, 81, 83, 83, 77, 83, 83, 68, 60,
+ 55, 38, 38, 38, 39, 38, 40, 38, 74, 51,
+ 55, 53, 41, 84, 84, 84, 84, 84, 84, 84,
+ 84, 84, 84, 38, 47, 84, 48, 47, 84, 49,
+ 56, 84, 57, 56, 84, 58, 68, 69, 84, 84,
+ 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+ 84, 70, 71, 72, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 46, 84, 84, 84, 84, 84,
+
+ 84, 84, 84, 46, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 54, 84, 84, 84, 84, 84,
+ 84, 54, 84, 54, 59, 59, 59, 59, 59, 59,
+ 59, 59, 59, 59, 62, 84, 84, 84, 84, 84,
+ 62, 62, 62, 62, 64, 84, 84, 84, 84, 84,
+ 64, 64, 64, 65, 65, 66, 66, 66, 84, 66,
+ 84, 66, 66, 66, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 73, 73, 84, 84, 73, 73,
+ 73, 73, 73, 73, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 75, 84, 84, 84, 84, 84,
+
+ 84, 84, 84, 75, 76, 76, 84, 84, 76, 76,
+ 76, 76, 76, 76, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 61, 82, 82, 82, 82, 82, 82,
+ 82, 82, 84, 82, 11, 84, 84, 84, 84, 84,
+ 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+ 84, 84, 84, 84, 84, 84, 84, 84
} ;
-static yyconst flex_int16_t yy_chk[265] =
+static yyconst flex_int16_t yy_chk[359] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 3, 3, 3, 3, 3, 3, 7, 8, 7, 8,
- 57, 7, 8, 15, 15, 38, 38, 56, 3, 4,
- 4, 4, 4, 4, 4, 21, 43, 58, 21, 43,
- 58, 59, 61, 55, 59, 61, 54, 4, 5, 5,
- 5, 5, 5, 5, 49, 5, 41, 40, 17, 9,
- 0, 0, 0, 0, 0, 0, 5, 6, 6, 6,
- 6, 6, 6, 0, 6, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 6, 11, 0, 11, 11,
-
- 0, 11, 33, 33, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 33, 33, 33, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 66, 0, 0,
- 0, 0, 0, 0, 0, 66, 67, 0, 67, 67,
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
- 69, 0, 0, 0, 0, 0, 0, 69, 69, 69,
- 70, 0, 0, 0, 0, 0, 0, 70, 0, 70,
- 71, 71, 71, 72, 72, 72, 0, 72, 0, 72,
-
- 72, 0, 72, 73, 73, 73, 73, 73, 73, 73,
- 73, 73, 73, 74, 74, 0, 0, 74, 74, 74,
- 74, 74, 74, 75, 75, 75, 75, 75, 75, 75,
- 75, 75, 75, 76, 76, 76, 76, 76, 76, 76,
- 0, 76, 76, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62
+ 1, 1, 1, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 5, 5, 5, 5,
+ 5, 5, 9, 10, 9, 10, 15, 79, 15, 15,
+ 9, 10, 17, 17, 30, 30, 78, 5, 6, 6,
+ 6, 6, 6, 6, 28, 33, 28, 28, 33, 48,
+ 77, 48, 48, 50, 50, 57, 75, 57, 57, 6,
+ 7, 7, 7, 7, 7, 7, 59, 59, 63, 80,
+
+ 7, 63, 80, 81, 83, 74, 81, 83, 69, 61,
+ 54, 7, 8, 8, 8, 8, 8, 8, 53, 52,
+ 25, 22, 8, 11, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 8, 13, 0, 13, 13, 0, 13,
+ 26, 0, 26, 26, 0, 26, 45, 45, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 45, 45, 45, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 88, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 88, 89, 89, 89, 89, 89, 89,
+ 89, 89, 89, 89, 90, 0, 0, 0, 0, 0,
+ 0, 90, 0, 90, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 92, 0, 0, 0, 0, 0,
+ 92, 92, 92, 92, 93, 0, 0, 0, 0, 0,
+ 93, 93, 93, 94, 94, 95, 95, 95, 0, 95,
+ 0, 95, 95, 95, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 97, 97, 0, 0, 97, 97,
+ 97, 97, 97, 97, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 99, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 99, 100, 100, 0, 0, 100, 100,
+ 100, 100, 100, 100, 101, 101, 101, 101, 101, 101,
+ 101, 101, 101, 101, 102, 102, 102, 102, 102, 102,
+ 102, 102, 0, 102, 84, 84, 84, 84, 84, 84,
+ 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+ 84, 84, 84, 84, 84, 84, 84, 84
} ;
/* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[31] =
+static yyconst flex_int32_t yy_rule_can_match_eol[40] =
{ 0,
-0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, };
+0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
+ };
-static yyconst flex_int16_t yy_rule_linenum[30] =
+static yyconst flex_int16_t yy_rule_linenum[39] =
{ 0,
- 61, 62, 63, 65, 66, 68, 73, 78, 83, 89,
- 90, 92, 112, 118, 125, 128, 148, 151, 154, 157,
- 163, 164, 166, 186, 187, 188, 189, 190, 191
+ 66, 67, 68, 70, 71, 73, 74, 76, 81, 86,
+ 91, 96, 102, 103, 104, 106, 108, 113, 120, 121,
+ 123, 144, 150, 157, 160, 180, 183, 186, 189, 195,
+ 196, 198, 218, 219, 220, 221, 222, 223
} ;
/* The intent behind this definition is that it'll catch
@@ -639,7 +672,7 @@ static yyconst flex_int16_t yy_rule_linenum[30] =
#line 1 "settings/settings_lexer.l"
#line 2 "settings/settings_lexer.l"
/*
- * Copyright (C) 2014 Tobias Brunner
+ * Copyright (C) 2014-2018 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -662,7 +695,7 @@ bool settings_parser_open_next_file(parser_helper_t *ctx);
static void include_files(parser_helper_t *ctx);
/* use start conditions stack */
-/* do not declare unneded functions */
+/* do not declare unneeded functions */
#define YY_NO_INPUT 1
/* don't use global variables, and interact properly with bison */
/* maintain the line number */
@@ -670,18 +703,22 @@ static void include_files(parser_helper_t *ctx);
/* prefix function/variable declarations */
/* don't change the name of the output file otherwise autotools has issues */
/* type of our extra data */
+/* state used to scan references */
+
/* state used to scan values */
/* state used to scan include file patterns */
/* state used to scan quoted strings */
-#line 680 "settings/settings_lexer.c"
+/* pattern for section/key names */
+#line 716 "settings/settings_lexer.c"
#define INITIAL 0
-#define val 1
-#define inc 2
-#define str 3
+#define ref 1
+#define val 2
+#define inc 3
+#define str 4
#ifndef YY_NO_UNISTD_H
/* Special case for "unistd.h", since it is non-ANSI. We include it way
@@ -1030,10 +1067,10 @@ YY_DECL
{
/* %% [7.0] user's declarations go here */
-#line 59 "settings/settings_lexer.l"
+#line 64 "settings/settings_lexer.l"
-#line 1037 "settings/settings_lexer.c"
+#line 1074 "settings/settings_lexer.c"
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
@@ -1062,13 +1099,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 63 )
+ if ( yy_current_state >= 85 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
- while ( yy_base[yy_current_state] != 244 );
+ while ( yy_base[yy_current_state] != 335 );
yy_find_action:
/* %% [10.0] code to find the action number goes here */
@@ -1103,13 +1140,13 @@ do_action: /* This label is used only to access EOF actions. */
{
if ( yy_act == 0 )
fprintf( stderr, "--scanner backing up\n" );
- else if ( yy_act < 30 )
+ else if ( yy_act < 39 )
fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
(long)yy_rule_linenum[yy_act], yytext );
- else if ( yy_act == 30 )
+ else if ( yy_act == 39 )
fprintf( stderr, "--accepting default rule (\"%s\")\n",
yytext );
- else if ( yy_act == 31 )
+ else if ( yy_act == 40 )
fprintf( stderr, "--(end of buffer or a NUL)\n" );
else
fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
@@ -1127,81 +1164,138 @@ do_action: /* This label is used only to access EOF actions. */
case 1:
YY_RULE_SETUP
-#line 61 "settings/settings_lexer.l"
+#line 66 "settings/settings_lexer.l"
/* eat comments */
YY_BREAK
case 2:
YY_RULE_SETUP
-#line 62 "settings/settings_lexer.l"
+#line 67 "settings/settings_lexer.l"
/* eat whitespace */
YY_BREAK
case 3:
/* rule 3 can match eol */
YY_RULE_SETUP
-#line 63 "settings/settings_lexer.l"
-return NEWLINE; /* also eats comments at the end of a line */
+#line 68 "settings/settings_lexer.l"
+/* eat newlines and comments at the end of a line */
YY_BREAK
case 4:
-#line 66 "settings/settings_lexer.l"
+#line 71 "settings/settings_lexer.l"
case 5:
YY_RULE_SETUP
-#line 66 "settings/settings_lexer.l"
+#line 71 "settings/settings_lexer.l"
return yytext[0];
YY_BREAK
case 6:
YY_RULE_SETUP
-#line 68 "settings/settings_lexer.l"
+#line 73 "settings/settings_lexer.l"
+return DOT;
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 74 "settings/settings_lexer.l"
+return COMMA;
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 76 "settings/settings_lexer.l"
+{
+ yy_push_state(ref, yyscanner);
+ return COLON;
+}
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 81 "settings/settings_lexer.l"
{
yy_push_state(val, yyscanner);
return yytext[0];
}
YY_BREAK
-case 7:
-/* rule 7 can match eol */
+case 10:
+/* rule 10 can match eol */
*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
YY_LINENO_REWIND_TO(yy_cp - 1);
yyg->yy_c_buf_p = yy_cp -= 1;
YY_DO_BEFORE_ACTION; /* set up yytext again */
YY_RULE_SETUP
-#line 73 "settings/settings_lexer.l"
+#line 86 "settings/settings_lexer.l"
{
yyextra->string_init(yyextra);
yy_push_state(inc, yyscanner);
}
YY_BREAK
-case 8:
+case 11:
YY_RULE_SETUP
-#line 78 "settings/settings_lexer.l"
+#line 91 "settings/settings_lexer.l"
{
PARSER_DBG1(yyextra, "unexpected string detected");
return STRING_ERROR;
}
YY_BREAK
-case 9:
+case 12:
YY_RULE_SETUP
-#line 83 "settings/settings_lexer.l"
+#line 96 "settings/settings_lexer.l"
{
yylval->s = strdup(yytext);
return NAME;
}
YY_BREAK
-case 10:
+case 13:
+YY_RULE_SETUP
+#line 102 "settings/settings_lexer.l"
+/* eat comments */
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 103 "settings/settings_lexer.l"
+/* eat whitespace */
+ YY_BREAK
+case 15:
+/* rule 15 can match eol */
+YY_RULE_SETUP
+#line 104 "settings/settings_lexer.l"
+/* eat newlines and comments at the end of a line */
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 106 "settings/settings_lexer.l"
+return COMMA;
+ YY_BREAK
+case 17:
YY_RULE_SETUP
-#line 89 "settings/settings_lexer.l"
+#line 108 "settings/settings_lexer.l"
+{
+ yylval->s = strdup(yytext);
+ return NAME;
+ }
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 113 "settings/settings_lexer.l"
+{
+ unput(yytext[0]);
+ yy_pop_state(yyscanner);
+ }
+ YY_BREAK
+
+
+case 19:
+YY_RULE_SETUP
+#line 120 "settings/settings_lexer.l"
/* just ignore these */
YY_BREAK
-case 11:
+case 20:
YY_RULE_SETUP
-#line 90 "settings/settings_lexer.l"
+#line 121 "settings/settings_lexer.l"
YY_BREAK
case YY_STATE_EOF(val):
-#line 91 "settings/settings_lexer.l"
-case 12:
-/* rule 12 can match eol */
+#line 122 "settings/settings_lexer.l"
+case 21:
+/* rule 21 can match eol */
YY_RULE_SETUP
-#line 92 "settings/settings_lexer.l"
+#line 123 "settings/settings_lexer.l"
{
if (*yytext)
{
@@ -1220,20 +1314,21 @@ YY_RULE_SETUP
}
}
yy_pop_state(yyscanner);
+ return NEWLINE;
}
YY_BREAK
-case 13:
+case 22:
YY_RULE_SETUP
-#line 112 "settings/settings_lexer.l"
+#line 144 "settings/settings_lexer.l"
{
yyextra->string_init(yyextra);
yy_push_state(str, yyscanner);
}
YY_BREAK
/* same as above, but allow more characters */
-case 14:
+case 23:
YY_RULE_SETUP
-#line 118 "settings/settings_lexer.l"
+#line 150 "settings/settings_lexer.l"
{
yylval->s = strdup(yytext);
return NAME;
@@ -1241,18 +1336,18 @@ YY_RULE_SETUP
YY_BREAK
-case 15:
+case 24:
YY_RULE_SETUP
-#line 125 "settings/settings_lexer.l"
+#line 157 "settings/settings_lexer.l"
/* just ignore these */
YY_BREAK
/* we allow all characters except #, } and spaces, they can be escaped */
case YY_STATE_EOF(inc):
-#line 127 "settings/settings_lexer.l"
-case 16:
-/* rule 16 can match eol */
+#line 159 "settings/settings_lexer.l"
+case 25:
+/* rule 25 can match eol */
YY_RULE_SETUP
-#line 128 "settings/settings_lexer.l"
+#line 160 "settings/settings_lexer.l"
{
if (*yytext)
{
@@ -1274,49 +1369,49 @@ YY_RULE_SETUP
yy_pop_state(yyscanner);
}
YY_BREAK
-case 17:
+case 26:
YY_RULE_SETUP
-#line 148 "settings/settings_lexer.l"
+#line 180 "settings/settings_lexer.l"
{ /* string include */
yy_push_state(str, yyscanner);
}
YY_BREAK
-case 18:
+case 27:
YY_RULE_SETUP
-#line 151 "settings/settings_lexer.l"
+#line 183 "settings/settings_lexer.l"
{
yyextra->string_add(yyextra, yytext);
}
YY_BREAK
-case 19:
+case 28:
YY_RULE_SETUP
-#line 154 "settings/settings_lexer.l"
+#line 186 "settings/settings_lexer.l"
{
yyextra->string_add(yyextra, yytext+1);
}
YY_BREAK
-case 20:
+case 29:
YY_RULE_SETUP
-#line 157 "settings/settings_lexer.l"
+#line 189 "settings/settings_lexer.l"
{
yyextra->string_add(yyextra, yytext);
}
YY_BREAK
-case 21:
+case 30:
YY_RULE_SETUP
-#line 163 "settings/settings_lexer.l"
+#line 195 "settings/settings_lexer.l"
/* just ignore these */
YY_BREAK
-case 22:
-#line 165 "settings/settings_lexer.l"
+case 31:
+#line 197 "settings/settings_lexer.l"
YY_RULE_SETUP
case YY_STATE_EOF(str):
-#line 165 "settings/settings_lexer.l"
-case 23:
+#line 197 "settings/settings_lexer.l"
+case 32:
YY_RULE_SETUP
-#line 166 "settings/settings_lexer.l"
+#line 198 "settings/settings_lexer.l"
{
if (!streq(yytext, "\""))
{
@@ -1337,43 +1432,44 @@ YY_RULE_SETUP
}
}
YY_BREAK
-case 24:
+case 33:
YY_RULE_SETUP
-#line 186 "settings/settings_lexer.l"
+#line 218 "settings/settings_lexer.l"
yyextra->string_add(yyextra, "\n");
YY_BREAK
-case 25:
+case 34:
YY_RULE_SETUP
-#line 187 "settings/settings_lexer.l"
+#line 219 "settings/settings_lexer.l"
yyextra->string_add(yyextra, "\r");
YY_BREAK
-case 26:
+case 35:
YY_RULE_SETUP
-#line 188 "settings/settings_lexer.l"
+#line 220 "settings/settings_lexer.l"
yyextra->string_add(yyextra, "\t");
YY_BREAK
-case 27:
-/* rule 27 can match eol */
+case 36:
+/* rule 36 can match eol */
YY_RULE_SETUP
-#line 189 "settings/settings_lexer.l"
+#line 221 "settings/settings_lexer.l"
/* merge lines that end with escaped EOL characters */
YY_BREAK
-case 28:
+case 37:
YY_RULE_SETUP
-#line 190 "settings/settings_lexer.l"
+#line 222 "settings/settings_lexer.l"
yyextra->string_add(yyextra, yytext+1);
YY_BREAK
-case 29:
-/* rule 29 can match eol */
+case 38:
+/* rule 38 can match eol */
YY_RULE_SETUP
-#line 191 "settings/settings_lexer.l"
+#line 223 "settings/settings_lexer.l"
{
yyextra->string_add(yyextra, yytext);
}
YY_BREAK
case YY_STATE_EOF(INITIAL):
-#line 196 "settings/settings_lexer.l"
+case YY_STATE_EOF(ref):
+#line 228 "settings/settings_lexer.l"
{
settings_parser_pop_buffer_state(yyscanner);
if (!settings_parser_open_next_file(yyextra) && !YY_CURRENT_BUFFER)
@@ -1382,12 +1478,12 @@ case YY_STATE_EOF(INITIAL):
}
}
YY_BREAK
-case 30:
+case 39:
YY_RULE_SETUP
-#line 204 "settings/settings_lexer.l"
+#line 236 "settings/settings_lexer.l"
YY_FATAL_ERROR( "flex scanner jammed" );
YY_BREAK
-#line 1391 "settings/settings_lexer.c"
+#line 1487 "settings/settings_lexer.c"
case YY_END_OF_BUFFER:
{
@@ -1705,7 +1801,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 63 )
+ if ( yy_current_state >= 85 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1739,11 +1835,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 63 )
+ if ( yy_current_state >= 85 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 62);
+ yy_is_jam = (yy_current_state == 84);
(void)yyg;
return yy_is_jam ? 0 : yy_current_state;
@@ -2778,7 +2874,7 @@ void settings_parser_free (void * ptr , yyscan_t yyscanner)
/* %ok-for-header */
-#line 204 "settings/settings_lexer.l"
+#line 236 "settings/settings_lexer.l"
diff --git a/src/libstrongswan/settings/settings_lexer.l b/src/libstrongswan/settings/settings_lexer.l
index fa1ecac10..19ab8d7b2 100644
--- a/src/libstrongswan/settings/settings_lexer.l
+++ b/src/libstrongswan/settings/settings_lexer.l
@@ -1,6 +1,6 @@
%{
/*
- * Copyright (C) 2014 Tobias Brunner
+ * Copyright (C) 2014-2018 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@ static void include_files(parser_helper_t *ctx);
/* use start conditions stack */
%option stack
-/* do not declare unneded functions */
+/* do not declare unneeded functions */
%option noinput noyywrap
/* don't use global variables, and interact properly with bison */
@@ -49,6 +49,8 @@ static void include_files(parser_helper_t *ctx);
/* type of our extra data */
%option extra-type="parser_helper_t*"
+/* state used to scan references */
+%x ref
/* state used to scan values */
%x val
/* state used to scan include file patterns */
@@ -56,15 +58,26 @@ static void include_files(parser_helper_t *ctx);
/* state used to scan quoted strings */
%x str
+/* pattern for section/key names */
+NAME [^#{}:.,="\r\n\t ]
+
%%
[\t ]*#[^\r\n]* /* eat comments */
[\t\r ]+ /* eat whitespace */
-\n|#.*\n return NEWLINE; /* also eats comments at the end of a line */
+\n|#.*\n /* eat newlines and comments at the end of a line */
"{" |
"}" return yytext[0];
+"." return DOT;
+"," return COMMA;
+
+":" {
+ yy_push_state(ref, yyscanner);
+ return COLON;
+}
+
"=" {
yy_push_state(val, yyscanner);
return yytext[0];
@@ -80,16 +93,34 @@ static void include_files(parser_helper_t *ctx);
return STRING_ERROR;
}
-[^#{}="\r\n\t ]+ {
+{NAME}+ {
yylval->s = strdup(yytext);
return NAME;
}
+<ref>{
+ [\t ]*#[^\r\n]* /* eat comments */
+ [\t\r ]+ /* eat whitespace */
+ \n|#.*\n /* eat newlines and comments at the end of a line */
+
+ "," return COMMA;
+
+ {NAME}+(\.{NAME}+)* {
+ yylval->s = strdup(yytext);
+ return NAME;
+ }
+
+ . {
+ unput(yytext[0]);
+ yy_pop_state(yyscanner);
+ }
+}
+
<val>{
\r /* just ignore these */
[\t ]+
<<EOF>> |
- [#}\n] {
+ [#}\n] {
if (*yytext)
{
switch (yytext[0])
@@ -107,15 +138,16 @@ static void include_files(parser_helper_t *ctx);
}
}
yy_pop_state(yyscanner);
+ return NEWLINE;
}
- "\"" {
+ "\"" {
yyextra->string_init(yyextra);
yy_push_state(str, yyscanner);
}
/* same as above, but allow more characters */
- [^#}"\r\n\t ]+ {
+ [^#}"\r\n\t ]+ {
yylval->s = strdup(yytext);
return NAME;
}
diff --git a/src/libstrongswan/settings/settings_parser.c b/src/libstrongswan/settings/settings_parser.c
index 3d1a2ba27..ad3d5288c 100644
--- a/src/libstrongswan/settings/settings_parser.c
+++ b/src/libstrongswan/settings/settings_parser.c
@@ -71,7 +71,7 @@
#line 1 "settings/settings_parser.y" /* yacc.c:339 */
/*
- * Copyright (C) 2014 Tobias Brunner
+ * Copyright (C) 2014-2018 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -120,6 +120,7 @@ static section_t *push_section(parser_helper_t *ctx, char *name);
static section_t *pop_section(parser_helper_t *ctx);
static void add_section(parser_helper_t *ctx, section_t *section);
static void add_setting(parser_helper_t *ctx, kv_t *kv);
+static void add_references(parser_helper_t *ctx, array_t *references);
/**
* Make sure to call lexer with the proper context
@@ -131,7 +132,7 @@ static int yylex(YYSTYPE *lvalp, parser_helper_t *ctx)
}
-#line 135 "settings/settings_parser.c" /* yacc.c:339 */
+#line 136 "settings/settings_parser.c" /* yacc.c:339 */
# ifndef YY_NULLPTR
# if defined __cplusplus && 201103L <= __cplusplus
@@ -168,28 +169,35 @@ extern int settings_parser_debug;
{
NAME = 258,
STRING = 259,
- NEWLINE = 260,
- STRING_ERROR = 261
+ DOT = 260,
+ COMMA = 261,
+ COLON = 262,
+ NEWLINE = 263,
+ STRING_ERROR = 264
};
#endif
/* Tokens. */
#define NAME 258
#define STRING 259
-#define NEWLINE 260
-#define STRING_ERROR 261
+#define DOT 260
+#define COMMA 261
+#define COLON 262
+#define NEWLINE 263
+#define STRING_ERROR 264
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
union YYSTYPE
{
-#line 77 "settings/settings_parser.y" /* yacc.c:355 */
+#line 78 "settings/settings_parser.y" /* yacc.c:355 */
char *s;
struct section_t *sec;
struct kv_t *kv;
+ array_t *refs;
-#line 193 "settings/settings_parser.c" /* yacc.c:355 */
+#line 201 "settings/settings_parser.c" /* yacc.c:355 */
};
typedef union YYSTYPE YYSTYPE;
@@ -205,7 +213,7 @@ int settings_parser_parse (parser_helper_t *ctx);
/* Copy the second part of user declarations. */
-#line 209 "settings/settings_parser.c" /* yacc.c:358 */
+#line 217 "settings/settings_parser.c" /* yacc.c:358 */
#ifdef short
# undef short
@@ -447,21 +455,21 @@ union yyalloc
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 2
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 13
+#define YYLAST 19
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 10
+#define YYNTOKENS 13
/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 8
+#define YYNNTS 9
/* YYNRULES -- Number of rules. */
-#define YYNRULES 15
+#define YYNRULES 17
/* YYNSTATES -- Number of states. */
-#define YYNSTATES 20
+#define YYNSTATES 24
/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
by yylex, with out-of-bounds checking. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 261
+#define YYMAXUTOK 264
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -476,13 +484,13 @@ static const yytype_uint8 yytranslate[] =
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 9, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 12, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 8, 2, 7, 2, 2, 2, 2,
+ 2, 2, 2, 11, 2, 10, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -496,15 +504,15 @@ static const yytype_uint8 yytranslate[] =
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
- 5, 6
+ 5, 6, 7, 8, 9
};
#if YYDEBUG
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 105, 105, 107, 108, 112, 116, 123, 131, 136,
- 143, 148, 155, 156, 170, 171
+ 0, 112, 112, 114, 115, 119, 123, 130, 138, 143,
+ 152, 157, 165, 170, 177, 178, 192, 193
};
#endif
@@ -513,9 +521,10 @@ static const yytype_uint8 yyrline[] =
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
- "$end", "error", "$undefined", "NAME", "STRING", "NEWLINE",
- "STRING_ERROR", "'}'", "'{'", "'='", "$accept", "statements",
- "statement", "section", "section_start", "setting", "value", "valuepart", YY_NULLPTR
+ "$end", "error", "$undefined", "NAME", "STRING", "\".\"", "\",\"",
+ "\":\"", "NEWLINE", "STRING_ERROR", "'}'", "'{'", "'='", "$accept",
+ "statements", "statement", "section", "section_start", "references",
+ "setting", "value", "valuepart", YY_NULLPTR
};
#endif
@@ -524,14 +533,15 @@ static const char *const yytname[] =
(internal) symbol number NUM (which must be that of a token). */
static const yytype_uint16 yytoknum[] =
{
- 0, 256, 257, 258, 259, 260, 261, 125, 123, 61
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 125, 123, 61
};
# endif
-#define YYPACT_NINF -11
+#define YYPACT_NINF -7
#define yypact_value_is_default(Yystate) \
- (!!((Yystate) == (-11)))
+ (!!((Yystate) == (-7)))
#define YYTABLE_NINF -1
@@ -542,8 +552,9 @@ static const yytype_uint16 yytoknum[] =
STATE-NUM. */
static const yytype_int8 yypact[] =
{
- -11, 0, -11, -1, -11, -11, -11, -11, -11, 2,
- -11, -2, 6, -11, -11, -11, -2, -11, -11, -11
+ -7, 0, -7, -6, -7, -7, -7, -7, -7, 1,
+ -7, 8, -1, -7, 4, -7, -7, 8, -7, -7,
+ 10, -7, -7, -7
};
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -552,19 +563,20 @@ static const yytype_int8 yypact[] =
static const yytype_uint8 yydefact[] =
{
2, 0, 1, 0, 3, 4, 5, 2, 6, 0,
- 8, 11, 0, 9, 14, 15, 10, 12, 7, 13
+ 8, 13, 0, 10, 0, 16, 17, 12, 14, 7,
+ 0, 9, 15, 11
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int8 yypgoto[] =
{
- -11, 5, -11, -11, -11, -11, -11, -10
+ -7, 7, -7, -7, -7, -7, -7, -7, 2
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int8 yydefgoto[] =
{
- -1, 1, 5, 6, 7, 8, 16, 17
+ -1, 1, 5, 6, 7, 14, 8, 17, 18
};
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
@@ -572,36 +584,37 @@ static const yytype_int8 yydefgoto[] =
number is the opposite. If YYTABLE_NINF, syntax error. */
static const yytype_uint8 yytable[] =
{
- 2, 14, 15, 3, 9, 4, 19, 10, 11, 3,
- 13, 4, 12, 18
+ 2, 9, 3, 3, 13, 10, 11, 4, 4, 19,
+ 20, 15, 16, 23, 12, 21, 0, 0, 0, 22
};
-static const yytype_uint8 yycheck[] =
+static const yytype_int8 yycheck[] =
{
- 0, 3, 4, 3, 5, 5, 16, 8, 9, 3,
- 8, 5, 7, 7
+ 0, 7, 3, 3, 3, 11, 12, 8, 8, 10,
+ 6, 3, 4, 3, 7, 11, -1, -1, -1, 17
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 11, 0, 3, 5, 12, 13, 14, 15, 5,
- 8, 9, 11, 8, 3, 4, 16, 17, 7, 17
+ 0, 14, 0, 3, 8, 15, 16, 17, 19, 7,
+ 11, 12, 14, 3, 18, 3, 4, 20, 21, 10,
+ 6, 11, 21, 3
};
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
- 0, 10, 11, 11, 11, 12, 12, 13, 14, 14,
- 15, 15, 16, 16, 17, 17
+ 0, 13, 14, 14, 14, 15, 15, 16, 17, 17,
+ 18, 18, 19, 19, 20, 20, 21, 21
};
/* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
static const yytype_uint8 yyr2[] =
{
- 0, 2, 0, 2, 2, 1, 1, 3, 2, 3,
- 3, 2, 1, 2, 1, 1
+ 0, 2, 0, 2, 2, 1, 1, 3, 2, 4,
+ 1, 3, 3, 2, 1, 2, 1, 1
};
@@ -1027,45 +1040,51 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, parser_helper_t *c
switch (yytype)
{
case 3: /* NAME */
-#line 91 "settings/settings_parser.y" /* yacc.c:1257 */
+#line 97 "settings/settings_parser.y" /* yacc.c:1257 */
{ free(((*yyvaluep).s)); }
-#line 1033 "settings/settings_parser.c" /* yacc.c:1257 */
+#line 1046 "settings/settings_parser.c" /* yacc.c:1257 */
break;
case 4: /* STRING */
-#line 91 "settings/settings_parser.y" /* yacc.c:1257 */
+#line 97 "settings/settings_parser.y" /* yacc.c:1257 */
{ free(((*yyvaluep).s)); }
-#line 1039 "settings/settings_parser.c" /* yacc.c:1257 */
+#line 1052 "settings/settings_parser.c" /* yacc.c:1257 */
break;
- case 13: /* section */
-#line 93 "settings/settings_parser.y" /* yacc.c:1257 */
+ case 16: /* section */
+#line 99 "settings/settings_parser.y" /* yacc.c:1257 */
{ pop_section(ctx); settings_section_destroy(((*yyvaluep).sec), NULL); }
-#line 1045 "settings/settings_parser.c" /* yacc.c:1257 */
+#line 1058 "settings/settings_parser.c" /* yacc.c:1257 */
break;
- case 14: /* section_start */
-#line 93 "settings/settings_parser.y" /* yacc.c:1257 */
+ case 17: /* section_start */
+#line 99 "settings/settings_parser.y" /* yacc.c:1257 */
{ pop_section(ctx); settings_section_destroy(((*yyvaluep).sec), NULL); }
-#line 1051 "settings/settings_parser.c" /* yacc.c:1257 */
+#line 1064 "settings/settings_parser.c" /* yacc.c:1257 */
break;
- case 15: /* setting */
-#line 94 "settings/settings_parser.y" /* yacc.c:1257 */
+ case 18: /* references */
+#line 101 "settings/settings_parser.y" /* yacc.c:1257 */
+ { array_destroy_function(((*yyvaluep).refs), (void*)free, NULL); }
+#line 1070 "settings/settings_parser.c" /* yacc.c:1257 */
+ break;
+
+ case 19: /* setting */
+#line 100 "settings/settings_parser.y" /* yacc.c:1257 */
{ settings_kv_destroy(((*yyvaluep).kv), NULL); }
-#line 1057 "settings/settings_parser.c" /* yacc.c:1257 */
+#line 1076 "settings/settings_parser.c" /* yacc.c:1257 */
break;
- case 16: /* value */
-#line 91 "settings/settings_parser.y" /* yacc.c:1257 */
+ case 20: /* value */
+#line 97 "settings/settings_parser.y" /* yacc.c:1257 */
{ free(((*yyvaluep).s)); }
-#line 1063 "settings/settings_parser.c" /* yacc.c:1257 */
+#line 1082 "settings/settings_parser.c" /* yacc.c:1257 */
break;
- case 17: /* valuepart */
-#line 91 "settings/settings_parser.y" /* yacc.c:1257 */
+ case 21: /* valuepart */
+#line 97 "settings/settings_parser.y" /* yacc.c:1257 */
{ free(((*yyvaluep).s)); }
-#line 1069 "settings/settings_parser.c" /* yacc.c:1257 */
+#line 1088 "settings/settings_parser.c" /* yacc.c:1257 */
break;
@@ -1331,64 +1350,84 @@ yyreduce:
switch (yyn)
{
case 5:
-#line 113 "settings/settings_parser.y" /* yacc.c:1646 */
+#line 120 "settings/settings_parser.y" /* yacc.c:1646 */
{
add_section(ctx, (yyvsp[0].sec));
}
-#line 1339 "settings/settings_parser.c" /* yacc.c:1646 */
+#line 1358 "settings/settings_parser.c" /* yacc.c:1646 */
break;
case 6:
-#line 117 "settings/settings_parser.y" /* yacc.c:1646 */
+#line 124 "settings/settings_parser.y" /* yacc.c:1646 */
{
add_setting(ctx, (yyvsp[0].kv));
}
-#line 1347 "settings/settings_parser.c" /* yacc.c:1646 */
+#line 1366 "settings/settings_parser.c" /* yacc.c:1646 */
break;
case 7:
-#line 124 "settings/settings_parser.y" /* yacc.c:1646 */
+#line 131 "settings/settings_parser.y" /* yacc.c:1646 */
{
pop_section(ctx);
(yyval.sec) = (yyvsp[-2].sec);
}
-#line 1356 "settings/settings_parser.c" /* yacc.c:1646 */
+#line 1375 "settings/settings_parser.c" /* yacc.c:1646 */
break;
case 8:
-#line 132 "settings/settings_parser.y" /* yacc.c:1646 */
+#line 139 "settings/settings_parser.y" /* yacc.c:1646 */
{
(yyval.sec) = push_section(ctx, (yyvsp[-1].s));
}
-#line 1364 "settings/settings_parser.c" /* yacc.c:1646 */
+#line 1383 "settings/settings_parser.c" /* yacc.c:1646 */
break;
case 9:
-#line 137 "settings/settings_parser.y" /* yacc.c:1646 */
+#line 144 "settings/settings_parser.y" /* yacc.c:1646 */
{
- (yyval.sec) = push_section(ctx, (yyvsp[-2].s));
+ (yyval.sec) = push_section(ctx, (yyvsp[-3].s));
+ add_references(ctx, (yyvsp[-1].refs));
+ array_destroy((yyvsp[-1].refs));
}
-#line 1372 "settings/settings_parser.c" /* yacc.c:1646 */
+#line 1393 "settings/settings_parser.c" /* yacc.c:1646 */
break;
case 10:
-#line 144 "settings/settings_parser.y" /* yacc.c:1646 */
+#line 153 "settings/settings_parser.y" /* yacc.c:1646 */
{
- (yyval.kv) = settings_kv_create((yyvsp[-2].s), (yyvsp[0].s));
+ (yyval.refs) = array_create(0, 0);
+ array_insert((yyval.refs), ARRAY_TAIL, (yyvsp[0].s));
}
-#line 1380 "settings/settings_parser.c" /* yacc.c:1646 */
+#line 1402 "settings/settings_parser.c" /* yacc.c:1646 */
break;
case 11:
-#line 149 "settings/settings_parser.y" /* yacc.c:1646 */
+#line 158 "settings/settings_parser.y" /* yacc.c:1646 */
{
- (yyval.kv) = settings_kv_create((yyvsp[-1].s), NULL);
+ array_insert((yyvsp[-2].refs), ARRAY_TAIL, (yyvsp[0].s));
+ (yyval.refs) = (yyvsp[-2].refs);
}
-#line 1388 "settings/settings_parser.c" /* yacc.c:1646 */
+#line 1411 "settings/settings_parser.c" /* yacc.c:1646 */
+ break;
+
+ case 12:
+#line 166 "settings/settings_parser.y" /* yacc.c:1646 */
+ {
+ (yyval.kv) = settings_kv_create((yyvsp[-2].s), (yyvsp[0].s));
+ }
+#line 1419 "settings/settings_parser.c" /* yacc.c:1646 */
break;
case 13:
-#line 157 "settings/settings_parser.y" /* yacc.c:1646 */
+#line 171 "settings/settings_parser.y" /* yacc.c:1646 */
+ {
+ (yyval.kv) = settings_kv_create((yyvsp[-1].s), NULL);
+ }
+#line 1427 "settings/settings_parser.c" /* yacc.c:1646 */
+ break;
+
+ case 15:
+#line 179 "settings/settings_parser.y" /* yacc.c:1646 */
{ /* just put a single space between them, use strings for more */
if (asprintf(&(yyval.s), "%s %s", (yyvsp[-1].s), (yyvsp[0].s)) < 0)
{
@@ -1399,11 +1438,11 @@ yyreduce:
free((yyvsp[-1].s));
free((yyvsp[0].s));
}
-#line 1403 "settings/settings_parser.c" /* yacc.c:1646 */
+#line 1442 "settings/settings_parser.c" /* yacc.c:1646 */
break;
-#line 1407 "settings/settings_parser.c" /* yacc.c:1646 */
+#line 1446 "settings/settings_parser.c" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -1631,7 +1670,7 @@ yyreturn:
#endif
return yyresult;
}
-#line 174 "settings/settings_parser.y" /* yacc.c:1906 */
+#line 196 "settings/settings_parser.y" /* yacc.c:1906 */
/**
@@ -1700,6 +1739,27 @@ static void add_setting(parser_helper_t *ctx, kv_t *kv)
}
/**
+ * Adds the given references to the section on top of the stack
+ */
+static void add_references(parser_helper_t *ctx, array_t *references)
+{
+ array_t *sections = (array_t*)ctx->context;
+ section_t *section;
+ enumerator_t *refs;
+ char *ref;
+
+ array_get(sections, ARRAY_TAIL, &section);
+
+ refs = array_create_enumerator(references);
+ while (refs->enumerate(refs, &ref))
+ {
+ settings_reference_add(section, ref, FALSE);
+ array_remove_at(references, refs);
+ }
+ refs->destroy(refs);
+}
+
+/**
* Parse the given file and add all sections and key/value pairs to the
* given section.
*/
diff --git a/src/libstrongswan/settings/settings_parser.h b/src/libstrongswan/settings/settings_parser.h
index b41e0d56f..7c2a82841 100644
--- a/src/libstrongswan/settings/settings_parser.h
+++ b/src/libstrongswan/settings/settings_parser.h
@@ -47,28 +47,35 @@ extern int settings_parser_debug;
{
NAME = 258,
STRING = 259,
- NEWLINE = 260,
- STRING_ERROR = 261
+ DOT = 260,
+ COMMA = 261,
+ COLON = 262,
+ NEWLINE = 263,
+ STRING_ERROR = 264
};
#endif
/* Tokens. */
#define NAME 258
#define STRING 259
-#define NEWLINE 260
-#define STRING_ERROR 261
+#define DOT 260
+#define COMMA 261
+#define COLON 262
+#define NEWLINE 263
+#define STRING_ERROR 264
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
union YYSTYPE
{
-#line 77 "settings/settings_parser.y" /* yacc.c:1909 */
+#line 78 "settings/settings_parser.y" /* yacc.c:1909 */
char *s;
struct section_t *sec;
struct kv_t *kv;
+ array_t *refs;
-#line 72 "settings/settings_parser.h" /* yacc.c:1909 */
+#line 79 "settings/settings_parser.h" /* yacc.c:1909 */
};
typedef union YYSTYPE YYSTYPE;
diff --git a/src/libstrongswan/settings/settings_parser.y b/src/libstrongswan/settings/settings_parser.y
index 2ab9ea723..cc1c91775 100644
--- a/src/libstrongswan/settings/settings_parser.y
+++ b/src/libstrongswan/settings/settings_parser.y
@@ -1,6 +1,6 @@
%{
/*
- * Copyright (C) 2014 Tobias Brunner
+ * Copyright (C) 2014-2018 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -49,6 +49,7 @@ static section_t *push_section(parser_helper_t *ctx, char *name);
static section_t *pop_section(parser_helper_t *ctx);
static void add_section(parser_helper_t *ctx, section_t *section);
static void add_setting(parser_helper_t *ctx, kv_t *kv);
+static void add_references(parser_helper_t *ctx, array_t *references);
/**
* Make sure to call lexer with the proper context
@@ -78,20 +79,26 @@ static int yylex(YYSTYPE *lvalp, parser_helper_t *ctx)
char *s;
struct section_t *sec;
struct kv_t *kv;
+ array_t *refs;
}
%token <s> NAME STRING
+%token DOT "."
+%token COMMA ","
+%token COLON ":"
%token NEWLINE STRING_ERROR
/* ...and other symbols */
%type <s> value valuepart
%type <sec> section_start section
%type <kv> setting
+%type <refs> references
/* properly destroy string tokens that are strdup()ed on error */
%destructor { free($$); } NAME STRING value valuepart
/* properly destroy parse results on error */
%destructor { pop_section(ctx); settings_section_destroy($$, NULL); } section_start section
%destructor { settings_kv_destroy($$, NULL); } setting
+%destructor { array_destroy_function($$, (void*)free, NULL); } references
/* there are two shift/reduce conflicts because of the "NAME = NAME" and
* "NAME {" ambiguity, and the "NAME =" rule) */
@@ -133,9 +140,24 @@ section_start:
$$ = push_section(ctx, $NAME);
}
|
- NAME NEWLINE '{'
+ NAME ":" references '{'
{
$$ = push_section(ctx, $NAME);
+ add_references(ctx, $references);
+ array_destroy($references);
+ }
+ ;
+
+references:
+ NAME
+ {
+ $$ = array_create(0, 0);
+ array_insert($$, ARRAY_TAIL, $1);
+ }
+ | references "," NAME
+ {
+ array_insert($1, ARRAY_TAIL, $3);
+ $$ = $1;
}
;
@@ -239,6 +261,27 @@ static void add_setting(parser_helper_t *ctx, kv_t *kv)
}
/**
+ * Adds the given references to the section on top of the stack
+ */
+static void add_references(parser_helper_t *ctx, array_t *references)
+{
+ array_t *sections = (array_t*)ctx->context;
+ section_t *section;
+ enumerator_t *refs;
+ char *ref;
+
+ array_get(sections, ARRAY_TAIL, &section);
+
+ refs = array_create_enumerator(references);
+ while (refs->enumerate(refs, &ref))
+ {
+ settings_reference_add(section, ref, FALSE);
+ array_remove_at(references, refs);
+ }
+ refs->destroy(refs);
+}
+
+/**
* Parse the given file and add all sections and key/value pairs to the
* given section.
*/
diff --git a/src/libstrongswan/settings/settings_types.c b/src/libstrongswan/settings/settings_types.c
index 1c2d61de7..625b70409 100644
--- a/src/libstrongswan/settings/settings_types.c
+++ b/src/libstrongswan/settings/settings_types.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2014 Tobias Brunner
+ * Copyright (C) 2010-2018 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -69,6 +69,12 @@ static void kv_destroy(kv_t *kv, int idx, array_t *contents)
settings_kv_destroy(kv, contents);
}
+static void ref_destroy(section_ref_t *ref, int idx, void *ctx)
+{
+ free(ref->name);
+ free(ref);
+}
+
/*
* Described in header
*/
@@ -78,7 +84,7 @@ void settings_section_destroy(section_t *this, array_t *contents)
array_destroy(this->sections_order);
array_destroy_function(this->kv, (void*)kv_destroy, contents);
array_destroy(this->kv_order);
- array_destroy(this->fallbacks);
+ array_destroy_function(this->references, (void*)ref_destroy, NULL);
free(this->name);
free(this);
}
@@ -130,6 +136,35 @@ void settings_kv_add(section_t *section, kv_t *kv, array_t *contents)
}
/*
+ * Described in header
+ */
+void settings_reference_add(section_t *section, char *name, bool permanent)
+{
+ section_ref_t *ref;
+ int i;
+
+ for (i = 0; i < array_count(section->references); i++)
+ {
+ array_get(section->references, i, &ref);
+ if (ref->permanent && !permanent)
+ { /* add it before any permanent references */
+ break;
+ }
+ if (ref->permanent == permanent && streq(name, ref->name))
+ {
+ free(name);
+ return;
+ }
+ }
+
+ INIT(ref,
+ .name = name,
+ .permanent = permanent,
+ );
+ array_insert_create(&section->references, i, ref);
+}
+
+/*
* Add a section to the given parent, optionally remove settings/subsections
* not found when extending an existing section
*/
@@ -167,14 +202,28 @@ void settings_section_add(section_t *parent, section_t *section,
static bool section_purge(section_t *this, array_t *contents)
{
section_t *current;
+ section_ref_t *ref;
int i, idx;
array_destroy_function(this->kv, (void*)kv_destroy, contents);
this->kv = NULL;
array_destroy(this->kv_order);
this->kv_order = NULL;
- /* we ensure sections used as fallback, or configured with fallbacks (or
- * having any such subsections) are not removed */
+ /* remove non-permanent references */
+ for (i = array_count(this->references) - 1; i >= 0; i--)
+ {
+ array_get(this->references, i, &ref);
+ if (!ref->permanent)
+ {
+ array_remove(this->references, i, NULL);
+ ref_destroy(ref, 0, NULL);
+ }
+ }
+ if (!array_count(this->references))
+ {
+ array_destroy(this->references);
+ this->references = NULL;
+ }
for (i = array_count(this->sections_order) - 1; i >= 0; i--)
{
array_get(this->sections_order, i, &current);
@@ -187,7 +236,9 @@ static bool section_purge(section_t *this, array_t *contents)
settings_section_destroy(current, contents);
}
}
- return !this->fallbacks && !array_count(this->sections);
+ /* we ensure sections configured with permanent references (or having any
+ * such subsections) are not removed */
+ return !this->references && !array_count(this->sections);
}
/*
@@ -198,14 +249,15 @@ void settings_section_extend(section_t *base, section_t *extension,
{
enumerator_t *enumerator;
section_t *section;
+ section_ref_t *ref;
kv_t *kv;
array_t *sections = NULL, *kvs = NULL;
int idx;
if (purge)
- { /* remove sections and settings in base not found in extension, the
- * others are removed too (from the _order list) so they can be inserted
- * in the order found in extension */
+ { /* remove sections, settings in base not found in extension, the others
+ * are removed too (from the _order list) so they can be inserted in the
+ * order found in extension, non-permanent references are removed */
enumerator = array_create_enumerator(base->sections_order);
while (enumerator->enumerate(enumerator, (void**)&section))
{
@@ -245,6 +297,18 @@ void settings_section_extend(section_t *base, section_t *extension,
array_sort(kvs, settings_kv_sort, NULL);
}
}
+
+ enumerator = array_create_enumerator(base->references);
+ while (enumerator->enumerate(enumerator, (void**)&ref))
+ {
+ if (ref->permanent)
+ { /* permanent references are ignored */
+ continue;
+ }
+ array_remove_at(base->references, enumerator);
+ ref_destroy(ref, 0, NULL);
+ }
+ enumerator->destroy(enumerator);
}
while (array_remove(extension->sections_order, 0, &section))
@@ -278,6 +342,16 @@ void settings_section_extend(section_t *base, section_t *extension,
array_remove(extension->kv, idx, NULL);
settings_kv_add(base, kv, contents);
}
+
+ while (array_remove(extension->references, 0, &ref))
+ {
+ if (ref->permanent)
+ { /* ignore permanent references in the extension */
+ continue;
+ }
+ settings_reference_add(base, strdup(ref->name), FALSE);
+ ref_destroy(ref, 0, NULL);
+ }
array_destroy(sections);
array_destroy(kvs);
}
diff --git a/src/libstrongswan/settings/settings_types.h b/src/libstrongswan/settings/settings_types.h
index 82bcb230a..8163a0134 100644
--- a/src/libstrongswan/settings/settings_types.h
+++ b/src/libstrongswan/settings/settings_types.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2014 Tobias Brunner
+ * Copyright (C) 2010-2018 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
#define SETTINGS_TYPES_H_
typedef struct kv_t kv_t;
+typedef struct section_ref_t section_ref_t;
typedef struct section_t section_t;
#include "collections/array.h"
@@ -45,6 +46,23 @@ struct kv_t {
};
/**
+ * Section reference.
+ */
+struct section_ref_t {
+
+ /**
+ * Name of the referenced section.
+ */
+ char *name;
+
+ /**
+ * TRUE for permanent references that were added programmatically via
+ * add_fallback() and are not removed during reloads/purges.
+ */
+ bool permanent;
+};
+
+/**
* Section containing subsections and key value pairs.
*/
struct section_t {
@@ -55,9 +73,9 @@ struct section_t {
char *name;
/**
- * Fallback sections, as section_t.
+ * Referenced sections, as section_ref_t.
*/
- array_t *fallbacks;
+ array_t *references;
/**
* Subsections, as section_t.
@@ -116,6 +134,15 @@ void settings_kv_set(kv_t *kv, char *value, array_t *contents);
void settings_kv_add(section_t *section, kv_t *kv, array_t *contents);
/**
+ * Add a reference to another section.
+ *
+ * @param section section to which to add the reference
+ * @param name name of the referenced section (adopted)
+ * @param permanent whether the reference is not removed during reloads
+ */
+void settings_reference_add(section_t *section, char *name, bool permanent);
+
+/**
* Create a section with the given name.
*
* @param name name (gets adopted)