Statistics
| Branch: | Revision:

root / qemu-option.c @ d35215f8

History | View | Annotate | Download (23 kB)

1 d3f24367 Kevin Wolf
/*
2 d3f24367 Kevin Wolf
 * Commandline option parsing functions
3 d3f24367 Kevin Wolf
 *
4 d3f24367 Kevin Wolf
 * Copyright (c) 2003-2008 Fabrice Bellard
5 d3f24367 Kevin Wolf
 * Copyright (c) 2009 Kevin Wolf <kwolf@redhat.com>
6 d3f24367 Kevin Wolf
 *
7 d3f24367 Kevin Wolf
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 d3f24367 Kevin Wolf
 * of this software and associated documentation files (the "Software"), to deal
9 d3f24367 Kevin Wolf
 * in the Software without restriction, including without limitation the rights
10 d3f24367 Kevin Wolf
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 d3f24367 Kevin Wolf
 * copies of the Software, and to permit persons to whom the Software is
12 d3f24367 Kevin Wolf
 * furnished to do so, subject to the following conditions:
13 d3f24367 Kevin Wolf
 *
14 d3f24367 Kevin Wolf
 * The above copyright notice and this permission notice shall be included in
15 d3f24367 Kevin Wolf
 * all copies or substantial portions of the Software.
16 d3f24367 Kevin Wolf
 *
17 d3f24367 Kevin Wolf
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 d3f24367 Kevin Wolf
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 d3f24367 Kevin Wolf
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 d3f24367 Kevin Wolf
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 d3f24367 Kevin Wolf
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 d3f24367 Kevin Wolf
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 d3f24367 Kevin Wolf
 * THE SOFTWARE.
24 d3f24367 Kevin Wolf
 */
25 d3f24367 Kevin Wolf
26 d3f24367 Kevin Wolf
#include <stdio.h>
27 d3f24367 Kevin Wolf
#include <string.h>
28 d3f24367 Kevin Wolf
29 d3f24367 Kevin Wolf
#include "qemu-common.h"
30 827b0813 Markus Armbruster
#include "qemu-error.h"
31 01e7f188 Markus Armbruster
#include "qemu-objects.h"
32 d3f24367 Kevin Wolf
#include "qemu-option.h"
33 d3f24367 Kevin Wolf
34 d3f24367 Kevin Wolf
/*
35 d3f24367 Kevin Wolf
 * Extracts the name of an option from the parameter string (p points at the
36 d3f24367 Kevin Wolf
 * first byte of the option name)
37 d3f24367 Kevin Wolf
 *
38 d3f24367 Kevin Wolf
 * The option name is delimited by delim (usually , or =) or the string end
39 d3f24367 Kevin Wolf
 * and is copied into buf. If the option name is longer than buf_size, it is
40 d3f24367 Kevin Wolf
 * truncated. buf is always zero terminated.
41 d3f24367 Kevin Wolf
 *
42 d3f24367 Kevin Wolf
 * The return value is the position of the delimiter/zero byte after the option
43 d3f24367 Kevin Wolf
 * name in p.
44 d3f24367 Kevin Wolf
 */
45 d3f24367 Kevin Wolf
const char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
46 d3f24367 Kevin Wolf
{
47 d3f24367 Kevin Wolf
    char *q;
48 d3f24367 Kevin Wolf
49 d3f24367 Kevin Wolf
    q = buf;
50 d3f24367 Kevin Wolf
    while (*p != '\0' && *p != delim) {
51 d3f24367 Kevin Wolf
        if (q && (q - buf) < buf_size - 1)
52 d3f24367 Kevin Wolf
            *q++ = *p;
53 d3f24367 Kevin Wolf
        p++;
54 d3f24367 Kevin Wolf
    }
55 d3f24367 Kevin Wolf
    if (q)
56 d3f24367 Kevin Wolf
        *q = '\0';
57 d3f24367 Kevin Wolf
58 d3f24367 Kevin Wolf
    return p;
59 d3f24367 Kevin Wolf
}
60 d3f24367 Kevin Wolf
61 d3f24367 Kevin Wolf
/*
62 d3f24367 Kevin Wolf
 * Extracts the value of an option from the parameter string p (p points at the
63 d3f24367 Kevin Wolf
 * first byte of the option value)
64 d3f24367 Kevin Wolf
 *
65 d3f24367 Kevin Wolf
 * This function is comparable to get_opt_name with the difference that the
66 d3f24367 Kevin Wolf
 * delimiter is fixed to be comma which starts a new option. To specify an
67 d3f24367 Kevin Wolf
 * option value that contains commas, double each comma.
68 d3f24367 Kevin Wolf
 */
69 d3f24367 Kevin Wolf
const char *get_opt_value(char *buf, int buf_size, const char *p)
70 d3f24367 Kevin Wolf
{
71 d3f24367 Kevin Wolf
    char *q;
72 d3f24367 Kevin Wolf
73 d3f24367 Kevin Wolf
    q = buf;
74 d3f24367 Kevin Wolf
    while (*p != '\0') {
75 d3f24367 Kevin Wolf
        if (*p == ',') {
76 d3f24367 Kevin Wolf
            if (*(p + 1) != ',')
77 d3f24367 Kevin Wolf
                break;
78 d3f24367 Kevin Wolf
            p++;
79 d3f24367 Kevin Wolf
        }
80 d3f24367 Kevin Wolf
        if (q && (q - buf) < buf_size - 1)
81 d3f24367 Kevin Wolf
            *q++ = *p;
82 d3f24367 Kevin Wolf
        p++;
83 d3f24367 Kevin Wolf
    }
84 d3f24367 Kevin Wolf
    if (q)
85 d3f24367 Kevin Wolf
        *q = '\0';
86 d3f24367 Kevin Wolf
87 d3f24367 Kevin Wolf
    return p;
88 d3f24367 Kevin Wolf
}
89 d3f24367 Kevin Wolf
90 62c5802e Gerd Hoffmann
int get_next_param_value(char *buf, int buf_size,
91 62c5802e Gerd Hoffmann
                         const char *tag, const char **pstr)
92 62c5802e Gerd Hoffmann
{
93 62c5802e Gerd Hoffmann
    const char *p;
94 62c5802e Gerd Hoffmann
    char option[128];
95 62c5802e Gerd Hoffmann
96 62c5802e Gerd Hoffmann
    p = *pstr;
97 62c5802e Gerd Hoffmann
    for(;;) {
98 62c5802e Gerd Hoffmann
        p = get_opt_name(option, sizeof(option), p, '=');
99 62c5802e Gerd Hoffmann
        if (*p != '=')
100 62c5802e Gerd Hoffmann
            break;
101 62c5802e Gerd Hoffmann
        p++;
102 62c5802e Gerd Hoffmann
        if (!strcmp(tag, option)) {
103 62c5802e Gerd Hoffmann
            *pstr = get_opt_value(buf, buf_size, p);
104 62c5802e Gerd Hoffmann
            if (**pstr == ',') {
105 62c5802e Gerd Hoffmann
                (*pstr)++;
106 62c5802e Gerd Hoffmann
            }
107 62c5802e Gerd Hoffmann
            return strlen(buf);
108 62c5802e Gerd Hoffmann
        } else {
109 62c5802e Gerd Hoffmann
            p = get_opt_value(NULL, 0, p);
110 62c5802e Gerd Hoffmann
        }
111 62c5802e Gerd Hoffmann
        if (*p != ',')
112 62c5802e Gerd Hoffmann
            break;
113 62c5802e Gerd Hoffmann
        p++;
114 62c5802e Gerd Hoffmann
    }
115 62c5802e Gerd Hoffmann
    return 0;
116 62c5802e Gerd Hoffmann
}
117 62c5802e Gerd Hoffmann
118 62c5802e Gerd Hoffmann
int get_param_value(char *buf, int buf_size,
119 62c5802e Gerd Hoffmann
                    const char *tag, const char *str)
120 62c5802e Gerd Hoffmann
{
121 62c5802e Gerd Hoffmann
    return get_next_param_value(buf, buf_size, tag, &str);
122 62c5802e Gerd Hoffmann
}
123 62c5802e Gerd Hoffmann
124 62c5802e Gerd Hoffmann
int check_params(char *buf, int buf_size,
125 62c5802e Gerd Hoffmann
                 const char * const *params, const char *str)
126 62c5802e Gerd Hoffmann
{
127 62c5802e Gerd Hoffmann
    const char *p;
128 62c5802e Gerd Hoffmann
    int i;
129 62c5802e Gerd Hoffmann
130 62c5802e Gerd Hoffmann
    p = str;
131 62c5802e Gerd Hoffmann
    while (*p != '\0') {
132 62c5802e Gerd Hoffmann
        p = get_opt_name(buf, buf_size, p, '=');
133 62c5802e Gerd Hoffmann
        if (*p != '=') {
134 62c5802e Gerd Hoffmann
            return -1;
135 62c5802e Gerd Hoffmann
        }
136 62c5802e Gerd Hoffmann
        p++;
137 62c5802e Gerd Hoffmann
        for (i = 0; params[i] != NULL; i++) {
138 62c5802e Gerd Hoffmann
            if (!strcmp(params[i], buf)) {
139 62c5802e Gerd Hoffmann
                break;
140 62c5802e Gerd Hoffmann
            }
141 62c5802e Gerd Hoffmann
        }
142 62c5802e Gerd Hoffmann
        if (params[i] == NULL) {
143 62c5802e Gerd Hoffmann
            return -1;
144 62c5802e Gerd Hoffmann
        }
145 62c5802e Gerd Hoffmann
        p = get_opt_value(NULL, 0, p);
146 62c5802e Gerd Hoffmann
        if (*p != ',') {
147 62c5802e Gerd Hoffmann
            break;
148 62c5802e Gerd Hoffmann
        }
149 62c5802e Gerd Hoffmann
        p++;
150 62c5802e Gerd Hoffmann
    }
151 62c5802e Gerd Hoffmann
    return 0;
152 62c5802e Gerd Hoffmann
}
153 62c5802e Gerd Hoffmann
154 d3f24367 Kevin Wolf
/*
155 d3f24367 Kevin Wolf
 * Searches an option list for an option with the given name
156 d3f24367 Kevin Wolf
 */
157 d3f24367 Kevin Wolf
QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list,
158 d3f24367 Kevin Wolf
    const char *name)
159 d3f24367 Kevin Wolf
{
160 d3f24367 Kevin Wolf
    while (list && list->name) {
161 d3f24367 Kevin Wolf
        if (!strcmp(list->name, name)) {
162 d3f24367 Kevin Wolf
            return list;
163 d3f24367 Kevin Wolf
        }
164 d3f24367 Kevin Wolf
        list++;
165 d3f24367 Kevin Wolf
    }
166 d3f24367 Kevin Wolf
167 d3f24367 Kevin Wolf
    return NULL;
168 d3f24367 Kevin Wolf
}
169 d3f24367 Kevin Wolf
170 67b1355b Gerd Hoffmann
static int parse_option_bool(const char *name, const char *value, int *ret)
171 67b1355b Gerd Hoffmann
{
172 67b1355b Gerd Hoffmann
    if (value != NULL) {
173 67b1355b Gerd Hoffmann
        if (!strcmp(value, "on")) {
174 67b1355b Gerd Hoffmann
            *ret = 1;
175 67b1355b Gerd Hoffmann
        } else if (!strcmp(value, "off")) {
176 67b1355b Gerd Hoffmann
            *ret = 0;
177 67b1355b Gerd Hoffmann
        } else {
178 67b1355b Gerd Hoffmann
            fprintf(stderr, "Option '%s': Use 'on' or 'off'\n", name);
179 67b1355b Gerd Hoffmann
            return -1;
180 67b1355b Gerd Hoffmann
        }
181 67b1355b Gerd Hoffmann
    } else {
182 67b1355b Gerd Hoffmann
        *ret = 1;
183 67b1355b Gerd Hoffmann
    }
184 67b1355b Gerd Hoffmann
    return 0;
185 67b1355b Gerd Hoffmann
}
186 67b1355b Gerd Hoffmann
187 e27c88fe Gerd Hoffmann
static int parse_option_number(const char *name, const char *value, uint64_t *ret)
188 e27c88fe Gerd Hoffmann
{
189 e27c88fe Gerd Hoffmann
    char *postfix;
190 e27c88fe Gerd Hoffmann
    uint64_t number;
191 e27c88fe Gerd Hoffmann
192 e27c88fe Gerd Hoffmann
    if (value != NULL) {
193 e27c88fe Gerd Hoffmann
        number = strtoull(value, &postfix, 0);
194 e27c88fe Gerd Hoffmann
        if (*postfix != '\0') {
195 e27c88fe Gerd Hoffmann
            fprintf(stderr, "Option '%s' needs a number as parameter\n", name);
196 e27c88fe Gerd Hoffmann
            return -1;
197 e27c88fe Gerd Hoffmann
        }
198 21c9f4cd Gerd Hoffmann
        *ret = number;
199 e27c88fe Gerd Hoffmann
    } else {
200 e27c88fe Gerd Hoffmann
        fprintf(stderr, "Option '%s' needs a parameter\n", name);
201 e27c88fe Gerd Hoffmann
        return -1;
202 e27c88fe Gerd Hoffmann
    }
203 e27c88fe Gerd Hoffmann
    return 0;
204 e27c88fe Gerd Hoffmann
}
205 e27c88fe Gerd Hoffmann
206 7695019b Gerd Hoffmann
static int parse_option_size(const char *name, const char *value, uint64_t *ret)
207 7695019b Gerd Hoffmann
{
208 7695019b Gerd Hoffmann
    char *postfix;
209 7695019b Gerd Hoffmann
    double sizef;
210 7695019b Gerd Hoffmann
211 7695019b Gerd Hoffmann
    if (value != NULL) {
212 7695019b Gerd Hoffmann
        sizef = strtod(value, &postfix);
213 7695019b Gerd Hoffmann
        switch (*postfix) {
214 7695019b Gerd Hoffmann
        case 'T':
215 7695019b Gerd Hoffmann
            sizef *= 1024;
216 7695019b Gerd Hoffmann
        case 'G':
217 7695019b Gerd Hoffmann
            sizef *= 1024;
218 7695019b Gerd Hoffmann
        case 'M':
219 7695019b Gerd Hoffmann
            sizef *= 1024;
220 7695019b Gerd Hoffmann
        case 'K':
221 7695019b Gerd Hoffmann
        case 'k':
222 7695019b Gerd Hoffmann
            sizef *= 1024;
223 7695019b Gerd Hoffmann
        case 'b':
224 7695019b Gerd Hoffmann
        case '\0':
225 7695019b Gerd Hoffmann
            *ret = (uint64_t) sizef;
226 7695019b Gerd Hoffmann
            break;
227 7695019b Gerd Hoffmann
        default:
228 7695019b Gerd Hoffmann
            fprintf(stderr, "Option '%s' needs size as parameter\n", name);
229 7695019b Gerd Hoffmann
            fprintf(stderr, "You may use k, M, G or T suffixes for "
230 7695019b Gerd Hoffmann
                    "kilobytes, megabytes, gigabytes and terabytes.\n");
231 7695019b Gerd Hoffmann
            return -1;
232 7695019b Gerd Hoffmann
        }
233 7695019b Gerd Hoffmann
    } else {
234 7695019b Gerd Hoffmann
        fprintf(stderr, "Option '%s' needs a parameter\n", name);
235 7695019b Gerd Hoffmann
        return -1;
236 7695019b Gerd Hoffmann
    }
237 7695019b Gerd Hoffmann
    return 0;
238 7695019b Gerd Hoffmann
}
239 7695019b Gerd Hoffmann
240 d3f24367 Kevin Wolf
/*
241 d3f24367 Kevin Wolf
 * Sets the value of a parameter in a given option list. The parsing of the
242 d3f24367 Kevin Wolf
 * value depends on the type of option:
243 d3f24367 Kevin Wolf
 *
244 d3f24367 Kevin Wolf
 * OPT_FLAG (uses value.n):
245 d3f24367 Kevin Wolf
 *      If no value is given, the flag is set to 1.
246 d3f24367 Kevin Wolf
 *      Otherwise the value must be "on" (set to 1) or "off" (set to 0)
247 d3f24367 Kevin Wolf
 *
248 d3f24367 Kevin Wolf
 * OPT_STRING (uses value.s):
249 d3f24367 Kevin Wolf
 *      value is strdup()ed and assigned as option value
250 d3f24367 Kevin Wolf
 *
251 d3f24367 Kevin Wolf
 * OPT_SIZE (uses value.n):
252 d3f24367 Kevin Wolf
 *      The value is converted to an integer. Suffixes for kilobytes etc. are
253 d3f24367 Kevin Wolf
 *      allowed (powers of 1024).
254 d3f24367 Kevin Wolf
 *
255 d3f24367 Kevin Wolf
 * Returns 0 on succes, -1 in error cases
256 d3f24367 Kevin Wolf
 */
257 d3f24367 Kevin Wolf
int set_option_parameter(QEMUOptionParameter *list, const char *name,
258 d3f24367 Kevin Wolf
    const char *value)
259 d3f24367 Kevin Wolf
{
260 67b1355b Gerd Hoffmann
    int flag;
261 67b1355b Gerd Hoffmann
262 d3f24367 Kevin Wolf
    // Find a matching parameter
263 d3f24367 Kevin Wolf
    list = get_option_parameter(list, name);
264 d3f24367 Kevin Wolf
    if (list == NULL) {
265 d3f24367 Kevin Wolf
        fprintf(stderr, "Unknown option '%s'\n", name);
266 d3f24367 Kevin Wolf
        return -1;
267 d3f24367 Kevin Wolf
    }
268 d3f24367 Kevin Wolf
269 d3f24367 Kevin Wolf
    // Process parameter
270 d3f24367 Kevin Wolf
    switch (list->type) {
271 d3f24367 Kevin Wolf
    case OPT_FLAG:
272 3df04ac3 Mark McLoughlin
        if (parse_option_bool(name, value, &flag) == -1)
273 67b1355b Gerd Hoffmann
            return -1;
274 67b1355b Gerd Hoffmann
        list->value.n = flag;
275 d3f24367 Kevin Wolf
        break;
276 d3f24367 Kevin Wolf
277 d3f24367 Kevin Wolf
    case OPT_STRING:
278 d3f24367 Kevin Wolf
        if (value != NULL) {
279 d4c3fddd Jean-Christophe DUBOIS
            list->value.s = qemu_strdup(value);
280 d3f24367 Kevin Wolf
        } else {
281 d3f24367 Kevin Wolf
            fprintf(stderr, "Option '%s' needs a parameter\n", name);
282 d3f24367 Kevin Wolf
            return -1;
283 d3f24367 Kevin Wolf
        }
284 d3f24367 Kevin Wolf
        break;
285 d3f24367 Kevin Wolf
286 d3f24367 Kevin Wolf
    case OPT_SIZE:
287 3df04ac3 Mark McLoughlin
        if (parse_option_size(name, value, &list->value.n) == -1)
288 d3f24367 Kevin Wolf
            return -1;
289 d3f24367 Kevin Wolf
        break;
290 7695019b Gerd Hoffmann
291 d3f24367 Kevin Wolf
    default:
292 d3f24367 Kevin Wolf
        fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name);
293 d3f24367 Kevin Wolf
        return -1;
294 d3f24367 Kevin Wolf
    }
295 d3f24367 Kevin Wolf
296 d3f24367 Kevin Wolf
    return 0;
297 d3f24367 Kevin Wolf
}
298 d3f24367 Kevin Wolf
299 d3f24367 Kevin Wolf
/*
300 d3f24367 Kevin Wolf
 * Sets the given parameter to an integer instead of a string.
301 d3f24367 Kevin Wolf
 * This function cannot be used to set string options.
302 d3f24367 Kevin Wolf
 *
303 d3f24367 Kevin Wolf
 * Returns 0 on success, -1 in error cases
304 d3f24367 Kevin Wolf
 */
305 d3f24367 Kevin Wolf
int set_option_parameter_int(QEMUOptionParameter *list, const char *name,
306 d3f24367 Kevin Wolf
    uint64_t value)
307 d3f24367 Kevin Wolf
{
308 d3f24367 Kevin Wolf
    // Find a matching parameter
309 d3f24367 Kevin Wolf
    list = get_option_parameter(list, name);
310 d3f24367 Kevin Wolf
    if (list == NULL) {
311 d3f24367 Kevin Wolf
        fprintf(stderr, "Unknown option '%s'\n", name);
312 d3f24367 Kevin Wolf
        return -1;
313 d3f24367 Kevin Wolf
    }
314 d3f24367 Kevin Wolf
315 d3f24367 Kevin Wolf
    // Process parameter
316 d3f24367 Kevin Wolf
    switch (list->type) {
317 d3f24367 Kevin Wolf
    case OPT_FLAG:
318 d3f24367 Kevin Wolf
    case OPT_NUMBER:
319 d3f24367 Kevin Wolf
    case OPT_SIZE:
320 d3f24367 Kevin Wolf
        list->value.n = value;
321 d3f24367 Kevin Wolf
        break;
322 d3f24367 Kevin Wolf
323 d3f24367 Kevin Wolf
    default:
324 d3f24367 Kevin Wolf
        return -1;
325 d3f24367 Kevin Wolf
    }
326 d3f24367 Kevin Wolf
327 d3f24367 Kevin Wolf
    return 0;
328 d3f24367 Kevin Wolf
}
329 d3f24367 Kevin Wolf
330 d3f24367 Kevin Wolf
/*
331 d3f24367 Kevin Wolf
 * Frees a option list. If it contains strings, the strings are freed as well.
332 d3f24367 Kevin Wolf
 */
333 d3f24367 Kevin Wolf
void free_option_parameters(QEMUOptionParameter *list)
334 d3f24367 Kevin Wolf
{
335 d3f24367 Kevin Wolf
    QEMUOptionParameter *cur = list;
336 d3f24367 Kevin Wolf
337 d3f24367 Kevin Wolf
    while (cur && cur->name) {
338 d3f24367 Kevin Wolf
        if (cur->type == OPT_STRING) {
339 d4c3fddd Jean-Christophe DUBOIS
            qemu_free(cur->value.s);
340 d3f24367 Kevin Wolf
        }
341 d3f24367 Kevin Wolf
        cur++;
342 d3f24367 Kevin Wolf
    }
343 d3f24367 Kevin Wolf
344 d4c3fddd Jean-Christophe DUBOIS
    qemu_free(list);
345 d3f24367 Kevin Wolf
}
346 d3f24367 Kevin Wolf
347 d3f24367 Kevin Wolf
/*
348 d3f24367 Kevin Wolf
 * Parses a parameter string (param) into an option list (dest).
349 d3f24367 Kevin Wolf
 *
350 d3f24367 Kevin Wolf
 * list is the templace is. If dest is NULL, a new copy of list is created for
351 d3f24367 Kevin Wolf
 * it. If list is NULL, this function fails.
352 d3f24367 Kevin Wolf
 *
353 d3f24367 Kevin Wolf
 * A parameter string consists of one or more parameters, separated by commas.
354 d3f24367 Kevin Wolf
 * Each parameter consists of its name and possibly of a value. In the latter
355 d3f24367 Kevin Wolf
 * case, the value is delimited by an = character. To specify a value which
356 d3f24367 Kevin Wolf
 * contains commas, double each comma so it won't be recognized as the end of
357 d3f24367 Kevin Wolf
 * the parameter.
358 d3f24367 Kevin Wolf
 *
359 d3f24367 Kevin Wolf
 * For more details of the parsing see above.
360 d3f24367 Kevin Wolf
 *
361 d3f24367 Kevin Wolf
 * Returns a pointer to the first element of dest (or the newly allocated copy)
362 d3f24367 Kevin Wolf
 * or NULL in error cases
363 d3f24367 Kevin Wolf
 */
364 d3f24367 Kevin Wolf
QEMUOptionParameter *parse_option_parameters(const char *param,
365 d3f24367 Kevin Wolf
    QEMUOptionParameter *list, QEMUOptionParameter *dest)
366 d3f24367 Kevin Wolf
{
367 d3f24367 Kevin Wolf
    QEMUOptionParameter *cur;
368 d3f24367 Kevin Wolf
    QEMUOptionParameter *allocated = NULL;
369 d3f24367 Kevin Wolf
    char name[256];
370 d3f24367 Kevin Wolf
    char value[256];
371 d3f24367 Kevin Wolf
    char *param_delim, *value_delim;
372 d3f24367 Kevin Wolf
    char next_delim;
373 d3f24367 Kevin Wolf
    size_t num_options;
374 d3f24367 Kevin Wolf
375 d3f24367 Kevin Wolf
    if (list == NULL) {
376 d3f24367 Kevin Wolf
        return NULL;
377 d3f24367 Kevin Wolf
    }
378 d3f24367 Kevin Wolf
379 d3f24367 Kevin Wolf
    if (dest == NULL) {
380 d3f24367 Kevin Wolf
        // Count valid options
381 d3f24367 Kevin Wolf
        num_options = 0;
382 d3f24367 Kevin Wolf
        cur = list;
383 d3f24367 Kevin Wolf
        while (cur->name) {
384 d3f24367 Kevin Wolf
            num_options++;
385 d3f24367 Kevin Wolf
            cur++;
386 d3f24367 Kevin Wolf
        }
387 d3f24367 Kevin Wolf
388 d3f24367 Kevin Wolf
        // Create a copy of the option list to fill in values
389 d3f24367 Kevin Wolf
        dest = qemu_mallocz((num_options + 1) * sizeof(QEMUOptionParameter));
390 d3f24367 Kevin Wolf
        allocated = dest;
391 d3f24367 Kevin Wolf
        memcpy(dest, list, (num_options + 1) * sizeof(QEMUOptionParameter));
392 d3f24367 Kevin Wolf
    }
393 d3f24367 Kevin Wolf
394 d3f24367 Kevin Wolf
    while (*param) {
395 d3f24367 Kevin Wolf
396 d3f24367 Kevin Wolf
        // Find parameter name and value in the string
397 d3f24367 Kevin Wolf
        param_delim = strchr(param, ',');
398 d3f24367 Kevin Wolf
        value_delim = strchr(param, '=');
399 d3f24367 Kevin Wolf
400 d3f24367 Kevin Wolf
        if (value_delim && (value_delim < param_delim || !param_delim)) {
401 d3f24367 Kevin Wolf
            next_delim = '=';
402 d3f24367 Kevin Wolf
        } else {
403 d3f24367 Kevin Wolf
            next_delim = ',';
404 d3f24367 Kevin Wolf
            value_delim = NULL;
405 d3f24367 Kevin Wolf
        }
406 d3f24367 Kevin Wolf
407 d3f24367 Kevin Wolf
        param = get_opt_name(name, sizeof(name), param, next_delim);
408 d3f24367 Kevin Wolf
        if (value_delim) {
409 d3f24367 Kevin Wolf
            param = get_opt_value(value, sizeof(value), param + 1);
410 d3f24367 Kevin Wolf
        }
411 d3f24367 Kevin Wolf
        if (*param != '\0') {
412 d3f24367 Kevin Wolf
            param++;
413 d3f24367 Kevin Wolf
        }
414 d3f24367 Kevin Wolf
415 d3f24367 Kevin Wolf
        // Set the parameter
416 d3f24367 Kevin Wolf
        if (set_option_parameter(dest, name, value_delim ? value : NULL)) {
417 d3f24367 Kevin Wolf
            goto fail;
418 d3f24367 Kevin Wolf
        }
419 d3f24367 Kevin Wolf
    }
420 d3f24367 Kevin Wolf
421 d3f24367 Kevin Wolf
    return dest;
422 d3f24367 Kevin Wolf
423 d3f24367 Kevin Wolf
fail:
424 d3f24367 Kevin Wolf
    // Only free the list if it was newly allocated
425 d3f24367 Kevin Wolf
    free_option_parameters(allocated);
426 d3f24367 Kevin Wolf
    return NULL;
427 d3f24367 Kevin Wolf
}
428 d3f24367 Kevin Wolf
429 d3f24367 Kevin Wolf
/*
430 d3f24367 Kevin Wolf
 * Prints all options of a list that have a value to stdout
431 d3f24367 Kevin Wolf
 */
432 d3f24367 Kevin Wolf
void print_option_parameters(QEMUOptionParameter *list)
433 d3f24367 Kevin Wolf
{
434 d3f24367 Kevin Wolf
    while (list && list->name) {
435 d3f24367 Kevin Wolf
        switch (list->type) {
436 d3f24367 Kevin Wolf
            case OPT_STRING:
437 d3f24367 Kevin Wolf
                 if (list->value.s != NULL) {
438 d3f24367 Kevin Wolf
                     printf("%s='%s' ", list->name, list->value.s);
439 d3f24367 Kevin Wolf
                 }
440 d3f24367 Kevin Wolf
                break;
441 d3f24367 Kevin Wolf
            case OPT_FLAG:
442 d3f24367 Kevin Wolf
                printf("%s=%s ", list->name, list->value.n ? "on" : "off");
443 d3f24367 Kevin Wolf
                break;
444 d3f24367 Kevin Wolf
            case OPT_SIZE:
445 d3f24367 Kevin Wolf
            case OPT_NUMBER:
446 d3f24367 Kevin Wolf
                printf("%s=%" PRId64 " ", list->name, list->value.n);
447 d3f24367 Kevin Wolf
                break;
448 d3f24367 Kevin Wolf
            default:
449 d3f24367 Kevin Wolf
                printf("%s=(unkown type) ", list->name);
450 d3f24367 Kevin Wolf
                break;
451 d3f24367 Kevin Wolf
        }
452 d3f24367 Kevin Wolf
        list++;
453 d3f24367 Kevin Wolf
    }
454 d3f24367 Kevin Wolf
}
455 db08adf5 Kevin Wolf
456 db08adf5 Kevin Wolf
/*
457 db08adf5 Kevin Wolf
 * Prints an overview of all available options
458 db08adf5 Kevin Wolf
 */
459 db08adf5 Kevin Wolf
void print_option_help(QEMUOptionParameter *list)
460 db08adf5 Kevin Wolf
{
461 db08adf5 Kevin Wolf
    printf("Supported options:\n");
462 db08adf5 Kevin Wolf
    while (list && list->name) {
463 db08adf5 Kevin Wolf
        printf("%-16s %s\n", list->name,
464 db08adf5 Kevin Wolf
            list->help ? list->help : "No description available");
465 db08adf5 Kevin Wolf
        list++;
466 db08adf5 Kevin Wolf
    }
467 db08adf5 Kevin Wolf
}
468 e27c88fe Gerd Hoffmann
469 e27c88fe Gerd Hoffmann
/* ------------------------------------------------------------------ */
470 e27c88fe Gerd Hoffmann
471 e27c88fe Gerd Hoffmann
struct QemuOpt {
472 e27c88fe Gerd Hoffmann
    const char   *name;
473 e27c88fe Gerd Hoffmann
    const char   *str;
474 e27c88fe Gerd Hoffmann
475 238431a9 Blue Swirl
    const QemuOptDesc *desc;
476 e27c88fe Gerd Hoffmann
    union {
477 1f5c1775 Juan Quintela
        int      boolean;
478 e27c88fe Gerd Hoffmann
        uint64_t uint;
479 e27c88fe Gerd Hoffmann
    } value;
480 e27c88fe Gerd Hoffmann
481 e27c88fe Gerd Hoffmann
    QemuOpts     *opts;
482 72cf2d4f Blue Swirl
    QTAILQ_ENTRY(QemuOpt) next;
483 e27c88fe Gerd Hoffmann
};
484 e27c88fe Gerd Hoffmann
485 e27c88fe Gerd Hoffmann
struct QemuOpts {
486 b09417b9 Jan Kiszka
    char *id;
487 e27c88fe Gerd Hoffmann
    QemuOptsList *list;
488 827b0813 Markus Armbruster
    Location loc;
489 dc9ca4ba Mark McLoughlin
    QTAILQ_HEAD(QemuOptHead, QemuOpt) head;
490 72cf2d4f Blue Swirl
    QTAILQ_ENTRY(QemuOpts) next;
491 e27c88fe Gerd Hoffmann
};
492 e27c88fe Gerd Hoffmann
493 e27c88fe Gerd Hoffmann
static QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
494 e27c88fe Gerd Hoffmann
{
495 e27c88fe Gerd Hoffmann
    QemuOpt *opt;
496 e27c88fe Gerd Hoffmann
497 dc9ca4ba Mark McLoughlin
    QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
498 e27c88fe Gerd Hoffmann
        if (strcmp(opt->name, name) != 0)
499 e27c88fe Gerd Hoffmann
            continue;
500 e27c88fe Gerd Hoffmann
        return opt;
501 e27c88fe Gerd Hoffmann
    }
502 e27c88fe Gerd Hoffmann
    return NULL;
503 e27c88fe Gerd Hoffmann
}
504 e27c88fe Gerd Hoffmann
505 e27c88fe Gerd Hoffmann
const char *qemu_opt_get(QemuOpts *opts, const char *name)
506 e27c88fe Gerd Hoffmann
{
507 e27c88fe Gerd Hoffmann
    QemuOpt *opt = qemu_opt_find(opts, name);
508 e27c88fe Gerd Hoffmann
    return opt ? opt->str : NULL;
509 e27c88fe Gerd Hoffmann
}
510 e27c88fe Gerd Hoffmann
511 e27c88fe Gerd Hoffmann
int qemu_opt_get_bool(QemuOpts *opts, const char *name, int defval)
512 e27c88fe Gerd Hoffmann
{
513 e27c88fe Gerd Hoffmann
    QemuOpt *opt = qemu_opt_find(opts, name);
514 e27c88fe Gerd Hoffmann
515 e27c88fe Gerd Hoffmann
    if (opt == NULL)
516 e27c88fe Gerd Hoffmann
        return defval;
517 e27c88fe Gerd Hoffmann
    assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
518 1f5c1775 Juan Quintela
    return opt->value.boolean;
519 e27c88fe Gerd Hoffmann
}
520 e27c88fe Gerd Hoffmann
521 e27c88fe Gerd Hoffmann
uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
522 e27c88fe Gerd Hoffmann
{
523 e27c88fe Gerd Hoffmann
    QemuOpt *opt = qemu_opt_find(opts, name);
524 e27c88fe Gerd Hoffmann
525 e27c88fe Gerd Hoffmann
    if (opt == NULL)
526 e27c88fe Gerd Hoffmann
        return defval;
527 e27c88fe Gerd Hoffmann
    assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER);
528 e27c88fe Gerd Hoffmann
    return opt->value.uint;
529 e27c88fe Gerd Hoffmann
}
530 e27c88fe Gerd Hoffmann
531 e27c88fe Gerd Hoffmann
uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
532 e27c88fe Gerd Hoffmann
{
533 e27c88fe Gerd Hoffmann
    QemuOpt *opt = qemu_opt_find(opts, name);
534 e27c88fe Gerd Hoffmann
535 e27c88fe Gerd Hoffmann
    if (opt == NULL)
536 e27c88fe Gerd Hoffmann
        return defval;
537 e27c88fe Gerd Hoffmann
    assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
538 e27c88fe Gerd Hoffmann
    return opt->value.uint;
539 e27c88fe Gerd Hoffmann
}
540 e27c88fe Gerd Hoffmann
541 e27c88fe Gerd Hoffmann
static int qemu_opt_parse(QemuOpt *opt)
542 e27c88fe Gerd Hoffmann
{
543 e27c88fe Gerd Hoffmann
    if (opt->desc == NULL)
544 e27c88fe Gerd Hoffmann
        return 0;
545 e27c88fe Gerd Hoffmann
    switch (opt->desc->type) {
546 e27c88fe Gerd Hoffmann
    case QEMU_OPT_STRING:
547 e27c88fe Gerd Hoffmann
        /* nothing */
548 e27c88fe Gerd Hoffmann
        return 0;
549 e27c88fe Gerd Hoffmann
    case QEMU_OPT_BOOL:
550 1f5c1775 Juan Quintela
        return parse_option_bool(opt->name, opt->str, &opt->value.boolean);
551 e27c88fe Gerd Hoffmann
    case QEMU_OPT_NUMBER:
552 e27c88fe Gerd Hoffmann
        return parse_option_number(opt->name, opt->str, &opt->value.uint);
553 e27c88fe Gerd Hoffmann
    case QEMU_OPT_SIZE:
554 e27c88fe Gerd Hoffmann
        return parse_option_size(opt->name, opt->str, &opt->value.uint);
555 e27c88fe Gerd Hoffmann
    default:
556 e27c88fe Gerd Hoffmann
        abort();
557 e27c88fe Gerd Hoffmann
    }
558 e27c88fe Gerd Hoffmann
}
559 e27c88fe Gerd Hoffmann
560 e27c88fe Gerd Hoffmann
static void qemu_opt_del(QemuOpt *opt)
561 e27c88fe Gerd Hoffmann
{
562 72cf2d4f Blue Swirl
    QTAILQ_REMOVE(&opt->opts->head, opt, next);
563 e27c88fe Gerd Hoffmann
    qemu_free((/* !const */ char*)opt->name);
564 e27c88fe Gerd Hoffmann
    qemu_free((/* !const */ char*)opt->str);
565 e27c88fe Gerd Hoffmann
    qemu_free(opt);
566 e27c88fe Gerd Hoffmann
}
567 e27c88fe Gerd Hoffmann
568 e27c88fe Gerd Hoffmann
int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
569 e27c88fe Gerd Hoffmann
{
570 e27c88fe Gerd Hoffmann
    QemuOpt *opt;
571 238431a9 Blue Swirl
    const QemuOptDesc *desc = opts->list->desc;
572 dc9ca4ba Mark McLoughlin
    int i;
573 e27c88fe Gerd Hoffmann
574 dc9ca4ba Mark McLoughlin
    for (i = 0; desc[i].name != NULL; i++) {
575 dc9ca4ba Mark McLoughlin
        if (strcmp(desc[i].name, name) == 0) {
576 dc9ca4ba Mark McLoughlin
            break;
577 e27c88fe Gerd Hoffmann
        }
578 dc9ca4ba Mark McLoughlin
    }
579 dc9ca4ba Mark McLoughlin
    if (desc[i].name == NULL) {
580 dc9ca4ba Mark McLoughlin
        if (i == 0) {
581 dc9ca4ba Mark McLoughlin
            /* empty list -> allow any */;
582 dc9ca4ba Mark McLoughlin
        } else {
583 dc9ca4ba Mark McLoughlin
            fprintf(stderr, "option \"%s\" is not valid for %s\n",
584 dc9ca4ba Mark McLoughlin
                    name, opts->list->name);
585 dc9ca4ba Mark McLoughlin
            return -1;
586 e27c88fe Gerd Hoffmann
        }
587 e27c88fe Gerd Hoffmann
    }
588 dc9ca4ba Mark McLoughlin
589 dc9ca4ba Mark McLoughlin
    opt = qemu_mallocz(sizeof(*opt));
590 dc9ca4ba Mark McLoughlin
    opt->name = qemu_strdup(name);
591 dc9ca4ba Mark McLoughlin
    opt->opts = opts;
592 dc9ca4ba Mark McLoughlin
    QTAILQ_INSERT_TAIL(&opts->head, opt, next);
593 dc9ca4ba Mark McLoughlin
    if (desc[i].name != NULL) {
594 dc9ca4ba Mark McLoughlin
        opt->desc = desc+i;
595 dc9ca4ba Mark McLoughlin
    }
596 e27c88fe Gerd Hoffmann
    if (value) {
597 e27c88fe Gerd Hoffmann
        opt->str = qemu_strdup(value);
598 e27c88fe Gerd Hoffmann
    }
599 e27c88fe Gerd Hoffmann
    if (qemu_opt_parse(opt) < 0) {
600 e27c88fe Gerd Hoffmann
        fprintf(stderr, "Failed to parse \"%s\" for \"%s.%s\"\n", opt->str,
601 e27c88fe Gerd Hoffmann
                opts->list->name, opt->name);
602 e27c88fe Gerd Hoffmann
        qemu_opt_del(opt);
603 e27c88fe Gerd Hoffmann
        return -1;
604 e27c88fe Gerd Hoffmann
    }
605 e27c88fe Gerd Hoffmann
    return 0;
606 e27c88fe Gerd Hoffmann
}
607 e27c88fe Gerd Hoffmann
608 48026075 Gerd Hoffmann
int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
609 48026075 Gerd Hoffmann
                     int abort_on_failure)
610 48026075 Gerd Hoffmann
{
611 48026075 Gerd Hoffmann
    QemuOpt *opt;
612 48026075 Gerd Hoffmann
    int rc = 0;
613 48026075 Gerd Hoffmann
614 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(opt, &opts->head, next) {
615 48026075 Gerd Hoffmann
        rc = func(opt->name, opt->str, opaque);
616 48026075 Gerd Hoffmann
        if (abort_on_failure  &&  rc != 0)
617 48026075 Gerd Hoffmann
            break;
618 48026075 Gerd Hoffmann
    }
619 48026075 Gerd Hoffmann
    return rc;
620 48026075 Gerd Hoffmann
}
621 48026075 Gerd Hoffmann
622 e27c88fe Gerd Hoffmann
QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
623 e27c88fe Gerd Hoffmann
{
624 e27c88fe Gerd Hoffmann
    QemuOpts *opts;
625 e27c88fe Gerd Hoffmann
626 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(opts, &list->head, next) {
627 e27c88fe Gerd Hoffmann
        if (!opts->id) {
628 e27c88fe Gerd Hoffmann
            continue;
629 e27c88fe Gerd Hoffmann
        }
630 e27c88fe Gerd Hoffmann
        if (strcmp(opts->id, id) != 0) {
631 e27c88fe Gerd Hoffmann
            continue;
632 e27c88fe Gerd Hoffmann
        }
633 e27c88fe Gerd Hoffmann
        return opts;
634 e27c88fe Gerd Hoffmann
    }
635 e27c88fe Gerd Hoffmann
    return NULL;
636 e27c88fe Gerd Hoffmann
}
637 e27c88fe Gerd Hoffmann
638 e27c88fe Gerd Hoffmann
QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists)
639 e27c88fe Gerd Hoffmann
{
640 e27c88fe Gerd Hoffmann
    QemuOpts *opts = NULL;
641 e27c88fe Gerd Hoffmann
642 e27c88fe Gerd Hoffmann
    if (id) {
643 e27c88fe Gerd Hoffmann
        opts = qemu_opts_find(list, id);
644 e27c88fe Gerd Hoffmann
        if (opts != NULL) {
645 e27c88fe Gerd Hoffmann
            if (fail_if_exists) {
646 e27c88fe Gerd Hoffmann
                fprintf(stderr, "tried to create id \"%s\" twice for \"%s\"\n",
647 e27c88fe Gerd Hoffmann
                        id, list->name);
648 e27c88fe Gerd Hoffmann
                return NULL;
649 e27c88fe Gerd Hoffmann
            } else {
650 e27c88fe Gerd Hoffmann
                return opts;
651 e27c88fe Gerd Hoffmann
            }
652 e27c88fe Gerd Hoffmann
        }
653 e27c88fe Gerd Hoffmann
    }
654 e27c88fe Gerd Hoffmann
    opts = qemu_mallocz(sizeof(*opts));
655 e27c88fe Gerd Hoffmann
    if (id) {
656 e27c88fe Gerd Hoffmann
        opts->id = qemu_strdup(id);
657 e27c88fe Gerd Hoffmann
    }
658 e27c88fe Gerd Hoffmann
    opts->list = list;
659 827b0813 Markus Armbruster
    loc_save(&opts->loc);
660 72cf2d4f Blue Swirl
    QTAILQ_INIT(&opts->head);
661 72cf2d4f Blue Swirl
    QTAILQ_INSERT_TAIL(&list->head, opts, next);
662 e27c88fe Gerd Hoffmann
    return opts;
663 e27c88fe Gerd Hoffmann
}
664 e27c88fe Gerd Hoffmann
665 e27c88fe Gerd Hoffmann
int qemu_opts_set(QemuOptsList *list, const char *id,
666 e27c88fe Gerd Hoffmann
                  const char *name, const char *value)
667 e27c88fe Gerd Hoffmann
{
668 e27c88fe Gerd Hoffmann
    QemuOpts *opts;
669 e27c88fe Gerd Hoffmann
670 e27c88fe Gerd Hoffmann
    opts = qemu_opts_create(list, id, 1);
671 e27c88fe Gerd Hoffmann
    if (opts == NULL) {
672 e27c88fe Gerd Hoffmann
        return -1;
673 e27c88fe Gerd Hoffmann
    }
674 e27c88fe Gerd Hoffmann
    return qemu_opt_set(opts, name, value);
675 e27c88fe Gerd Hoffmann
}
676 e27c88fe Gerd Hoffmann
677 48026075 Gerd Hoffmann
const char *qemu_opts_id(QemuOpts *opts)
678 48026075 Gerd Hoffmann
{
679 48026075 Gerd Hoffmann
    return opts->id;
680 48026075 Gerd Hoffmann
}
681 48026075 Gerd Hoffmann
682 e27c88fe Gerd Hoffmann
void qemu_opts_del(QemuOpts *opts)
683 e27c88fe Gerd Hoffmann
{
684 e27c88fe Gerd Hoffmann
    QemuOpt *opt;
685 e27c88fe Gerd Hoffmann
686 e27c88fe Gerd Hoffmann
    for (;;) {
687 72cf2d4f Blue Swirl
        opt = QTAILQ_FIRST(&opts->head);
688 e27c88fe Gerd Hoffmann
        if (opt == NULL)
689 e27c88fe Gerd Hoffmann
            break;
690 e27c88fe Gerd Hoffmann
        qemu_opt_del(opt);
691 e27c88fe Gerd Hoffmann
    }
692 72cf2d4f Blue Swirl
    QTAILQ_REMOVE(&opts->list->head, opts, next);
693 b09417b9 Jan Kiszka
    qemu_free(opts->id);
694 e27c88fe Gerd Hoffmann
    qemu_free(opts);
695 e27c88fe Gerd Hoffmann
}
696 e27c88fe Gerd Hoffmann
697 e27c88fe Gerd Hoffmann
int qemu_opts_print(QemuOpts *opts, void *dummy)
698 e27c88fe Gerd Hoffmann
{
699 e27c88fe Gerd Hoffmann
    QemuOpt *opt;
700 e27c88fe Gerd Hoffmann
701 e27c88fe Gerd Hoffmann
    fprintf(stderr, "%s: %s:", opts->list->name,
702 e27c88fe Gerd Hoffmann
            opts->id ? opts->id : "<noid>");
703 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(opt, &opts->head, next) {
704 e27c88fe Gerd Hoffmann
        fprintf(stderr, " %s=\"%s\"", opt->name, opt->str);
705 e27c88fe Gerd Hoffmann
    }
706 e27c88fe Gerd Hoffmann
    fprintf(stderr, "\n");
707 e27c88fe Gerd Hoffmann
    return 0;
708 e27c88fe Gerd Hoffmann
}
709 e27c88fe Gerd Hoffmann
710 96729cbd Gerd Hoffmann
int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname)
711 e27c88fe Gerd Hoffmann
{
712 d318ff99 Gerd Hoffmann
    char option[128], value[1024];
713 e27c88fe Gerd Hoffmann
    const char *p,*pe,*pc;
714 e27c88fe Gerd Hoffmann
715 2cfa571f Mark McLoughlin
    for (p = params; *p != '\0'; p++) {
716 e27c88fe Gerd Hoffmann
        pe = strchr(p, '=');
717 e27c88fe Gerd Hoffmann
        pc = strchr(p, ',');
718 e27c88fe Gerd Hoffmann
        if (!pe || (pc && pc < pe)) {
719 e27c88fe Gerd Hoffmann
            /* found "foo,more" */
720 e27c88fe Gerd Hoffmann
            if (p == params && firstname) {
721 e27c88fe Gerd Hoffmann
                /* implicitly named first option */
722 e27c88fe Gerd Hoffmann
                pstrcpy(option, sizeof(option), firstname);
723 e27c88fe Gerd Hoffmann
                p = get_opt_value(value, sizeof(value), p);
724 e27c88fe Gerd Hoffmann
            } else {
725 e27c88fe Gerd Hoffmann
                /* option without value, probably a flag */
726 e27c88fe Gerd Hoffmann
                p = get_opt_name(option, sizeof(option), p, ',');
727 96729cbd Gerd Hoffmann
                if (strncmp(option, "no", 2) == 0) {
728 e27c88fe Gerd Hoffmann
                    memmove(option, option+2, strlen(option+2)+1);
729 e27c88fe Gerd Hoffmann
                    pstrcpy(value, sizeof(value), "off");
730 e27c88fe Gerd Hoffmann
                } else {
731 e27c88fe Gerd Hoffmann
                    pstrcpy(value, sizeof(value), "on");
732 e27c88fe Gerd Hoffmann
                }
733 e27c88fe Gerd Hoffmann
            }
734 e27c88fe Gerd Hoffmann
        } else {
735 e27c88fe Gerd Hoffmann
            /* found "foo=bar,more" */
736 e27c88fe Gerd Hoffmann
            p = get_opt_name(option, sizeof(option), p, '=');
737 e27c88fe Gerd Hoffmann
            if (*p != '=') {
738 e27c88fe Gerd Hoffmann
                break;
739 e27c88fe Gerd Hoffmann
            }
740 e27c88fe Gerd Hoffmann
            p++;
741 e27c88fe Gerd Hoffmann
            p = get_opt_value(value, sizeof(value), p);
742 e27c88fe Gerd Hoffmann
        }
743 e27c88fe Gerd Hoffmann
        if (strcmp(option, "id") != 0) {
744 e27c88fe Gerd Hoffmann
            /* store and parse */
745 3df04ac3 Mark McLoughlin
            if (qemu_opt_set(opts, option, value) == -1) {
746 96729cbd Gerd Hoffmann
                return -1;
747 e27c88fe Gerd Hoffmann
            }
748 e27c88fe Gerd Hoffmann
        }
749 e27c88fe Gerd Hoffmann
        if (*p != ',') {
750 e27c88fe Gerd Hoffmann
            break;
751 e27c88fe Gerd Hoffmann
        }
752 e27c88fe Gerd Hoffmann
    }
753 96729cbd Gerd Hoffmann
    return 0;
754 96729cbd Gerd Hoffmann
}
755 96729cbd Gerd Hoffmann
756 8212c64f Markus Armbruster
QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
757 8212c64f Markus Armbruster
                          int permit_abbrev)
758 96729cbd Gerd Hoffmann
{
759 8212c64f Markus Armbruster
    const char *firstname;
760 d318ff99 Gerd Hoffmann
    char value[1024], *id = NULL;
761 96729cbd Gerd Hoffmann
    const char *p;
762 96729cbd Gerd Hoffmann
    QemuOpts *opts;
763 96729cbd Gerd Hoffmann
764 8212c64f Markus Armbruster
    assert(!permit_abbrev || list->implied_opt_name);
765 8212c64f Markus Armbruster
    firstname = permit_abbrev ? list->implied_opt_name : NULL;
766 8212c64f Markus Armbruster
767 96729cbd Gerd Hoffmann
    if (strncmp(params, "id=", 3) == 0) {
768 96729cbd Gerd Hoffmann
        get_opt_value(value, sizeof(value), params+3);
769 96729cbd Gerd Hoffmann
        id = qemu_strdup(value);
770 96729cbd Gerd Hoffmann
    } else if ((p = strstr(params, ",id=")) != NULL) {
771 96729cbd Gerd Hoffmann
        get_opt_value(value, sizeof(value), p+4);
772 96729cbd Gerd Hoffmann
        id = qemu_strdup(value);
773 96729cbd Gerd Hoffmann
    }
774 96729cbd Gerd Hoffmann
    opts = qemu_opts_create(list, id, 1);
775 96729cbd Gerd Hoffmann
    if (opts == NULL)
776 96729cbd Gerd Hoffmann
        return NULL;
777 96729cbd Gerd Hoffmann
778 96729cbd Gerd Hoffmann
    if (qemu_opts_do_parse(opts, params, firstname) != 0) {
779 96729cbd Gerd Hoffmann
        qemu_opts_del(opts);
780 96729cbd Gerd Hoffmann
        return NULL;
781 96729cbd Gerd Hoffmann
    }
782 96729cbd Gerd Hoffmann
783 e27c88fe Gerd Hoffmann
    return opts;
784 e27c88fe Gerd Hoffmann
}
785 e27c88fe Gerd Hoffmann
786 01e7f188 Markus Armbruster
static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
787 01e7f188 Markus Armbruster
{
788 01e7f188 Markus Armbruster
    char buf[32];
789 01e7f188 Markus Armbruster
    const char *value;
790 01e7f188 Markus Armbruster
    int n;
791 01e7f188 Markus Armbruster
792 01e7f188 Markus Armbruster
    if (!strcmp(key, "id")) {
793 01e7f188 Markus Armbruster
        return;
794 01e7f188 Markus Armbruster
    }
795 01e7f188 Markus Armbruster
796 01e7f188 Markus Armbruster
    switch (qobject_type(obj)) {
797 01e7f188 Markus Armbruster
    case QTYPE_QSTRING:
798 01e7f188 Markus Armbruster
        value = qstring_get_str(qobject_to_qstring(obj));
799 01e7f188 Markus Armbruster
        break;
800 01e7f188 Markus Armbruster
    case QTYPE_QINT:
801 01e7f188 Markus Armbruster
        n = snprintf(buf, sizeof(buf), "%" PRId64,
802 01e7f188 Markus Armbruster
                     qint_get_int(qobject_to_qint(obj)));
803 01e7f188 Markus Armbruster
        assert(n < sizeof(buf));
804 01e7f188 Markus Armbruster
        value = buf;
805 01e7f188 Markus Armbruster
        break;
806 01e7f188 Markus Armbruster
    case QTYPE_QFLOAT:
807 01e7f188 Markus Armbruster
        n = snprintf(buf, sizeof(buf), "%.17g",
808 01e7f188 Markus Armbruster
                     qfloat_get_double(qobject_to_qfloat(obj)));
809 01e7f188 Markus Armbruster
        assert(n < sizeof(buf));
810 01e7f188 Markus Armbruster
        value = buf;
811 01e7f188 Markus Armbruster
        break;
812 01e7f188 Markus Armbruster
    case QTYPE_QBOOL:
813 d35215f8 Blue Swirl
        pstrcpy(buf, sizeof(buf),
814 d35215f8 Blue Swirl
                qbool_get_int(qobject_to_qbool(obj)) ? "on" : "off");
815 01e7f188 Markus Armbruster
        value = buf;
816 01e7f188 Markus Armbruster
        break;
817 01e7f188 Markus Armbruster
    default:
818 01e7f188 Markus Armbruster
        return;
819 01e7f188 Markus Armbruster
    }
820 01e7f188 Markus Armbruster
    qemu_opt_set(opaque, key, value);
821 01e7f188 Markus Armbruster
}
822 01e7f188 Markus Armbruster
823 01e7f188 Markus Armbruster
/*
824 01e7f188 Markus Armbruster
 * Create QemuOpts from a QDict.
825 01e7f188 Markus Armbruster
 * Use value of key "id" as ID if it exists and is a QString.
826 01e7f188 Markus Armbruster
 * Only QStrings, QInts, QFloats and QBools are copied.  Entries with
827 01e7f188 Markus Armbruster
 * other types are silently ignored.
828 01e7f188 Markus Armbruster
 */
829 01e7f188 Markus Armbruster
QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict)
830 01e7f188 Markus Armbruster
{
831 01e7f188 Markus Armbruster
    QemuOpts *opts;
832 01e7f188 Markus Armbruster
833 01e7f188 Markus Armbruster
    opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1);
834 01e7f188 Markus Armbruster
    if (opts == NULL)
835 01e7f188 Markus Armbruster
        return NULL;
836 01e7f188 Markus Armbruster
837 01e7f188 Markus Armbruster
    qdict_iter(qdict, qemu_opts_from_qdict_1, opts);
838 01e7f188 Markus Armbruster
    return opts;
839 01e7f188 Markus Armbruster
}
840 01e7f188 Markus Armbruster
841 01e7f188 Markus Armbruster
/*
842 01e7f188 Markus Armbruster
 * Convert from QemuOpts to QDict.
843 01e7f188 Markus Armbruster
 * The QDict values are of type QString.
844 01e7f188 Markus Armbruster
 * TODO We'll want to use types appropriate for opt->desc->type, but
845 01e7f188 Markus Armbruster
 * this is enough for now.
846 01e7f188 Markus Armbruster
 */
847 01e7f188 Markus Armbruster
QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
848 01e7f188 Markus Armbruster
{
849 01e7f188 Markus Armbruster
    QemuOpt *opt;
850 01e7f188 Markus Armbruster
    QObject *val;
851 01e7f188 Markus Armbruster
852 01e7f188 Markus Armbruster
    if (!qdict) {
853 01e7f188 Markus Armbruster
        qdict = qdict_new();
854 01e7f188 Markus Armbruster
    }
855 01e7f188 Markus Armbruster
    if (opts->id) {
856 01e7f188 Markus Armbruster
        qdict_put(qdict, "id", qstring_from_str(opts->id));
857 01e7f188 Markus Armbruster
    }
858 01e7f188 Markus Armbruster
    QTAILQ_FOREACH(opt, &opts->head, next) {
859 01e7f188 Markus Armbruster
        val = QOBJECT(qstring_from_str(opt->str));
860 01e7f188 Markus Armbruster
        qdict_put_obj(qdict, opt->name, val);
861 01e7f188 Markus Armbruster
    }
862 01e7f188 Markus Armbruster
    return qdict;
863 01e7f188 Markus Armbruster
}
864 01e7f188 Markus Armbruster
865 5dc519ef Mark McLoughlin
/* Validate parsed opts against descriptions where no
866 5dc519ef Mark McLoughlin
 * descriptions were provided in the QemuOptsList.
867 5dc519ef Mark McLoughlin
 */
868 238431a9 Blue Swirl
int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
869 5dc519ef Mark McLoughlin
{
870 5dc519ef Mark McLoughlin
    QemuOpt *opt;
871 5dc519ef Mark McLoughlin
872 5dc519ef Mark McLoughlin
    assert(opts->list->desc[0].name == NULL);
873 5dc519ef Mark McLoughlin
874 5dc519ef Mark McLoughlin
    QTAILQ_FOREACH(opt, &opts->head, next) {
875 5dc519ef Mark McLoughlin
        int i;
876 5dc519ef Mark McLoughlin
877 5dc519ef Mark McLoughlin
        for (i = 0; desc[i].name != NULL; i++) {
878 5dc519ef Mark McLoughlin
            if (strcmp(desc[i].name, opt->name) == 0) {
879 5dc519ef Mark McLoughlin
                break;
880 5dc519ef Mark McLoughlin
            }
881 5dc519ef Mark McLoughlin
        }
882 5dc519ef Mark McLoughlin
        if (desc[i].name == NULL) {
883 5dc519ef Mark McLoughlin
            fprintf(stderr, "option \"%s\" is not valid for %s\n",
884 5dc519ef Mark McLoughlin
                    opt->name, opts->list->name);
885 5dc519ef Mark McLoughlin
            return -1;
886 5dc519ef Mark McLoughlin
        }
887 5dc519ef Mark McLoughlin
888 5dc519ef Mark McLoughlin
        opt->desc = &desc[i];
889 5dc519ef Mark McLoughlin
890 5dc519ef Mark McLoughlin
        if (qemu_opt_parse(opt) < 0) {
891 5dc519ef Mark McLoughlin
            return -1;
892 5dc519ef Mark McLoughlin
        }
893 5dc519ef Mark McLoughlin
    }
894 5dc519ef Mark McLoughlin
895 5dc519ef Mark McLoughlin
    return 0;
896 5dc519ef Mark McLoughlin
}
897 5dc519ef Mark McLoughlin
898 e27c88fe Gerd Hoffmann
int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
899 e27c88fe Gerd Hoffmann
                      int abort_on_failure)
900 e27c88fe Gerd Hoffmann
{
901 827b0813 Markus Armbruster
    Location loc;
902 e27c88fe Gerd Hoffmann
    QemuOpts *opts;
903 e27c88fe Gerd Hoffmann
    int rc = 0;
904 e27c88fe Gerd Hoffmann
905 827b0813 Markus Armbruster
    loc_push_none(&loc);
906 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(opts, &list->head, next) {
907 827b0813 Markus Armbruster
        loc_restore(&opts->loc);
908 4a2594dd Markus Armbruster
        rc |= func(opts, opaque);
909 e27c88fe Gerd Hoffmann
        if (abort_on_failure  &&  rc != 0)
910 e27c88fe Gerd Hoffmann
            break;
911 e27c88fe Gerd Hoffmann
    }
912 827b0813 Markus Armbruster
    loc_pop(&loc);
913 e27c88fe Gerd Hoffmann
    return rc;
914 e27c88fe Gerd Hoffmann
}