1 /* 2 * variable.c 3 * variable management 4 * 5 * SPDX-License-Identifier: pkgconf 6 * 7 * Copyright (c) 2026 pkgconf authors (see AUTHORS). 8 * 9 * Permission to use, copy, modify, and/or distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * This software is provided 'as is' and without any warranty, express or 14 * implied. In no event shall the authors be liable for any damages arising 15 * from the use of this software. 16 */ 17 18 #include <libpkgconf/libpkgconf.h> 19 #include <libpkgconf/stdinc.h> 20 21 /* 22 * !doc 23 * 24 * libpkgconf `variable` module 25 * ============================ 26 * 27 * The libpkgconf `variable` module contains the functions related to 28 * managing variables. It replaces the old `tuple` module. 29 */ 30 31 pkgconf_variable_t * 32 pkgconf_variable_new(const char *key) 33 { 34 pkgconf_variable_t *v; 35 36 if (key == NULL) 37 return NULL; 38 39 v = calloc(1, sizeof(*v)); 40 if (v == NULL) 41 return NULL; 42 43 v->key = strdup(key); 44 if (v->key == NULL) 45 { 46 free(v); 47 return NULL; 48 } 49 50 return v; 51 } 52 53 void 54 pkgconf_variable_free(pkgconf_variable_t *v) 55 { 56 if (v == NULL) 57 return; 58 59 pkgconf_buffer_finalize(&v->bcbuf); 60 free(v->key); 61 free(v); 62 } 63 64 pkgconf_variable_t * 65 pkgconf_variable_find(const pkgconf_list_t *vars, const char *key) 66 { 67 const pkgconf_node_t *n; 68 69 if (vars == NULL || key == NULL) 70 return NULL; 71 72 PKGCONF_FOREACH_LIST_ENTRY(vars->head, n) 73 { 74 pkgconf_variable_t *v = n->data; 75 76 if (!strcmp(v->key, key)) 77 return v; 78 } 79 80 return NULL; 81 } 82 83 pkgconf_variable_t * 84 pkgconf_variable_get_or_create(pkgconf_list_t *vars, const char *key) 85 { 86 pkgconf_variable_t *v; 87 88 if (vars == NULL || key == NULL) 89 return NULL; 90 91 v = pkgconf_variable_find(vars, key); 92 if (v != NULL) 93 return v; 94 95 v = pkgconf_variable_new(key); 96 if (v == NULL) 97 return NULL; 98 99 pkgconf_node_insert_tail(&v->iter, v, vars); 100 101 return v; 102 } 103 104 void 105 pkgconf_variable_delete(pkgconf_list_t *vars, pkgconf_variable_t *v) 106 { 107 if (vars == NULL || v == NULL) 108 return; 109 110 pkgconf_node_delete(&v->iter, vars); 111 pkgconf_variable_free(v); 112 } 113 114 void 115 pkgconf_variable_list_free(pkgconf_list_t *vars) 116 { 117 pkgconf_node_t *node, *tmp; 118 119 if (vars == NULL) 120 return; 121 122 PKGCONF_FOREACH_LIST_ENTRY_SAFE(vars->head, tmp, node) 123 { 124 pkgconf_variable_t *v = node->data; 125 126 pkgconf_node_delete(node, vars); 127 pkgconf_variable_free(v); 128 } 129 } 130 131 bool 132 pkgconf_variable_eval(pkgconf_client_t *client, 133 const pkgconf_list_t *tuples, 134 const pkgconf_variable_t *v, 135 pkgconf_buffer_t *out, 136 bool *saw_sysroot) 137 { 138 if (client == NULL || tuples == NULL || v == NULL || out == NULL) 139 return false; 140 141 return pkgconf_bytecode_eval(client, tuples, &v->bc, out, saw_sysroot); 142 } 143 144 char * 145 pkgconf_variable_eval_str(pkgconf_client_t *client, 146 const pkgconf_list_t *tuples, 147 const pkgconf_variable_t *v, 148 bool *saw_sysroot) 149 { 150 pkgconf_buffer_t out = PKGCONF_BUFFER_INITIALIZER; 151 152 if (client == NULL || tuples == NULL || v == NULL) 153 return NULL; 154 155 if (!pkgconf_variable_eval(client, tuples, v, &out, saw_sysroot)) 156 { 157 pkgconf_buffer_finalize(&out); 158 return NULL; 159 } 160 161 return pkgconf_buffer_freeze(&out); 162 } 163