xref: /freebsd/contrib/pkgconf/libpkgconf/variable.c (revision 592efe252472a3385acf36b1f49ecf710a7f3d9c)
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