2
#include "libxlu_internal.h"
3
#include "libxlu_cfg_y.h"
4
#include "libxlu_cfg_l.h"
5
#include "libxlu_cfg_i.h"
7
XLU_Config *xlu_cfg_init(FILE *report, const char *report_filename) {
10
cfg= malloc(sizeof(*cfg));
14
cfg->filename= strdup(report_filename);
15
if (!cfg->filename) { free(cfg); return 0; }
21
int xlu_cfg_readfile(XLU_Config *cfg, const char *real_filename) {
30
f= fopen(real_filename, "r");
33
fprintf(cfg->report,"%s: unable to open configuration file: %s\n",
34
real_filename, strerror(e));
38
e= xlu__cfg_yylex_init_extra(&ctx, &ctx.scanner);
40
fprintf(cfg->report,"%s: unable to create scanner: %s\n",
41
cfg->filename, strerror(e));
45
xlu__cfg_yyrestart(f, ctx.scanner);
47
r= xlu__cfg_yyparse(&ctx);
48
if (r) assert(ctx.err);
50
xlu__cfg_yylex_destroy(ctx.scanner);
56
void xlu__cfg_set_free(XLU_ConfigSetting *set) {
62
void xlu_cfg_destroy(XLU_Config *cfg) {
63
XLU_ConfigSetting *set, *set_next;
65
for (set= cfg->settings;
69
xlu__cfg_set_free(set);
75
static XLU_ConfigSetting *find(const XLU_Config *cfg, const char *n) {
76
XLU_ConfigSetting *set;
78
for (set= cfg->settings;
81
if (!strcmp(set->name, n))
86
static int find_atom(const XLU_Config *cfg, const char *n,
87
XLU_ConfigSetting **set_r) {
88
XLU_ConfigSetting *set;
91
if (!set) return ESRCH;
93
if (set->avalues!=1) {
95
"%s:%d: warning: parameter `%s' is"
96
" a list but should be a single value\n",
97
cfg->filename, set->lineno, n);
104
int xlu_cfg_get_string(const XLU_Config *cfg, const char *n,
105
const char **value_r) {
106
XLU_ConfigSetting *set;
109
e= find_atom(cfg,n,&set); if (e) return e;
110
*value_r= set->values[0];
114
int xlu_cfg_get_long(const XLU_Config *cfg, const char *n,
117
XLU_ConfigSetting *set;
121
e= find_atom(cfg,n,&set); if (e) return e;
122
errno= 0; l= strtol(set->values[0], &ep, 0);
126
assert(e==EINVAL || e==ERANGE);
128
"%s:%d: warning: parameter `%s' could not be parsed"
129
" as a number: %s\n",
130
cfg->filename, set->lineno, n, strerror(e));
133
if (*ep || ep==set->values[0]) {
135
"%s:%d: warning: parameter `%s' is not a valid number\n",
136
cfg->filename, set->lineno, n);
144
int xlu_cfg_get_list(const XLU_Config *cfg, const char *n,
145
XLU_ConfigList **list_r, int *entries_r) {
146
XLU_ConfigSetting *set;
147
set= find(cfg,n); if (!set) return ESRCH;
148
if (set->avalues==1) {
150
"%s:%d: warning: parameter `%s' is a single value"
151
" but should be a list\n",
152
cfg->filename, set->lineno, n);
155
if (list_r) *list_r= set;
156
if (entries_r) *entries_r= set->nvalues;
160
const char *xlu_cfg_get_listitem(const XLU_ConfigList *set, int entry) {
161
if (entry < 0 || entry >= set->nvalues) return 0;
162
return set->values[entry];
166
XLU_ConfigSetting *xlu__cfg_set_mk(CfgParseContext *ctx,
167
int alloc, char *atom) {
168
XLU_ConfigSetting *set= 0;
170
if (ctx->err) goto x;
171
assert(!!alloc == !!atom);
173
set= malloc(sizeof(*set));
176
set->name= 0; /* tbd */
183
set->values= malloc(sizeof(*set->values) * alloc);
184
if (!set->values) goto xe;
187
set->values[0]= atom;
199
void xlu__cfg_set_add(CfgParseContext *ctx, XLU_ConfigSetting *set,
201
if (ctx->err) return;
205
if (set->nvalues >= set->avalues) {
209
if (set->avalues > INT_MAX / 100) { ctx->err= ERANGE; return; }
210
new_avalues= set->avalues * 4;
211
new_values= realloc(set->values,
212
sizeof(*new_values) * new_avalues);
213
if (!new_values) { ctx->err= errno; free(atom); return; }
214
set->values= new_values;
215
set->avalues= new_avalues;
217
set->values[set->nvalues++]= atom;
220
void xlu__cfg_set_store(CfgParseContext *ctx, char *name,
221
XLU_ConfigSetting *set, int lineno) {
222
if (ctx->err) return;
227
set->next= ctx->cfg->settings;
228
ctx->cfg->settings= set;
231
char *xlu__cfgl_strdup(CfgParseContext *ctx, const char *src) {
234
if (ctx->err) return 0;
236
if (!result) ctx->err= errno;
240
char *xlu__cfgl_dequote(CfgParseContext *ctx, const char *src) {
246
if (ctx->err) return 0;
249
assert(len>=2 && src[0]==src[len-1]);
251
result= malloc(len-1);
252
if (!result) { ctx->err= errno; return 0; }
261
assert(p < src+len-1);
263
if (nc=='"' || nc=='\'' || nc=='\\') {
265
} else if (nc=='a') { *q++= '\007';
266
} else if (nc=='b') { *q++= '\010';
267
} else if (nc=='f') { *q++= '\014';
268
} else if (nc=='n') { *q++= '\n';
269
} else if (nc=='r') { *q++= '\r';
270
} else if (nc=='t') { *q++= '\t';
271
} else if (nc=='v') { *q++= '\013';
272
} else if (nc=='x') {
274
#define NUMERIC_CHAR(minlen,maxlen,base,basetext) do{ \
275
char numbuf[(maxlen)+1], *ep; \
278
strncpy(numbuf,p,(maxlen)); \
279
numbuf[(maxlen)]= 0; \
280
val= strtoul(numbuf, &ep, (base)); \
281
if (ep <= numbuf+(minlen)) { \
282
xlu__cfgl_lexicalerror(ctx,"invalid digit after" \
283
" backslash " basetext "numerical character escape" \
284
" in quoted string"); \
288
p += (ep - numbuf); \
292
NUMERIC_CHAR(2,2,16,"hex");
293
} else if (nc>='0' && nc<='7') {
294
NUMERIC_CHAR(1,3,10,"octal");
296
assert(p <= src+len-1);
307
void xlu__cfgl_lexicalerror(CfgParseContext *ctx, char const *msg) {
309
loc.first_line= xlu__cfg_yyget_lineno(ctx->scanner);
310
xlu__cfg_yyerror(&loc, ctx, msg);
311
ctx->lexerrlineno= loc.first_line;
314
void xlu__cfg_yyerror(YYLTYPE *loc, CfgParseContext *ctx, char const *msg) {
315
const char *text, *newline;
318
lineno= loc->first_line;
319
if (lineno <= ctx->lexerrlineno) return;
321
text= xlu__cfg_yyget_text(ctx->scanner);
322
len= xlu__cfg_yyget_leng(ctx->scanner);
324
if (len>0 && text[len-1]=='\n') {
328
newline= "<newline>";
331
while (len>0 && (text[len-1]=='\t' || text[len-1]==' ')) {
335
fprintf(ctx->cfg->report,
336
"%s:%d: config parsing error near %s%.*s%s%s: %s\n",
337
ctx->cfg->filename, lineno,
338
len?"`":"", len, text, len?"'":"", newline,
340
if (!ctx->err) ctx->err= EINVAL;