From: Michael Tremer Date: Mon, 24 May 2021 13:00:17 +0000 (+0000) Subject: parser: Implement fetching recursive variables X-Git-Tag: 0.9.28~1285^2~85 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f4d930714790b39ab1efd4aa8a8f021e693360fa;p=pakfire.git parser: Implement fetching recursive variables Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/include/pakfire/util.h b/src/libpakfire/include/pakfire/util.h index 74c4f5f33..e861c61f0 100644 --- a/src/libpakfire/include/pakfire/util.h +++ b/src/libpakfire/include/pakfire/util.h @@ -41,6 +41,7 @@ void pakfire_parse_deps(Pakfire pakfire, PakfirePackage pkg, int pakfire_string_startswith(const char* s, const char* prefix); int pakfire_string_endswith(const char* s, const char* suffix); +int pakfire_string_matches(const char* s, const char* pattern); char* pakfire_unquote_in_place(char* s); int pakfire_string_partition(const char* s, const char* delim, char** s1, char** s2); char* pakfire_string_replace(const char* s, const char* pattern, const char* repl); diff --git a/src/libpakfire/parser.c b/src/libpakfire/parser.c index 2ac993925..99991038c 100644 --- a/src/libpakfire/parser.c +++ b/src/libpakfire/parser.c @@ -202,6 +202,11 @@ static struct pakfire_parser_declaration* pakfire_parser_get_declaration( if (!namespace) namespace = ""; + if (namespace) + DEBUG(parser->pakfire, "Looking up %s.%s\n", namespace, name); + else + DEBUG(parser->pakfire, "Looking up %s\n", name); + struct pakfire_parser_declaration* d; for (unsigned i = 0; i < parser->num_declarations; i++) { d = parser->declarations[i]; @@ -305,7 +310,7 @@ static const char* pakfire_parser_get_raw(PakfireParser parser, const char* name d = pakfire_parser_get_declaration(parser, namespace, name); // Return a match when it actually contains a string - if (d) + if (d && d->value) return d->value; // We are done, if the namespace is empty @@ -321,7 +326,7 @@ static const char* pakfire_parser_get_raw(PakfireParser parser, const char* name if (*template) { d = pakfire_parser_get_declaration(parser, template, name); - if (d) + if (d && d->value) return d->value; } } @@ -334,7 +339,7 @@ static const char* pakfire_parser_get_raw(PakfireParser parser, const char* name pakfire_parser_strip_namespace(&n); d = pakfire_parser_get_declaration(parser, n, name); - if (d) + if (d && d->value) return d->value; // End if we have exhausted the namespace @@ -504,6 +509,11 @@ static int pakfire_parser_expand_variables(PakfireParser parser, break; } + // Find the entire matched pattern + r = pcre2_substring_get_bynumber(match, 0, &pattern, &pattern_length); + if (r) + goto ERROR; + // Find the variable name r = pcre2_substring_get_bynumber(match, 1, &variable, &variable_length); if (r) @@ -514,6 +524,23 @@ static int pakfire_parser_expand_variables(PakfireParser parser, // Search for a declaration of this variable const char* repl = pakfire_parser_get_raw(parser, namespace, (const char*)variable); + // Is this a recursive pattern? + if (repl && pakfire_string_matches(repl, (const char*)pattern)) { + DEBUG(parser->pakfire, "Recursion detected in %s\n", pattern); + + // Move up one step and lookup there + if (namespace && *namespace) { + char* parent_namespace = strdupa(namespace); + pakfire_parser_strip_namespace(&parent_namespace); + + repl = pakfire_parser_get_raw(parser, parent_namespace, (const char*)variable); + + // If we have already reached the top namespace, we replace with an empty string + } else { + repl = NULL; + } + } + // What is its value? if (repl) { DEBUG(parser->pakfire, "Replacing %%{%s} with '%s'\n", variable, repl); @@ -521,11 +548,6 @@ static int pakfire_parser_expand_variables(PakfireParser parser, DEBUG(parser->pakfire, "Replacing %%{%s} with an empty string\n", variable); } - // Find the entire matched pattern - r = pcre2_substring_get_bynumber(match, 0, &pattern, &pattern_length); - if (r) - goto ERROR; - // Replace all occurrences char* tmp = pakfire_string_replace(*buffer, (const char*)pattern, (repl) ? repl : ""); if (!tmp) diff --git a/src/libpakfire/parser/grammar.y b/src/libpakfire/parser/grammar.y index 83ca76c59..b94b11b0d 100644 --- a/src/libpakfire/parser/grammar.y +++ b/src/libpakfire/parser/grammar.y @@ -314,11 +314,7 @@ subparser : subparser_name T_EOL block T_END T_EOL int r = pakfire_string_partition($1, ":", &key, &value); if (r == 0) { if (strcmp("package", key) == 0) { - char* name = pakfire_parser_expand($$, NULL, value); - if (name) { - pakfire_parser_set($$, NULL, "name", name); - free(name); - } + pakfire_parser_set($$, NULL, "name", value); } if (key) diff --git a/src/libpakfire/util.c b/src/libpakfire/util.c index fd29b683b..383359997 100644 --- a/src/libpakfire/util.c +++ b/src/libpakfire/util.c @@ -164,6 +164,10 @@ int pakfire_string_endswith(const char* s, const char* suffix) { return !strcmp(s + strlen(s) - strlen(suffix), suffix); } +int pakfire_string_matches(const char* s, const char* pattern) { + return !!strstr(s, pattern); +} + char* pakfire_unquote_in_place(char* s) { if (!s || !*s) return s;