2209c3038ffd5c0111077cb870777b127a8febea
3 * Common definitions for `runlisp'
5 * (c) 2020 Mark Wooding
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Runlisp, a tool for invoking Common Lisp scripts.
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.
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
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/>.
33 /*----- Header files ------------------------------------------------------*/
40 /*----- Handy macros ------------------------------------------------------*/
42 #define N(v) (sizeof(v)/sizeof((v)[0]))
45 # define GCC_VERSION_P(maj, min) \
46 (__GNUC__ > (maj) || (__GNUC__ == (maj) && __GNUC_MINOR__ >= (min)))
48 # define GCC_VERSION_P(maj, min) 0
52 # define CLANG_VERSION_P(maj, min) \
53 (__clang_major__ > (maj) || (__clang_major__ == (maj) && \
54 __clang_minor__ >= (min)))
56 # define CLANG_VERSION_P(maj, min) 0
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)))
64 #if GCC_VERSION_P(4, 0) || CLANG_VERSION_P(3, 3)
65 # define EXECL_LIKE(ntrail) __attribute__((__sentinel__(ntrail)))
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)
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)
76 #define DISCARD(x) do if (x); while (0)
78 #define END ((const char *)0)
81 # define SIZE_MAX (-(size_t)1)
84 /*----- Miscellany --------------------------------------------------------*/
86 extern int str_lt(const char */
*a*/
, size_t /*an*/,
87 const char */
*b*/
, size_t /*bn*/);
89 /*----- Diagnostic utilities ----------------------------------------------*/
91 extern const char *progname
;
93 extern void set_progname(const char */
*prog*/
);
94 extern void vmoan(const char */
*msg*/
, va_list /*ap*/);
95 extern PRINTF_LIKE(1, 2) void moan(const char */
*msg*/
, ...);
96 extern NORETURN
PRINTF_LIKE(1, 2) void lose(const char */
*msg*/
, ...);
98 /*----- Memory allocation -------------------------------------------------*/
100 extern void *xmalloc(size_t /*n*/);
101 extern void *xrealloc(void */
*p*/
, size_t /*n*/);
102 extern char *xstrndup(const char */
*p*/
, size_t /*n*/);
103 extern char *xstrdup(const char */
*p*/
);
105 /*----- Dynamic strings ---------------------------------------------------*/
111 #define DSTR_INIT { 0, 0, 0 }
113 extern void dstr_init(struct dstr */
*d*/
);
114 extern void dstr_reset(struct dstr */
*d*/
);
115 extern void dstr_ensure(struct dstr */
*d*/
, size_t /*n*/);
116 extern void dstr_release(struct dstr */
*d*/
);
117 extern void dstr_putm(struct dstr */
*d*/
, const void */
*p*/
, size_t /*n*/);
118 extern void dstr_puts(struct dstr */
*d*/
, const char */
*p*/
);
119 extern void dstr_putc(struct dstr */
*d*/
, int /*ch*/);
120 extern void dstr_putz(struct dstr */
*d*/
);
121 extern void dstr_vputf(struct dstr */
*d*/
,
122 const char */
*p*/
, va_list /*ap*/);
123 extern PRINTF_LIKE(2, 3)
124 void dstr_putf(struct dstr */
*d*/
, const char */
*p*/
, ...);
125 extern int dstr_readline(struct dstr */
*d*/
, FILE */
*fp*/
);
127 /*----- Dynamic vectors of strings ----------------------------------------*/
133 #define ARGV_INIT { 0, 0, 0, 0 }
135 extern void argv_init(struct argv */
*a*/v
);
136 extern void argv_reset(struct argv */
*av*/
);
137 extern void argv_ensure(struct argv */
*av*/
, size_t /*n*/);
138 extern void argv_ensure_offset(struct argv */
*av*/
, size_t /*n*/);
139 extern void argv_release(struct argv */
*av*/
);
140 extern void argv_append(struct argv */
*av*/
, const char */
*p*/
);
141 extern void argv_appendz(struct argv */
*av*/
);
142 extern void argv_appendn(struct argv */
*av*/
,
143 const char *const */
*v*/
, size_t /*n*/);
144 extern void argv_appendav(struct argv */
*av*/
, const struct argv */
*bv*/
);
145 extern void argv_appendv(struct argv */
*av*/
, va_list /*ap*/);
146 extern EXECL_LIKE(0) void argv_appendl(struct argv */
*av*/
, ...);
147 extern void argv_prepend(struct argv */
*av*/
, const char */
*p*/
);
148 extern void argv_prependn(struct argv */
*av*/
,
149 const char *const */
*v*/
, size_t /*n*/);
150 extern void argv_prependav(struct argv */
*av*/
, const struct argv */
*bv*/
);
151 extern void argv_prependv(struct argv */
*av*/
, va_list /*ap*/);
152 extern EXECL_LIKE(0) void argv_prependl(struct argv */
*av*/
, ...);
154 /*----- Treaps ------------------------------------------------------------*/
157 struct treap_node
*root
;
159 #define TREAP_INIT { 0 }
163 struct treap_node
*left
, *right
;
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)
169 #define TREAP_PATHMAX 64
171 struct treap_node
**path
[TREAP_PATHMAX
];
176 struct treap_node
*stack
[TREAP_PATHMAX
];
180 extern void treap_init(struct treap */
*t*/
);
181 extern void *treap_lookup(const struct treap */
*t*/
,
182 const char */
*k*/
, size_t /*kn*/);
183 extern void *treap_probe(struct treap */
*t*/
,
184 const char */
*k*/
, size_t /*kn*/,
185 struct treap_path */
*p*/
);
186 extern void treap_insert(struct treap */
*t*/
, const struct treap_path */
*p*/
,
187 struct treap_node */
*n*/
,
188 const char */
*k*/
, size_t /*kn*/);
189 extern void *treap_remove(struct treap */
*t*/
,
190 const char */
*k*/
, size_t /*kn*/);
191 extern void treap_start_iter(struct treap */
*t*/
, struct treap_iter */
*i*/
);
192 extern void *treap_next(struct treap_iter */
*i*/
);
193 extern void treap_check(struct treap */
*t*/
);
194 extern void treap_dump(struct treap */
*t*/
);
196 /*----- Configuration file parsing ----------------------------------------*/
199 struct treap sections
;
200 struct config_section
*head
, **tail
;
201 struct config_section
*fallback
;
203 #define CONFIG_INIT { TREAP_INIT, 0, 0 }
205 struct config_section
{
206 struct treap_node _node
;
207 struct config_section
*next
;
208 struct config_section
**parents
; size_t nparents
;
212 #define CONFIG_SECTION_NAME(sect) TREAP_NODE_KEY(sect)
213 #define CONFIG_SECTION_NAMELEN(sect) TREAP_NODE_KEYLEN(sect)
215 struct config_cache_entry
{
216 struct treap_node _node
;
219 struct config_var
*var
;
223 struct treap_node _node
;
224 char *file
; unsigned line
;
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
232 #define CF_OVERRIDE 4u
234 struct config_section_iter
{
235 struct config_section
*sect
;
238 struct config_var_iter
{
242 extern void config_init(struct config */
*conf*/
);
244 extern struct config_section
*config_find_section(struct config */
*conf*/
,
246 const char */
*name*/
);
247 extern struct config_section
*config_find_section_n(struct config */
*conf*/
,
249 const char */
*name*/
,
253 extern void config_set_fallback(struct config */
*conf*/
,
254 struct config_section */
*sect*/
);
255 extern void config_set_parent(struct config_section */
*sect*/
,
256 struct config_section */
*parent*/
);
258 extern void config_start_section_iter(struct config */
*conf*/
,
259 struct config_section_iter */
*i*/
);
260 extern struct config_section
*config_next_section
261 (struct config_section_iter */
*i*/
);
263 extern struct config_var
*config_find_var(struct config */
*conf*/
,
264 struct config_section */
*sect*/
,
266 const char */
*name*/
);
267 extern struct config_var
*config_find_var_n(struct config */
*conf*/
,
268 struct config_section */
*sect*/
,
270 const char */
*name*/
,
272 #define CF_INHERIT 2u
274 extern void config_set_var(struct config */
*conf*/
,
275 struct config_section */
*sect*/
, unsigned /*f*/,
276 const char */
*name*/
, const char */
*value*/
);
277 extern 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*/);
281 extern void config_start_var_iter(struct config_section */
*sect*/
,
282 struct config_var_iter */
*i*/
);
283 extern struct config_var
*config_next_var(struct config_var_iter */
*i*/
);
285 extern int config_read_file(struct config */
*conf*/
, const char */
*file*/
,
287 extern int config_read_dir(struct config */
*conf*/
,
288 const char */
*dir*/
, unsigned /*f*/);
289 extern void config_read_env(struct config */
*conf*/
,
290 struct config_section */
*sect*/
);
291 #define CF_NOENTOK 1u
293 extern void config_subst_string(struct config */
*config*/
,
294 struct config_section */
*home*/
,
295 const char */
*what*/
,
296 const char */
*p*/
, struct dstr */
*d*/
);
297 extern char *config_subst_string_alloc(struct config */
*config*/
,
298 struct config_section */
*home*/
,
299 const char */
*what*/
,
301 extern void config_subst_var(struct config */
*config*/
,
302 struct config_section */
*home*/
,
303 struct config_var */
*var*/
,
305 extern char *config_subst_var_alloc(struct config */
*config*/
,
306 struct config_section */
*home*/
,
307 struct config_var */
*var*/
);
308 extern void config_subst_split_var(struct config */
*config*/
,
309 struct config_section */
*home*/
,
310 struct config_var */
*var*/
,
311 struct argv */
*av*/
);
313 /*----- That's all, folks -------------------------------------------------*/