return d;
}
+static char* extract_string(const char* buffer, const regmatch_t* match) {
+ // Determine the length of the string
+ size_t l = match->rm_eo - match->rm_so;
+
+ // Allocate sufficient memory
+ char* s = malloc(l + 1);
+ if (!s)
+ return NULL;
+
+ // Copy string
+ snprintf(s, l + 1, "%s", buffer + match->rm_so);
+
+ return s;
+}
+
PAKFIRE_EXPORT char* pakfire_parser_expand(PakfireParser parser,
const char* namespace, const char* value) {
// Return NULL when the value is NULL
// Create a working copy of the string we are expanding
char* buffer = strdup(value);
+ char* variable = NULL;
+ char* pattern = NULL;
const size_t max_groups = 2;
regmatch_t groups[max_groups];
break;
}
- // Set offsets to the matched variable name
- off_t start = groups[1].rm_so, end = groups[1].rm_eo;
-
- // Get the name of the variable
- char* variable = malloc(end - start + 1);
- snprintf(variable, end - start + 1, "%s", buffer + start);
+ // Find the variable name
+ variable = extract_string(buffer, &groups[1]);
+ if (!variable)
+ goto ERROR;
DEBUG(parser->pakfire, "Expanding variable: %s\n", variable);
// Search for a declaration of this variable
- struct pakfire_parser_declaration* v =
+ struct pakfire_parser_declaration* d =
pakfire_parser_find_declaration(parser, namespace, variable);
- const char* value = NULL;
- if (v && v->value) {
- DEBUG(parser->pakfire, "Replacing %%{%s} with %s = '%s'\n",
- variable, v->name, v->value);
+ // What is its value?
+ const char* repl = NULL;
+ if (d && d->value) {
+ DEBUG(parser->pakfire, "Replacing %%{%s} with %s.%s = '%s'\n", variable,
+ d->namespace, d->name, d->value);
- value = v->value;
+ repl = d->value;
} else {
- DEBUG(parser->pakfire, "Replacing %%{%s} with an empty string\n",
- variable);
+ DEBUG(parser->pakfire, "Replacing %%{%s} with an empty string\n", variable);
+
+ repl = "";
}
- // Reset offsets to the whole matched string
- start = groups[0].rm_so; end = groups[0].rm_eo;
+ // Find the entire matched pattern
+ pattern = extract_string(buffer, &groups[0]);
+ if (!pattern)
+ goto ERROR;
- // Length of the new buffer
- size_t length = strlen(buffer) - (end - start) + ((value) ? strlen(value) : 0);
+ // Replace all occurrences
+ char* tmp = pakfire_string_replace(buffer, pattern, repl);
+ if (!tmp)
+ goto ERROR;
- char* b = malloc(length + 1);
+ // Replace buffer
+ free(buffer);
+ buffer = tmp;
- // Copy buffer up to the beginning of the match
- snprintf(b, start + 1, "%s", buffer);
+ // Free resources
+ free(variable);
+ free(pattern);
+ variable = pattern = NULL;
- // Append the new value (if any)
- if (value)
- strcat(b, value);
-
- // Append the rest of the buffer
- if (buffer + end)
- strcat(b, buffer + end);
+ DEBUG(parser->pakfire, "New buffer: %s\n", buffer);
+ }
- DEBUG(parser->pakfire, "New buffer: %s\n", b);
+ goto OUT;
- // Drop old buffer
+ERROR:
+ if (buffer) {
free(buffer);
- buffer = b;
+ buffer = NULL;
}
+OUT:
regfree(&preg);
+ if (variable)
+ free(variable);
+ if (pattern)
+ free(pattern);
+
return buffer;
}