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 *
pkgconf_variable_new(const char * key)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
pkgconf_variable_free(pkgconf_variable_t * v)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 *
pkgconf_variable_find(const pkgconf_list_t * vars,const char * key)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 *
pkgconf_variable_get_or_create(pkgconf_list_t * vars,const char * key)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
pkgconf_variable_delete(pkgconf_list_t * vars,pkgconf_variable_t * v)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
pkgconf_variable_list_free(pkgconf_list_t * vars)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
pkgconf_variable_eval(pkgconf_client_t * client,const pkgconf_list_t * tuples,const pkgconf_variable_t * v,pkgconf_buffer_t * out,bool * saw_sysroot)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 *
pkgconf_variable_eval_str(pkgconf_client_t * client,const pkgconf_list_t * tuples,const pkgconf_variable_t * v,bool * saw_sysroot)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