@@@ work in progress
[runlisp] / lib.h
CommitLineData
7b8ff279
MW
1/* -*-c-*-
2 *
3 * Common definitions for `runlisp'
4 *
5 * (c) 2020 Mark Wooding
6 */
7
8/*----- Licensing notice --------------------------------------------------*
9 *
10 * This file is part of Runlisp, a tool for invoking Common Lisp scripts.
11 *
12 * Runlisp is free software: you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 3 of the License, or (at your
15 * option) any later version.
16 *
17 * Runlisp is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with Runlisp. If not, see <https://www.gnu.org/licenses/>.
24 */
25
26#ifndef LIB_H
27#define LIB_H
28
29#ifdef __cplusplus
30 extern "C" {
31#endif
32
33/*----- Header files ------------------------------------------------------*/
34
35#include <limits.h>
36#include <stdarg.h>
37#include <stddef.h>
38#include <stdio.h>
39
40/*----- Handy macros ------------------------------------------------------*/
41
42#define N(v) (sizeof(v)/sizeof((v)[0]))
43
44#if defined(__GNUC__)
45# define GCC_VERSION_P(maj, min) \
46 (__GNUC__ > (maj) || (__GNUC__ == (maj) && __GNUC_MINOR__ >= (min)))
47#else
48# define GCC_VERSION_P(maj, min) 0
49#endif
50
51#ifdef __clang__
52# define CLANG_VERSION_P(maj, min) \
53 (__clang_major__ > (maj) || (__clang_major__ == (maj) && \
54 __clang_minor__ >= (min)))
55#else
56# define CLANG_VERSION_P(maj, min) 0
57#endif
58
59#if GCC_VERSION_P(2, 5) || CLANG_VERSION_P(3, 3)
60# define NORETURN __attribute__((__noreturn__))
61# define PRINTF_LIKE(fix, aix) __attribute__((__format__(printf, fix, aix)))
62#endif
63
64#if GCC_VERSION_P(4, 0) || CLANG_VERSION_P(3, 3)
65# define EXECL_LIKE(ntrail) __attribute__((__sentinel__(ntrail)))
66#endif
67
68#define CTYPE_HACK(func, ch) (func((unsigned char)(ch)))
69#define ISSPACE(ch) CTYPE_HACK(isspace, ch)
70#define ISALNUM(ch) CTYPE_HACK(isalnum, ch)
71
72#define MEMCMP(x, op, y, n) (memcmp((x), (y), (n)) op 0)
73#define STRCMP(x, op, y) (strcmp((x), (y)) op 0)
74#define STRNCMP(x, op, y, n) (strncmp((x), (y), (n)) op 0)
75
76#define DISCARD(x) do if (x); while (0)
77
78#define END ((const char *)0)
79
80#ifndef SIZE_MAX
81# define SIZE_MAX (-(size_t)1)
82#endif
83
84/*----- Miscellany --------------------------------------------------------*/
85
86extern int str_lt(const char */*a*/, size_t /*an*/,
87 const char */*b*/, size_t /*bn*/);
88
89/*----- Diagnostic utilities ----------------------------------------------*/
90
91extern const char *progname;
92
93extern void set_progname(const char */*prog*/);
94extern void vmoan(const char */*msg*/, va_list /*ap*/);
95extern PRINTF_LIKE(1, 2) void moan(const char */*msg*/, ...);
96extern NORETURN PRINTF_LIKE(1, 2) void lose(const char */*msg*/, ...);
97
98/*----- Memory allocation -------------------------------------------------*/
99
100extern void *xmalloc(size_t /*n*/);
101extern void *xrealloc(void */*p*/, size_t /*n*/);
102extern char *xstrndup(const char */*p*/, size_t /*n*/);
103extern char *xstrdup(const char */*p*/);
104
105/*----- Dynamic strings ---------------------------------------------------*/
106
107struct dstr {
108 char *p;
109 size_t len, sz;
110};
111#define DSTR_INIT { 0, 0, 0 }
112
113extern void dstr_init(struct dstr */*d*/);
114extern void dstr_reset(struct dstr */*d*/);
115extern void dstr_ensure(struct dstr */*d*/, size_t /*n*/);
116extern void dstr_release(struct dstr */*d*/);
117extern void dstr_putm(struct dstr */*d*/, const void */*p*/, size_t /*n*/);
118extern void dstr_puts(struct dstr */*d*/, const char */*p*/);
119extern void dstr_putc(struct dstr */*d*/, int /*ch*/);
120extern void dstr_putz(struct dstr */*d*/);
121extern void dstr_vputf(struct dstr */*d*/,
122 const char */*p*/, va_list /*ap*/);
123extern PRINTF_LIKE(2, 3)
124 void dstr_putf(struct dstr */*d*/, const char */*p*/, ...);
125extern int dstr_readline(struct dstr */*d*/, FILE */*fp*/);
126
127/*----- Dynamic vectors of strings ----------------------------------------*/
128
129struct argv {
130 const char **v;
131 size_t o, n, sz;
132};
133#define ARGV_INIT { 0, 0, 0, 0 }
134
135extern void argv_init(struct argv */*a*/v);
136extern void argv_reset(struct argv */*av*/);
137extern void argv_ensure(struct argv */*av*/, size_t /*n*/);
138extern void argv_ensure_offset(struct argv */*av*/, size_t /*n*/);
139extern void argv_release(struct argv */*av*/);
140extern void argv_append(struct argv */*av*/, const char */*p*/);
141extern void argv_appendz(struct argv */*av*/);
142extern void argv_appendn(struct argv */*av*/,
143 const char *const */*v*/, size_t /*n*/);
144extern void argv_appendav(struct argv */*av*/, const struct argv */*bv*/);
145extern void argv_appendv(struct argv */*av*/, va_list /*ap*/);
146extern EXECL_LIKE(0) void argv_appendl(struct argv */*av*/, ...);
147extern void argv_prepend(struct argv */*av*/, const char */*p*/);
148extern void argv_prependn(struct argv */*av*/,
149 const char *const */*v*/, size_t /*n*/);
150extern void argv_prependav(struct argv */*av*/, const struct argv */*bv*/);
151extern void argv_prependv(struct argv */*av*/, va_list /*ap*/);
152extern EXECL_LIKE(0) void argv_prependl(struct argv */*av*/, ...);
153
154/*----- Treaps ------------------------------------------------------------*/
155
156struct treap {
157 struct treap_node *root;
158};
159#define TREAP_INIT { 0 }
160
161struct treap_node {
162 unsigned wt;
163 struct treap_node *left, *right;
164 char *k; size_t kn;
165};
166#define TREAP_NODE_KEY(n) (((const struct treap_node *)(n))->k + 0)
167#define TREAP_NODE_KEYLEN(n) (((const struct treap_node *)(n))->kn + 0)
168
169#define TREAP_PATHMAX 64
170struct treap_path {
171 struct treap_node **path[TREAP_PATHMAX];
172 unsigned nsteps;
173};
174
175struct treap_iter {
176 struct treap_node *stack[TREAP_PATHMAX];
177 unsigned sp;
178};
179
180extern void treap_init(struct treap */*t*/);
181extern void *treap_lookup(const struct treap */*t*/,
182 const char */*k*/, size_t /*kn*/);
183extern void *treap_probe(struct treap */*t*/,
184 const char */*k*/, size_t /*kn*/,
185 struct treap_path */*p*/);
186extern void treap_insert(struct treap */*t*/, const struct treap_path */*p*/,
187 struct treap_node */*n*/,
188 const char */*k*/, size_t /*kn*/);
189extern void *treap_remove(struct treap */*t*/,
190 const char */*k*/, size_t /*kn*/);
191extern void treap_start_iter(struct treap */*t*/, struct treap_iter */*i*/);
192extern void *treap_next(struct treap_iter */*i*/);
193extern void treap_check(struct treap */*t*/);
194extern void treap_dump(struct treap */*t*/);
195
196/*----- Configuration file parsing ----------------------------------------*/
197
198struct config {
199 struct treap sections;
200 struct config_section *head, **tail;
201 struct config_section *fallback;
202};
203#define CONFIG_INIT { TREAP_INIT, 0, 0 }
204
205struct config_section {
206 struct treap_node _node;
207 struct config_section *next;
208 struct config_section **parents; size_t nparents;
209 struct treap vars;
210 struct treap cache;
211};
212#define CONFIG_SECTION_NAME(sect) TREAP_NODE_KEY(sect)
213#define CONFIG_SECTION_NAMELEN(sect) TREAP_NODE_KEYLEN(sect)
214
215struct config_cache_entry {
216 struct treap_node _node;
217 unsigned f;
218#define CF_OPEN 1u
219 struct config_var *var;
220};
221
222struct config_var {
223 struct treap_node _node;
224 char *file; unsigned line;
225 char *val; size_t n;
226 unsigned f;
227};
228#define CONFIG_VAR_NAME(var) TREAP_NODE_KEY(var)
229#define CONFIG_VAR_NAMELEN(var) TREAP_NODE_KEYLEN(var)
230#define CF_LITERAL 1u
231#define CF_EXPAND 2u
232#define CF_OVERRIDE 4u
233
234struct config_section_iter {
235 struct config_section *sect;
236};
237
238struct config_var_iter {
239 struct treap_iter i;
240};
241
242extern void config_init(struct config */*conf*/);
243
244extern struct config_section *config_find_section(struct config */*conf*/,
245 unsigned /*f*/,
246 const char */*name*/);
247extern struct config_section *config_find_section_n(struct config */*conf*/,
248 unsigned /*f*/,
249 const char */*name*/,
250 size_t /*sz*/);
251#define CF_CREAT 1u
252
253extern void config_set_fallback(struct config */*conf*/,
254 struct config_section */*sect*/);
255extern void config_set_parent(struct config_section */*sect*/,
256 struct config_section */*parent*/);
257
258extern void config_start_section_iter(struct config */*conf*/,
259 struct config_section_iter */*i*/);
260extern struct config_section *config_next_section
261 (struct config_section_iter */*i*/);
262
263extern struct config_var *config_find_var(struct config */*conf*/,
264 struct config_section */*sect*/,
265 unsigned /*f*/,
266 const char */*name*/);
267extern struct config_var *config_find_var_n(struct config */*conf*/,
268 struct config_section */*sect*/,
269 unsigned /*f*/,
270 const char */*name*/,
271 size_t /*sz*/);
272#define CF_INHERIT 2u
273
274extern void config_set_var(struct config */*conf*/,
275 struct config_section */*sect*/, unsigned /*f*/,
276 const char */*name*/, const char */*value*/);
277extern void config_set_var_n(struct config */*conf*/,
278 struct config_section */*sect*/, unsigned /*f*/,
279 const char */*name*/, size_t /*namelen*/,
280 const char */*value*/, size_t /*valuelen*/);
281extern void config_start_var_iter(struct config_section */*sect*/,
282 struct config_var_iter */*i*/);
283extern struct config_var *config_next_var(struct config_var_iter */*i*/);
284
285extern int config_read_file(struct config */*conf*/, const char */*file*/,
286 unsigned /*f*/);
287extern int config_read_dir(struct config */*conf*/,
288 const char */*dir*/, unsigned /*f*/);
289extern void config_read_env(struct config */*conf*/,
290 struct config_section */*sect*/);
291#define CF_NOENTOK 1u
292
293extern void config_subst_string(struct config */*config*/,
294 struct config_section */*home*/,
295 const char */*what*/,
296 const char */*p*/, struct dstr */*d*/);
297extern char *config_subst_string_alloc(struct config */*config*/,
298 struct config_section */*home*/,
299 const char */*what*/,
300 const char */*p*/);
301extern void config_subst_var(struct config */*config*/,
302 struct config_section */*home*/,
303 struct config_var */*var*/,
304 struct dstr */*d*/);
305extern char *config_subst_var_alloc(struct config */*config*/,
306 struct config_section */*home*/,
307 struct config_var */*var*/);
308extern void config_subst_split_var(struct config */*config*/,
309 struct config_section */*home*/,
310 struct config_var */*var*/,
311 struct argv */*av*/);
312
313/*----- That's all, folks -------------------------------------------------*/
314
315#ifdef __cplusplus
316 }
317#endif
318
319#endif