debuggers.hg

view tools/libxl/libxlu_cfg.c @ 22848:6341fe0f4e5a

Added tag 4.1.0-rc2 for changeset 9dca60d88c63
author Keir Fraser <keir@xen.org>
date Tue Jan 25 14:06:55 2011 +0000 (2011-01-25)
parents cb94dbe20f97
children
line source
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) {
8 XLU_Config *cfg;
10 cfg= malloc(sizeof(*cfg));
11 if (!cfg) return 0;
13 cfg->report= report;
14 cfg->filename= strdup(report_filename);
15 if (!cfg->filename) { free(cfg); return 0; }
17 cfg->settings= 0;
18 return cfg;
19 }
21 static int ctx_prep(CfgParseContext *ctx, XLU_Config *cfg) {
22 int e;
24 ctx->cfg= cfg;
25 ctx->err= 0;
26 ctx->lexerrlineno= -1;
27 ctx->likely_python= 0;
28 ctx->scanner= 0;
30 e= xlu__cfg_yylex_init_extra(ctx, &ctx->scanner);
31 if (e) {
32 fprintf(cfg->report,"%s: unable to create scanner: %s\n",
33 cfg->filename, strerror(e));
34 return e;
35 }
36 return 0;
37 }
39 static void ctx_dispose(CfgParseContext *ctx) {
40 if (ctx->scanner) xlu__cfg_yylex_destroy(ctx->scanner);
41 }
43 static void parse(CfgParseContext *ctx) {
44 /* On return, ctx.err will be updated with the error status. */
45 int r;
46 r= xlu__cfg_yyparse(ctx);
47 if (r) assert(ctx->err);
49 if (ctx->err && ctx->likely_python) {
50 fputs(
51 "warning: Config file looks like it contains Python code.\n"
52 "warning: Arbitrary Python is no longer supported.\n"
53 "warning: See http://wiki.xen.org/xenwiki/PythonInXlConfig\n",
54 ctx->cfg->report);
55 }
56 }
58 int xlu_cfg_readfile(XLU_Config *cfg, const char *real_filename) {
59 FILE *f = 0;
60 int e;
62 CfgParseContext ctx;
63 e = ctx_prep(&ctx, cfg);
64 if (e) { ctx.err= e; goto xe; }
66 f= fopen(real_filename, "r");
67 if (!f) {
68 ctx.err = errno;
69 fprintf(cfg->report,"%s: unable to open configuration file: %s\n",
70 real_filename, strerror(e));
71 goto xe;
72 }
74 xlu__cfg_yyrestart(f, ctx.scanner);
76 parse(&ctx);
78 xe:
79 ctx_dispose(&ctx);
80 if (f) fclose(f);
82 return ctx.err;
83 }
85 int xlu_cfg_readdata(XLU_Config *cfg, const char *data, int length) {
86 int e;
87 YY_BUFFER_STATE buf= 0;
89 CfgParseContext ctx;
90 e= ctx_prep(&ctx, cfg);
91 if (e) { ctx.err= e; goto xe; }
93 buf = xlu__cfg_yy_scan_bytes(data, length, ctx.scanner);
94 if (!buf) {
95 fprintf(cfg->report,"%s: unable to allocate scanner buffer\n",
96 cfg->filename);
97 ctx.err= ENOMEM;
98 goto xe;
99 }
101 parse(&ctx);
103 xe:
104 if (buf) xlu__cfg_yy_delete_buffer(buf, ctx.scanner);
105 ctx_dispose(&ctx);
107 return ctx.err;
108 }
110 void xlu__cfg_set_free(XLU_ConfigSetting *set) {
111 int i;
113 if (!set) return;
114 free(set->name);
115 for (i=0; i<set->nvalues; i++)
116 free(set->values[i]);
117 free(set->values);
118 free(set);
119 }
121 void xlu_cfg_destroy(XLU_Config *cfg) {
122 XLU_ConfigSetting *set, *set_next;
124 for (set= cfg->settings;
125 set;
126 set= set_next) {
127 set_next= set->next;
128 xlu__cfg_set_free(set);
129 }
130 free(cfg->filename);
131 free(cfg);
132 }
134 static XLU_ConfigSetting *find(const XLU_Config *cfg, const char *n) {
135 XLU_ConfigSetting *set;
137 for (set= cfg->settings;
138 set;
139 set= set->next)
140 if (!strcmp(set->name, n))
141 return set;
142 return 0;
143 }
145 static int find_atom(const XLU_Config *cfg, const char *n,
146 XLU_ConfigSetting **set_r) {
147 XLU_ConfigSetting *set;
149 set= find(cfg,n);
150 if (!set) return ESRCH;
152 if (set->avalues!=1) {
153 fprintf(cfg->report,
154 "%s:%d: warning: parameter `%s' is"
155 " a list but should be a single value\n",
156 cfg->filename, set->lineno, n);
157 return EINVAL;
158 }
159 *set_r= set;
160 return 0;
161 }
163 int xlu_cfg_get_string(const XLU_Config *cfg, const char *n,
164 const char **value_r) {
165 XLU_ConfigSetting *set;
166 int e;
168 e= find_atom(cfg,n,&set); if (e) return e;
169 *value_r= set->values[0];
170 return 0;
171 }
173 int xlu_cfg_replace_string(const XLU_Config *cfg, const char *n,
174 char **value_r) {
175 XLU_ConfigSetting *set;
176 int e;
178 e= find_atom(cfg,n,&set); if (e) return e;
179 free(*value_r);
180 *value_r= strdup(set->values[0]);
181 return 0;
182 }
184 int xlu_cfg_get_long(const XLU_Config *cfg, const char *n,
185 long *value_r) {
186 long l;
187 XLU_ConfigSetting *set;
188 int e;
189 char *ep;
191 e= find_atom(cfg,n,&set); if (e) return e;
192 errno= 0; l= strtol(set->values[0], &ep, 0);
193 e= errno;
194 if (errno) {
195 e= errno;
196 assert(e==EINVAL || e==ERANGE);
197 fprintf(cfg->report,
198 "%s:%d: warning: parameter `%s' could not be parsed"
199 " as a number: %s\n",
200 cfg->filename, set->lineno, n, strerror(e));
201 return e;
202 }
203 if (*ep || ep==set->values[0]) {
204 fprintf(cfg->report,
205 "%s:%d: warning: parameter `%s' is not a valid number\n",
206 cfg->filename, set->lineno, n);
207 return EINVAL;
208 }
209 *value_r= l;
210 return 0;
211 }
214 int xlu_cfg_get_list(const XLU_Config *cfg, const char *n,
215 XLU_ConfigList **list_r, int *entries_r, int dont_warn) {
216 XLU_ConfigSetting *set;
217 set= find(cfg,n); if (!set) return ESRCH;
218 if (set->avalues==1) {
219 if (!dont_warn) {
220 fprintf(cfg->report,
221 "%s:%d: warning: parameter `%s' is a single value"
222 " but should be a list\n",
223 cfg->filename, set->lineno, n);
224 }
225 return EINVAL;
226 }
227 if (list_r) *list_r= set;
228 if (entries_r) *entries_r= set->nvalues;
229 return 0;
230 }
232 const char *xlu_cfg_get_listitem(const XLU_ConfigList *set, int entry) {
233 if (entry < 0 || entry >= set->nvalues) return 0;
234 return set->values[entry];
235 }
238 XLU_ConfigSetting *xlu__cfg_set_mk(CfgParseContext *ctx,
239 int alloc, char *atom) {
240 XLU_ConfigSetting *set= 0;
242 if (ctx->err) goto x;
243 assert(!!alloc == !!atom);
245 set= malloc(sizeof(*set));
246 if (!set) goto xe;
248 set->name= 0; /* tbd */
249 set->avalues= alloc;
251 if (!alloc) {
252 set->nvalues= 0;
253 set->values= 0;
254 } else {
255 set->values= malloc(sizeof(*set->values) * alloc);
256 if (!set->values) goto xe;
258 set->nvalues= 1;
259 set->values[0]= atom;
260 }
261 return set;
263 xe:
264 ctx->err= errno;
265 x:
266 free(set);
267 free(atom);
268 return 0;
269 }
271 void xlu__cfg_set_add(CfgParseContext *ctx, XLU_ConfigSetting *set,
272 char *atom) {
273 if (ctx->err) return;
275 assert(atom);
277 if (set->nvalues >= set->avalues) {
278 int new_avalues;
279 char **new_values;
281 if (set->avalues > INT_MAX / 100) { ctx->err= ERANGE; return; }
282 new_avalues= set->avalues * 4;
283 new_values= realloc(set->values,
284 sizeof(*new_values) * new_avalues);
285 if (!new_values) { ctx->err= errno; free(atom); return; }
286 set->values= new_values;
287 set->avalues= new_avalues;
288 }
289 set->values[set->nvalues++]= atom;
290 }
292 void xlu__cfg_set_store(CfgParseContext *ctx, char *name,
293 XLU_ConfigSetting *set, int lineno) {
294 if (ctx->err) return;
296 assert(name);
297 set->name= name;
298 set->lineno= lineno;
299 set->next= ctx->cfg->settings;
300 ctx->cfg->settings= set;
301 }
303 char *xlu__cfgl_strdup(CfgParseContext *ctx, const char *src) {
304 char *result;
306 if (ctx->err) return 0;
307 result= strdup(src);
308 if (!result) ctx->err= errno;
309 return result;
310 }
312 char *xlu__cfgl_dequote(CfgParseContext *ctx, const char *src) {
313 char *result;
314 const char *p;
315 char *q;
316 int len, c, nc;
318 if (ctx->err) return 0;
320 len= strlen(src);
321 assert(len>=2 && src[0]==src[len-1]);
323 result= malloc(len-1);
324 if (!result) { ctx->err= errno; return 0; }
326 q= result;
328 for (p= src+1;
329 p < src+len-1;
330 ) {
331 c= *p++;
332 if (c=='\\') {
333 assert(p < src+len-1);
334 nc= *p++;
335 if (nc=='"' || nc=='\'' || nc=='\\') {
336 *q++= nc;
337 } else if (nc=='a') { *q++= '\007';
338 } else if (nc=='b') { *q++= '\010';
339 } else if (nc=='f') { *q++= '\014';
340 } else if (nc=='n') { *q++= '\n';
341 } else if (nc=='r') { *q++= '\r';
342 } else if (nc=='t') { *q++= '\t';
343 } else if (nc=='v') { *q++= '\013';
344 } else if (nc=='x') {
346 #define NUMERIC_CHAR(minlen,maxlen,base,basetext) do{ \
347 char numbuf[(maxlen)+1], *ep; \
348 unsigned long val; \
349 \
350 strncpy(numbuf,p,(maxlen)); \
351 numbuf[(maxlen)]= 0; \
352 val= strtoul(numbuf, &ep, (base)); \
353 if (ep <= numbuf+(minlen)) { \
354 xlu__cfgl_lexicalerror(ctx,"invalid digit after" \
355 " backslash " basetext "numerical character escape" \
356 " in quoted string"); \
357 ctx->err= EINVAL; \
358 goto x; \
359 } \
360 p += (ep - numbuf); \
361 }while(0)
363 p++;
364 NUMERIC_CHAR(2,2,16,"hex");
365 } else if (nc>='0' && nc<='7') {
366 NUMERIC_CHAR(1,3,10,"octal");
367 }
368 assert(p <= src+len-1);
369 } else {
370 *q++= c;
371 }
372 }
374 x:
375 *q++= 0;
376 return result;
377 }
379 void xlu__cfgl_lexicalerror(CfgParseContext *ctx, char const *msg) {
380 YYLTYPE loc;
381 loc.first_line= xlu__cfg_yyget_lineno(ctx->scanner);
382 xlu__cfg_yyerror(&loc, ctx, msg);
383 ctx->lexerrlineno= loc.first_line;
384 }
386 void xlu__cfg_yyerror(YYLTYPE *loc, CfgParseContext *ctx, char const *msg) {
387 const char *text, *newline;
388 int len, lineno;
390 lineno= loc->first_line;
391 if (lineno <= ctx->lexerrlineno) return;
393 text= xlu__cfg_yyget_text(ctx->scanner);
394 len= xlu__cfg_yyget_leng(ctx->scanner);
395 newline= "";
396 if (len>0 && text[len-1]=='\n') {
397 len--;
398 lineno--;
399 if (!len) {
400 newline= "<newline>";
401 }
402 }
403 while (len>0 && (text[len-1]=='\t' || text[len-1]==' ')) {
404 len--;
405 }
407 fprintf(ctx->cfg->report,
408 "%s:%d: config parsing error near %s%.*s%s%s: %s\n",
409 ctx->cfg->filename, lineno,
410 len?"`":"", len, text, len?"'":"", newline,
411 msg);
412 if (!ctx->err) ctx->err= EINVAL;
413 }