Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */ 2 : : 3 : : #include <errno.h> 4 : : #include <stddef.h> 5 : : #include <stdlib.h> 6 : : #include <string.h> 7 : : 8 : : #include "alloc-util.h" 9 : : #include "macro.h" 10 : : #include "replace-var.h" 11 : : #include "string-util.h" 12 : : 13 : : /* 14 : : * Generic infrastructure for replacing @FOO@ style variables in 15 : : * strings. Will call a callback for each replacement. 16 : : */ 17 : : 18 : 168 : static int get_variable(const char *b, char **r) { 19 : : size_t k; 20 : : char *t; 21 : : 22 [ - + ]: 168 : assert(b); 23 [ - + ]: 168 : assert(r); 24 : : 25 [ + + ]: 168 : if (*b != '@') 26 : 120 : return 0; 27 : : 28 : 48 : k = strspn(b + 1, UPPERCASE_LETTERS "_"); 29 [ + + - + ]: 48 : if (k <= 0 || b[k+1] != '@') 30 : 40 : return 0; 31 : : 32 : 8 : t = strndup(b + 1, k); 33 [ - + ]: 8 : if (!t) 34 : 0 : return -ENOMEM; 35 : : 36 : 8 : *r = t; 37 : 8 : return 1; 38 : : } 39 : : 40 : 4 : char *replace_var(const char *text, char *(*lookup)(const char *variable, void *userdata), void *userdata) { 41 : : char *r, *t; 42 : : const char *f; 43 : : size_t l; 44 : : 45 [ - + ]: 4 : assert(text); 46 [ - + ]: 4 : assert(lookup); 47 : : 48 : 4 : l = strlen(text); 49 : 4 : r = new(char, l+1); 50 [ - + ]: 4 : if (!r) 51 : 0 : return NULL; 52 : : 53 : 4 : f = text; 54 : 4 : t = r; 55 [ + + ]: 172 : while (*f) { 56 [ + - + + : 328 : _cleanup_free_ char *v = NULL, *n = NULL; - + ] 57 : : char *a; 58 : : int k; 59 : : size_t skip, d, nl; 60 : : 61 : 168 : k = get_variable(f, &v); 62 [ - + ]: 168 : if (k < 0) 63 : 0 : goto oom; 64 [ + + ]: 168 : if (k == 0) { 65 : 160 : *(t++) = *(f++); 66 : 160 : continue; 67 : : } 68 : : 69 : 8 : n = lookup(v, userdata); 70 [ - + ]: 8 : if (!n) 71 : 0 : goto oom; 72 : : 73 : 8 : skip = strlen(v) + 2; 74 : : 75 : 8 : d = t - r; 76 : 8 : nl = l - skip + strlen(n); 77 : 8 : a = realloc(r, nl + 1); 78 [ - + ]: 8 : if (!a) 79 : 0 : goto oom; 80 : : 81 : 8 : l = nl; 82 : 8 : r = a; 83 : 8 : t = r + d; 84 : : 85 : 8 : t = stpcpy(t, n); 86 : 8 : f += skip; 87 : : } 88 : : 89 : 4 : *t = 0; 90 : 4 : return r; 91 : : 92 : 0 : oom: 93 : 0 : return mfree(r); 94 : : }