diff options
Diffstat (limited to 'src/libstrongswan/settings')
-rw-r--r-- | src/libstrongswan/settings/settings.c | 452 | ||||
-rw-r--r-- | src/libstrongswan/settings/settings.h | 26 | ||||
-rw-r--r-- | src/libstrongswan/settings/settings_lexer.c | 466 | ||||
-rw-r--r-- | src/libstrongswan/settings/settings_lexer.l | 46 | ||||
-rw-r--r-- | src/libstrongswan/settings/settings_parser.c | 224 | ||||
-rw-r--r-- | src/libstrongswan/settings/settings_parser.h | 19 | ||||
-rw-r--r-- | src/libstrongswan/settings/settings_parser.y | 47 | ||||
-rw-r--r-- | src/libstrongswan/settings/settings_types.c | 90 | ||||
-rw-r--r-- | src/libstrongswan/settings/settings_types.h | 33 |
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, ¤t); + 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), §ions); - 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, §ions); 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, §ions); 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, §ions); 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, §ion); + + 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, §ion); + + 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(§ion->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, ¤t); @@ -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**)§ion)) { @@ -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, §ion)) @@ -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) |