~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to tools/libxl/libxlu_cfg.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#include "libxlu_internal.h"
 
3
#include "libxlu_cfg_y.h"
 
4
#include "libxlu_cfg_l.h"
 
5
#include "libxlu_cfg_i.h"
 
6
 
 
7
XLU_Config *xlu_cfg_init(FILE *report, const char *report_filename) {
 
8
    XLU_Config *cfg;
 
9
 
 
10
    cfg= malloc(sizeof(*cfg));
 
11
    if (!cfg) return 0;
 
12
 
 
13
    cfg->report= report;
 
14
    cfg->filename= strdup(report_filename);
 
15
    if (!cfg->filename) { free(cfg); return 0; }
 
16
 
 
17
    cfg->settings= 0;
 
18
    return cfg;
 
19
}
 
20
 
 
21
int xlu_cfg_readfile(XLU_Config *cfg, const char *real_filename) {
 
22
    CfgParseContext ctx;
 
23
    FILE *f;
 
24
    int e, r;
 
25
 
 
26
    ctx.cfg= cfg;
 
27
    ctx.err= 0;
 
28
    ctx.lexerrlineno= -1;
 
29
    
 
30
    f= fopen(real_filename, "r");
 
31
    if (!f) {
 
32
        e= errno;
 
33
        fprintf(cfg->report,"%s: unable to open configuration file: %s\n",
 
34
                real_filename, strerror(e));
 
35
        return e;
 
36
    }
 
37
 
 
38
    e= xlu__cfg_yylex_init_extra(&ctx, &ctx.scanner);
 
39
    if (e) {
 
40
        fprintf(cfg->report,"%s: unable to create scanner: %s\n",
 
41
                cfg->filename, strerror(e));
 
42
        return e;
 
43
    }
 
44
 
 
45
    xlu__cfg_yyrestart(f, ctx.scanner);
 
46
 
 
47
    r= xlu__cfg_yyparse(&ctx);
 
48
    if (r) assert(ctx.err);
 
49
 
 
50
    xlu__cfg_yylex_destroy(ctx.scanner);
 
51
    fclose(f);
 
52
 
 
53
    return ctx.err;
 
54
}
 
55
 
 
56
void xlu__cfg_set_free(XLU_ConfigSetting *set) {
 
57
    free(set->name);
 
58
    free(set->values);
 
59
    free(set);
 
60
}
 
61
 
 
62
void xlu_cfg_destroy(XLU_Config *cfg) {
 
63
    XLU_ConfigSetting *set, *set_next;
 
64
 
 
65
    for (set= cfg->settings;
 
66
         set;
 
67
         set= set_next) {
 
68
        set_next= set->next;
 
69
        xlu__cfg_set_free(set);
 
70
    }
 
71
    free(cfg->filename);
 
72
    free(cfg);
 
73
}
 
74
 
 
75
static XLU_ConfigSetting *find(const XLU_Config *cfg, const char *n) {
 
76
    XLU_ConfigSetting *set;
 
77
 
 
78
    for (set= cfg->settings;
 
79
         set;
 
80
         set= set->next)
 
81
        if (!strcmp(set->name, n))
 
82
            return set;
 
83
    return 0;
 
84
}
 
85
 
 
86
static int find_atom(const XLU_Config *cfg, const char *n,
 
87
                     XLU_ConfigSetting **set_r) {
 
88
    XLU_ConfigSetting *set;
 
89
 
 
90
    set= find(cfg,n);
 
91
    if (!set) return ESRCH;
 
92
 
 
93
    if (set->avalues!=1) {
 
94
        fprintf(cfg->report,
 
95
                "%s:%d: warning: parameter `%s' is"
 
96
                " a list but should be a single value\n",
 
97
                cfg->filename, set->lineno, n);
 
98
        return EINVAL;
 
99
    }
 
100
    *set_r= set;
 
101
    return 0;
 
102
}
 
103
 
 
104
int xlu_cfg_get_string(const XLU_Config *cfg, const char *n,
 
105
                       const char **value_r) {
 
106
    XLU_ConfigSetting *set;
 
107
    int e;
 
108
 
 
109
    e= find_atom(cfg,n,&set);  if (e) return e;
 
110
    *value_r= set->values[0];
 
111
    return 0;
 
112
}
 
113
        
 
114
int xlu_cfg_get_long(const XLU_Config *cfg, const char *n,
 
115
                     long *value_r) {
 
116
    long l;
 
117
    XLU_ConfigSetting *set;
 
118
    int e;
 
119
    char *ep;
 
120
 
 
121
    e= find_atom(cfg,n,&set);  if (e) return e;
 
122
    errno= 0; l= strtol(set->values[0], &ep, 0);
 
123
    e= errno;
 
124
    if (errno) {
 
125
        e= errno;
 
126
        assert(e==EINVAL || e==ERANGE);
 
127
        fprintf(cfg->report,
 
128
                "%s:%d: warning: parameter `%s' could not be parsed"
 
129
                " as a number: %s\n",
 
130
                cfg->filename, set->lineno, n, strerror(e));
 
131
        return e;
 
132
    }
 
133
    if (*ep || ep==set->values[0]) {
 
134
        fprintf(cfg->report,
 
135
                "%s:%d: warning: parameter `%s' is not a valid number\n",
 
136
                cfg->filename, set->lineno, n);
 
137
        return EINVAL;
 
138
    }
 
139
    *value_r= l;
 
140
    return 0;
 
141
}
 
142
        
 
143
 
 
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) {
 
149
        fprintf(cfg->report,
 
150
                "%s:%d: warning: parameter `%s' is a single value"
 
151
                " but should be a list\n",
 
152
                cfg->filename, set->lineno, n);
 
153
        return EINVAL;
 
154
    }
 
155
    if (list_r) *list_r= set;
 
156
    if (entries_r) *entries_r= set->nvalues;
 
157
    return 0;
 
158
}
 
159
 
 
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];
 
163
}
 
164
 
 
165
 
 
166
XLU_ConfigSetting *xlu__cfg_set_mk(CfgParseContext *ctx,
 
167
                                   int alloc, char *atom) {
 
168
    XLU_ConfigSetting *set= 0;
 
169
 
 
170
    if (ctx->err) goto x;
 
171
    assert(!!alloc == !!atom);
 
172
 
 
173
    set= malloc(sizeof(*set));
 
174
    if (!set) goto xe;
 
175
 
 
176
    set->name= 0; /* tbd */
 
177
    set->avalues= alloc;
 
178
    
 
179
    if (!alloc) {
 
180
        set->nvalues= 0;
 
181
        set->values= 0;
 
182
    } else {
 
183
        set->values= malloc(sizeof(*set->values) * alloc);
 
184
        if (!set->values) goto xe;
 
185
 
 
186
        set->nvalues= 1;
 
187
        set->values[0]= atom;
 
188
    }
 
189
    return set;
 
190
 
 
191
 xe:
 
192
    ctx->err= errno;
 
193
 x:
 
194
    free(set);
 
195
    free(atom);
 
196
    return 0;
 
197
}
 
198
 
 
199
void xlu__cfg_set_add(CfgParseContext *ctx, XLU_ConfigSetting *set,
 
200
                      char *atom) {
 
201
    if (ctx->err) return;
 
202
 
 
203
    assert(atom);
 
204
    
 
205
    if (set->nvalues >= set->avalues) {
 
206
        int new_avalues;
 
207
        char **new_values;
 
208
        
 
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;
 
216
    }
 
217
    set->values[set->nvalues++]= atom;
 
218
}
 
219
 
 
220
void xlu__cfg_set_store(CfgParseContext *ctx, char *name,
 
221
                        XLU_ConfigSetting *set, int lineno) {
 
222
    if (ctx->err) return;
 
223
 
 
224
    assert(name);
 
225
    set->name= name;
 
226
    set->lineno= lineno;
 
227
    set->next= ctx->cfg->settings;
 
228
    ctx->cfg->settings= set;
 
229
}
 
230
 
 
231
char *xlu__cfgl_strdup(CfgParseContext *ctx, const char *src) {
 
232
    char *result;
 
233
    
 
234
    if (ctx->err) return 0;
 
235
    result= strdup(src);
 
236
    if (!result) ctx->err= errno;
 
237
    return result;
 
238
}
 
239
 
 
240
char *xlu__cfgl_dequote(CfgParseContext *ctx, const char *src) {
 
241
    char *result;
 
242
    const char *p;
 
243
    char *q;
 
244
    int len, c, nc;
 
245
 
 
246
    if (ctx->err) return 0;
 
247
 
 
248
    len= strlen(src);
 
249
    assert(len>=2 && src[0]==src[len-1]);
 
250
 
 
251
    result= malloc(len-1);
 
252
    if (!result) { ctx->err= errno; return 0; }
 
253
 
 
254
    q= result;
 
255
 
 
256
    for (p= src+1;
 
257
         p < src+len-1;
 
258
         ) {
 
259
        c= *p++;
 
260
        if (c=='\\') {
 
261
            assert(p < src+len-1);
 
262
            nc= *p++;
 
263
            if (nc=='"' || nc=='\'' || nc=='\\') {
 
264
                *q++= 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') {
 
273
 
 
274
#define NUMERIC_CHAR(minlen,maxlen,base,basetext) do{                        \
 
275
                char numbuf[(maxlen)+1], *ep;                                \
 
276
                unsigned long val;                                           \
 
277
                                                                             \
 
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");                               \
 
285
                    ctx->err= EINVAL;                                        \
 
286
                    goto x;                                                  \
 
287
                }                                                            \
 
288
                p += (ep - numbuf);                                          \
 
289
 }while(0) 
 
290
 
 
291
                p++;
 
292
                NUMERIC_CHAR(2,2,16,"hex");
 
293
            } else if (nc>='0' && nc<='7') {
 
294
                NUMERIC_CHAR(1,3,10,"octal");
 
295
            }
 
296
            assert(p <= src+len-1);
 
297
        } else {
 
298
            *q++= c;
 
299
        }
 
300
    }
 
301
 
 
302
 x:
 
303
    *q++= 0;
 
304
    return result;
 
305
}
 
306
 
 
307
void xlu__cfgl_lexicalerror(CfgParseContext *ctx, char const *msg) {
 
308
    YYLTYPE loc;
 
309
    loc.first_line= xlu__cfg_yyget_lineno(ctx->scanner);
 
310
    xlu__cfg_yyerror(&loc, ctx, msg);
 
311
    ctx->lexerrlineno= loc.first_line;
 
312
}
 
313
 
 
314
void xlu__cfg_yyerror(YYLTYPE *loc, CfgParseContext *ctx, char const *msg) {
 
315
    const char *text, *newline;
 
316
    int len, lineno;
 
317
 
 
318
    lineno= loc->first_line;
 
319
    if (lineno <= ctx->lexerrlineno) return;
 
320
 
 
321
    text= xlu__cfg_yyget_text(ctx->scanner);
 
322
    len= xlu__cfg_yyget_leng(ctx->scanner);
 
323
    newline= "";
 
324
    if (len>0 && text[len-1]=='\n') {
 
325
        len--;
 
326
        lineno--;
 
327
        if (!len) {
 
328
            newline= "<newline>";
 
329
        }
 
330
    }
 
331
    while (len>0 && (text[len-1]=='\t' || text[len-1]==' ')) {
 
332
        len--;
 
333
    }
 
334
 
 
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,
 
339
            msg);
 
340
    if (!ctx->err) ctx->err= EINVAL;
 
341
}