Statistics
| Branch: | Revision:

root / qemu-option.c @ b09ea7d5

History | View | Annotate | Download (9.8 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 d3f24367 Kevin Wolf
#include "qemu-option.h"
31 d3f24367 Kevin Wolf
32 d3f24367 Kevin Wolf
/*
33 d3f24367 Kevin Wolf
 * Extracts the name of an option from the parameter string (p points at the
34 d3f24367 Kevin Wolf
 * first byte of the option name)
35 d3f24367 Kevin Wolf
 *
36 d3f24367 Kevin Wolf
 * The option name is delimited by delim (usually , or =) or the string end
37 d3f24367 Kevin Wolf
 * and is copied into buf. If the option name is longer than buf_size, it is
38 d3f24367 Kevin Wolf
 * truncated. buf is always zero terminated.
39 d3f24367 Kevin Wolf
 *
40 d3f24367 Kevin Wolf
 * The return value is the position of the delimiter/zero byte after the option
41 d3f24367 Kevin Wolf
 * name in p.
42 d3f24367 Kevin Wolf
 */
43 d3f24367 Kevin Wolf
const char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
44 d3f24367 Kevin Wolf
{
45 d3f24367 Kevin Wolf
    char *q;
46 d3f24367 Kevin Wolf
47 d3f24367 Kevin Wolf
    q = buf;
48 d3f24367 Kevin Wolf
    while (*p != '\0' && *p != delim) {
49 d3f24367 Kevin Wolf
        if (q && (q - buf) < buf_size - 1)
50 d3f24367 Kevin Wolf
            *q++ = *p;
51 d3f24367 Kevin Wolf
        p++;
52 d3f24367 Kevin Wolf
    }
53 d3f24367 Kevin Wolf
    if (q)
54 d3f24367 Kevin Wolf
        *q = '\0';
55 d3f24367 Kevin Wolf
56 d3f24367 Kevin Wolf
    return p;
57 d3f24367 Kevin Wolf
}
58 d3f24367 Kevin Wolf
59 d3f24367 Kevin Wolf
/*
60 d3f24367 Kevin Wolf
 * Extracts the value of an option from the parameter string p (p points at the
61 d3f24367 Kevin Wolf
 * first byte of the option value)
62 d3f24367 Kevin Wolf
 *
63 d3f24367 Kevin Wolf
 * This function is comparable to get_opt_name with the difference that the
64 d3f24367 Kevin Wolf
 * delimiter is fixed to be comma which starts a new option. To specify an
65 d3f24367 Kevin Wolf
 * option value that contains commas, double each comma.
66 d3f24367 Kevin Wolf
 */
67 d3f24367 Kevin Wolf
const char *get_opt_value(char *buf, int buf_size, const char *p)
68 d3f24367 Kevin Wolf
{
69 d3f24367 Kevin Wolf
    char *q;
70 d3f24367 Kevin Wolf
71 d3f24367 Kevin Wolf
    q = buf;
72 d3f24367 Kevin Wolf
    while (*p != '\0') {
73 d3f24367 Kevin Wolf
        if (*p == ',') {
74 d3f24367 Kevin Wolf
            if (*(p + 1) != ',')
75 d3f24367 Kevin Wolf
                break;
76 d3f24367 Kevin Wolf
            p++;
77 d3f24367 Kevin Wolf
        }
78 d3f24367 Kevin Wolf
        if (q && (q - buf) < buf_size - 1)
79 d3f24367 Kevin Wolf
            *q++ = *p;
80 d3f24367 Kevin Wolf
        p++;
81 d3f24367 Kevin Wolf
    }
82 d3f24367 Kevin Wolf
    if (q)
83 d3f24367 Kevin Wolf
        *q = '\0';
84 d3f24367 Kevin Wolf
85 d3f24367 Kevin Wolf
    return p;
86 d3f24367 Kevin Wolf
}
87 d3f24367 Kevin Wolf
88 d3f24367 Kevin Wolf
/*
89 d3f24367 Kevin Wolf
 * Searches an option list for an option with the given name
90 d3f24367 Kevin Wolf
 */
91 d3f24367 Kevin Wolf
QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list,
92 d3f24367 Kevin Wolf
    const char *name)
93 d3f24367 Kevin Wolf
{
94 d3f24367 Kevin Wolf
    while (list && list->name) {
95 d3f24367 Kevin Wolf
        if (!strcmp(list->name, name)) {
96 d3f24367 Kevin Wolf
            return list;
97 d3f24367 Kevin Wolf
        }
98 d3f24367 Kevin Wolf
        list++;
99 d3f24367 Kevin Wolf
    }
100 d3f24367 Kevin Wolf
101 d3f24367 Kevin Wolf
    return NULL;
102 d3f24367 Kevin Wolf
}
103 d3f24367 Kevin Wolf
104 d3f24367 Kevin Wolf
/*
105 d3f24367 Kevin Wolf
 * Sets the value of a parameter in a given option list. The parsing of the
106 d3f24367 Kevin Wolf
 * value depends on the type of option:
107 d3f24367 Kevin Wolf
 *
108 d3f24367 Kevin Wolf
 * OPT_FLAG (uses value.n):
109 d3f24367 Kevin Wolf
 *      If no value is given, the flag is set to 1.
110 d3f24367 Kevin Wolf
 *      Otherwise the value must be "on" (set to 1) or "off" (set to 0)
111 d3f24367 Kevin Wolf
 *
112 d3f24367 Kevin Wolf
 * OPT_STRING (uses value.s):
113 d3f24367 Kevin Wolf
 *      value is strdup()ed and assigned as option value
114 d3f24367 Kevin Wolf
 *
115 d3f24367 Kevin Wolf
 * OPT_SIZE (uses value.n):
116 d3f24367 Kevin Wolf
 *      The value is converted to an integer. Suffixes for kilobytes etc. are
117 d3f24367 Kevin Wolf
 *      allowed (powers of 1024).
118 d3f24367 Kevin Wolf
 *
119 d3f24367 Kevin Wolf
 * Returns 0 on succes, -1 in error cases
120 d3f24367 Kevin Wolf
 */
121 d3f24367 Kevin Wolf
int set_option_parameter(QEMUOptionParameter *list, const char *name,
122 d3f24367 Kevin Wolf
    const char *value)
123 d3f24367 Kevin Wolf
{
124 d3f24367 Kevin Wolf
    // Find a matching parameter
125 d3f24367 Kevin Wolf
    list = get_option_parameter(list, name);
126 d3f24367 Kevin Wolf
    if (list == NULL) {
127 d3f24367 Kevin Wolf
        fprintf(stderr, "Unknown option '%s'\n", name);
128 d3f24367 Kevin Wolf
        return -1;
129 d3f24367 Kevin Wolf
    }
130 d3f24367 Kevin Wolf
131 d3f24367 Kevin Wolf
    // Process parameter
132 d3f24367 Kevin Wolf
    switch (list->type) {
133 d3f24367 Kevin Wolf
    case OPT_FLAG:
134 d3f24367 Kevin Wolf
        if (value != NULL) {
135 d3f24367 Kevin Wolf
            if (!strcmp(value, "on")) {
136 d3f24367 Kevin Wolf
                list->value.n = 1;
137 d3f24367 Kevin Wolf
            } else if (!strcmp(value, "off")) {
138 d3f24367 Kevin Wolf
                list->value.n = 0;
139 d3f24367 Kevin Wolf
            } else {
140 d3f24367 Kevin Wolf
                fprintf(stderr, "Option '%s': Use 'on' or 'off'\n", name);
141 d3f24367 Kevin Wolf
                return -1;
142 d3f24367 Kevin Wolf
            }
143 d3f24367 Kevin Wolf
        } else {
144 d3f24367 Kevin Wolf
            list->value.n = 1;
145 d3f24367 Kevin Wolf
        }
146 d3f24367 Kevin Wolf
        break;
147 d3f24367 Kevin Wolf
148 d3f24367 Kevin Wolf
    case OPT_STRING:
149 d3f24367 Kevin Wolf
        if (value != NULL) {
150 d3f24367 Kevin Wolf
            list->value.s = strdup(value);
151 d3f24367 Kevin Wolf
        } else {
152 d3f24367 Kevin Wolf
            fprintf(stderr, "Option '%s' needs a parameter\n", name);
153 d3f24367 Kevin Wolf
            return -1;
154 d3f24367 Kevin Wolf
        }
155 d3f24367 Kevin Wolf
        break;
156 d3f24367 Kevin Wolf
157 d3f24367 Kevin Wolf
    case OPT_SIZE:
158 d3f24367 Kevin Wolf
        if (value != NULL) {
159 d3f24367 Kevin Wolf
            double sizef = strtod(value, (char**) &value);
160 d3f24367 Kevin Wolf
161 d3f24367 Kevin Wolf
            switch (*value) {
162 d3f24367 Kevin Wolf
            case 'T':
163 d3f24367 Kevin Wolf
                sizef *= 1024;
164 d3f24367 Kevin Wolf
            case 'G':
165 d3f24367 Kevin Wolf
                sizef *= 1024;
166 d3f24367 Kevin Wolf
            case 'M':
167 d3f24367 Kevin Wolf
                sizef *= 1024;
168 d3f24367 Kevin Wolf
            case 'K':
169 d3f24367 Kevin Wolf
            case 'k':
170 d3f24367 Kevin Wolf
                sizef *= 1024;
171 d3f24367 Kevin Wolf
            case 'b':
172 d3f24367 Kevin Wolf
            case '\0':
173 d3f24367 Kevin Wolf
                list->value.n = (uint64_t) sizef;
174 d3f24367 Kevin Wolf
                break;
175 d3f24367 Kevin Wolf
            default:
176 d3f24367 Kevin Wolf
                fprintf(stderr, "Option '%s' needs size as parameter\n", name);
177 d3f24367 Kevin Wolf
                fprintf(stderr, "You may use k, M, G or T suffixes for "
178 d3f24367 Kevin Wolf
                    "kilobytes, megabytes, gigabytes and terabytes.\n");
179 d3f24367 Kevin Wolf
                return -1;
180 d3f24367 Kevin Wolf
            }
181 d3f24367 Kevin Wolf
        } else {
182 d3f24367 Kevin Wolf
            fprintf(stderr, "Option '%s' needs a parameter\n", name);
183 d3f24367 Kevin Wolf
            return -1;
184 d3f24367 Kevin Wolf
        }
185 d3f24367 Kevin Wolf
        break;
186 d3f24367 Kevin Wolf
    default:
187 d3f24367 Kevin Wolf
        fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name);
188 d3f24367 Kevin Wolf
        return -1;
189 d3f24367 Kevin Wolf
    }
190 d3f24367 Kevin Wolf
191 d3f24367 Kevin Wolf
    return 0;
192 d3f24367 Kevin Wolf
}
193 d3f24367 Kevin Wolf
194 d3f24367 Kevin Wolf
/*
195 d3f24367 Kevin Wolf
 * Sets the given parameter to an integer instead of a string.
196 d3f24367 Kevin Wolf
 * This function cannot be used to set string options.
197 d3f24367 Kevin Wolf
 *
198 d3f24367 Kevin Wolf
 * Returns 0 on success, -1 in error cases
199 d3f24367 Kevin Wolf
 */
200 d3f24367 Kevin Wolf
int set_option_parameter_int(QEMUOptionParameter *list, const char *name,
201 d3f24367 Kevin Wolf
    uint64_t value)
202 d3f24367 Kevin Wolf
{
203 d3f24367 Kevin Wolf
    // Find a matching parameter
204 d3f24367 Kevin Wolf
    list = get_option_parameter(list, name);
205 d3f24367 Kevin Wolf
    if (list == NULL) {
206 d3f24367 Kevin Wolf
        fprintf(stderr, "Unknown option '%s'\n", name);
207 d3f24367 Kevin Wolf
        return -1;
208 d3f24367 Kevin Wolf
    }
209 d3f24367 Kevin Wolf
210 d3f24367 Kevin Wolf
    // Process parameter
211 d3f24367 Kevin Wolf
    switch (list->type) {
212 d3f24367 Kevin Wolf
    case OPT_FLAG:
213 d3f24367 Kevin Wolf
    case OPT_NUMBER:
214 d3f24367 Kevin Wolf
    case OPT_SIZE:
215 d3f24367 Kevin Wolf
        list->value.n = value;
216 d3f24367 Kevin Wolf
        break;
217 d3f24367 Kevin Wolf
218 d3f24367 Kevin Wolf
    default:
219 d3f24367 Kevin Wolf
        return -1;
220 d3f24367 Kevin Wolf
    }
221 d3f24367 Kevin Wolf
222 d3f24367 Kevin Wolf
    return 0;
223 d3f24367 Kevin Wolf
}
224 d3f24367 Kevin Wolf
225 d3f24367 Kevin Wolf
/*
226 d3f24367 Kevin Wolf
 * Frees a option list. If it contains strings, the strings are freed as well.
227 d3f24367 Kevin Wolf
 */
228 d3f24367 Kevin Wolf
void free_option_parameters(QEMUOptionParameter *list)
229 d3f24367 Kevin Wolf
{
230 d3f24367 Kevin Wolf
    QEMUOptionParameter *cur = list;
231 d3f24367 Kevin Wolf
232 d3f24367 Kevin Wolf
    while (cur && cur->name) {
233 d3f24367 Kevin Wolf
        if (cur->type == OPT_STRING) {
234 d3f24367 Kevin Wolf
            free(cur->value.s);
235 d3f24367 Kevin Wolf
        }
236 d3f24367 Kevin Wolf
        cur++;
237 d3f24367 Kevin Wolf
    }
238 d3f24367 Kevin Wolf
239 d3f24367 Kevin Wolf
    free(list);
240 d3f24367 Kevin Wolf
}
241 d3f24367 Kevin Wolf
242 d3f24367 Kevin Wolf
/*
243 d3f24367 Kevin Wolf
 * Parses a parameter string (param) into an option list (dest).
244 d3f24367 Kevin Wolf
 *
245 d3f24367 Kevin Wolf
 * list is the templace is. If dest is NULL, a new copy of list is created for
246 d3f24367 Kevin Wolf
 * it. If list is NULL, this function fails.
247 d3f24367 Kevin Wolf
 *
248 d3f24367 Kevin Wolf
 * A parameter string consists of one or more parameters, separated by commas.
249 d3f24367 Kevin Wolf
 * Each parameter consists of its name and possibly of a value. In the latter
250 d3f24367 Kevin Wolf
 * case, the value is delimited by an = character. To specify a value which
251 d3f24367 Kevin Wolf
 * contains commas, double each comma so it won't be recognized as the end of
252 d3f24367 Kevin Wolf
 * the parameter.
253 d3f24367 Kevin Wolf
 *
254 d3f24367 Kevin Wolf
 * For more details of the parsing see above.
255 d3f24367 Kevin Wolf
 *
256 d3f24367 Kevin Wolf
 * Returns a pointer to the first element of dest (or the newly allocated copy)
257 d3f24367 Kevin Wolf
 * or NULL in error cases
258 d3f24367 Kevin Wolf
 */
259 d3f24367 Kevin Wolf
QEMUOptionParameter *parse_option_parameters(const char *param,
260 d3f24367 Kevin Wolf
    QEMUOptionParameter *list, QEMUOptionParameter *dest)
261 d3f24367 Kevin Wolf
{
262 d3f24367 Kevin Wolf
    QEMUOptionParameter *cur;
263 d3f24367 Kevin Wolf
    QEMUOptionParameter *allocated = NULL;
264 d3f24367 Kevin Wolf
    char name[256];
265 d3f24367 Kevin Wolf
    char value[256];
266 d3f24367 Kevin Wolf
    char *param_delim, *value_delim;
267 d3f24367 Kevin Wolf
    char next_delim;
268 d3f24367 Kevin Wolf
    size_t num_options;
269 d3f24367 Kevin Wolf
270 d3f24367 Kevin Wolf
    if (list == NULL) {
271 d3f24367 Kevin Wolf
        return NULL;
272 d3f24367 Kevin Wolf
    }
273 d3f24367 Kevin Wolf
274 d3f24367 Kevin Wolf
    if (dest == NULL) {
275 d3f24367 Kevin Wolf
        // Count valid options
276 d3f24367 Kevin Wolf
        num_options = 0;
277 d3f24367 Kevin Wolf
        cur = list;
278 d3f24367 Kevin Wolf
        while (cur->name) {
279 d3f24367 Kevin Wolf
            num_options++;
280 d3f24367 Kevin Wolf
            cur++;
281 d3f24367 Kevin Wolf
        }
282 d3f24367 Kevin Wolf
283 d3f24367 Kevin Wolf
        // Create a copy of the option list to fill in values
284 d3f24367 Kevin Wolf
        dest = qemu_mallocz((num_options + 1) * sizeof(QEMUOptionParameter));
285 d3f24367 Kevin Wolf
        allocated = dest;
286 d3f24367 Kevin Wolf
        memcpy(dest, list, (num_options + 1) * sizeof(QEMUOptionParameter));
287 d3f24367 Kevin Wolf
    }
288 d3f24367 Kevin Wolf
289 d3f24367 Kevin Wolf
    while (*param) {
290 d3f24367 Kevin Wolf
291 d3f24367 Kevin Wolf
        // Find parameter name and value in the string
292 d3f24367 Kevin Wolf
        param_delim = strchr(param, ',');
293 d3f24367 Kevin Wolf
        value_delim = strchr(param, '=');
294 d3f24367 Kevin Wolf
295 d3f24367 Kevin Wolf
        if (value_delim && (value_delim < param_delim || !param_delim)) {
296 d3f24367 Kevin Wolf
            next_delim = '=';
297 d3f24367 Kevin Wolf
        } else {
298 d3f24367 Kevin Wolf
            next_delim = ',';
299 d3f24367 Kevin Wolf
            value_delim = NULL;
300 d3f24367 Kevin Wolf
        }
301 d3f24367 Kevin Wolf
302 d3f24367 Kevin Wolf
        param = get_opt_name(name, sizeof(name), param, next_delim);
303 d3f24367 Kevin Wolf
        if (value_delim) {
304 d3f24367 Kevin Wolf
            param = get_opt_value(value, sizeof(value), param + 1);
305 d3f24367 Kevin Wolf
        }
306 d3f24367 Kevin Wolf
        if (*param != '\0') {
307 d3f24367 Kevin Wolf
            param++;
308 d3f24367 Kevin Wolf
        }
309 d3f24367 Kevin Wolf
310 d3f24367 Kevin Wolf
        // Set the parameter
311 d3f24367 Kevin Wolf
        if (set_option_parameter(dest, name, value_delim ? value : NULL)) {
312 d3f24367 Kevin Wolf
            goto fail;
313 d3f24367 Kevin Wolf
        }
314 d3f24367 Kevin Wolf
    }
315 d3f24367 Kevin Wolf
316 d3f24367 Kevin Wolf
    return dest;
317 d3f24367 Kevin Wolf
318 d3f24367 Kevin Wolf
fail:
319 d3f24367 Kevin Wolf
    // Only free the list if it was newly allocated
320 d3f24367 Kevin Wolf
    free_option_parameters(allocated);
321 d3f24367 Kevin Wolf
    return NULL;
322 d3f24367 Kevin Wolf
}
323 d3f24367 Kevin Wolf
324 d3f24367 Kevin Wolf
/*
325 d3f24367 Kevin Wolf
 * Prints all options of a list that have a value to stdout
326 d3f24367 Kevin Wolf
 */
327 d3f24367 Kevin Wolf
void print_option_parameters(QEMUOptionParameter *list)
328 d3f24367 Kevin Wolf
{
329 d3f24367 Kevin Wolf
    while (list && list->name) {
330 d3f24367 Kevin Wolf
        switch (list->type) {
331 d3f24367 Kevin Wolf
            case OPT_STRING:
332 d3f24367 Kevin Wolf
                 if (list->value.s != NULL) {
333 d3f24367 Kevin Wolf
                     printf("%s='%s' ", list->name, list->value.s);
334 d3f24367 Kevin Wolf
                 }
335 d3f24367 Kevin Wolf
                break;
336 d3f24367 Kevin Wolf
            case OPT_FLAG:
337 d3f24367 Kevin Wolf
                printf("%s=%s ", list->name, list->value.n ? "on" : "off");
338 d3f24367 Kevin Wolf
                break;
339 d3f24367 Kevin Wolf
            case OPT_SIZE:
340 d3f24367 Kevin Wolf
            case OPT_NUMBER:
341 d3f24367 Kevin Wolf
                printf("%s=%" PRId64 " ", list->name, list->value.n);
342 d3f24367 Kevin Wolf
                break;
343 d3f24367 Kevin Wolf
            default:
344 d3f24367 Kevin Wolf
                printf("%s=(unkown type) ", list->name);
345 d3f24367 Kevin Wolf
                break;
346 d3f24367 Kevin Wolf
        }
347 d3f24367 Kevin Wolf
        list++;
348 d3f24367 Kevin Wolf
    }
349 d3f24367 Kevin Wolf
}
350 db08adf5 Kevin Wolf
351 db08adf5 Kevin Wolf
/*
352 db08adf5 Kevin Wolf
 * Prints an overview of all available options
353 db08adf5 Kevin Wolf
 */
354 db08adf5 Kevin Wolf
void print_option_help(QEMUOptionParameter *list)
355 db08adf5 Kevin Wolf
{
356 db08adf5 Kevin Wolf
    printf("Supported options:\n");
357 db08adf5 Kevin Wolf
    while (list && list->name) {
358 db08adf5 Kevin Wolf
        printf("%-16s %s\n", list->name,
359 db08adf5 Kevin Wolf
            list->help ? list->help : "No description available");
360 db08adf5 Kevin Wolf
        list++;
361 db08adf5 Kevin Wolf
    }
362 db08adf5 Kevin Wolf
}