]> git.proxmox.com Git - mirror_qemu.git/blame - qemu-option.c
qemu-option: factor out parse_option_size
[mirror_qemu.git] / qemu-option.c
CommitLineData
d3f24367
KW
1/*
2 * Commandline option parsing functions
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 * Copyright (c) 2009 Kevin Wolf <kwolf@redhat.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26#include <stdio.h>
27#include <string.h>
28
29#include "qemu-common.h"
30#include "qemu-option.h"
31
32/*
33 * Extracts the name of an option from the parameter string (p points at the
34 * first byte of the option name)
35 *
36 * The option name is delimited by delim (usually , or =) or the string end
37 * and is copied into buf. If the option name is longer than buf_size, it is
38 * truncated. buf is always zero terminated.
39 *
40 * The return value is the position of the delimiter/zero byte after the option
41 * name in p.
42 */
43const char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
44{
45 char *q;
46
47 q = buf;
48 while (*p != '\0' && *p != delim) {
49 if (q && (q - buf) < buf_size - 1)
50 *q++ = *p;
51 p++;
52 }
53 if (q)
54 *q = '\0';
55
56 return p;
57}
58
59/*
60 * Extracts the value of an option from the parameter string p (p points at the
61 * first byte of the option value)
62 *
63 * This function is comparable to get_opt_name with the difference that the
64 * delimiter is fixed to be comma which starts a new option. To specify an
65 * option value that contains commas, double each comma.
66 */
67const char *get_opt_value(char *buf, int buf_size, const char *p)
68{
69 char *q;
70
71 q = buf;
72 while (*p != '\0') {
73 if (*p == ',') {
74 if (*(p + 1) != ',')
75 break;
76 p++;
77 }
78 if (q && (q - buf) < buf_size - 1)
79 *q++ = *p;
80 p++;
81 }
82 if (q)
83 *q = '\0';
84
85 return p;
86}
87
62c5802e
GH
88int get_next_param_value(char *buf, int buf_size,
89 const char *tag, const char **pstr)
90{
91 const char *p;
92 char option[128];
93
94 p = *pstr;
95 for(;;) {
96 p = get_opt_name(option, sizeof(option), p, '=');
97 if (*p != '=')
98 break;
99 p++;
100 if (!strcmp(tag, option)) {
101 *pstr = get_opt_value(buf, buf_size, p);
102 if (**pstr == ',') {
103 (*pstr)++;
104 }
105 return strlen(buf);
106 } else {
107 p = get_opt_value(NULL, 0, p);
108 }
109 if (*p != ',')
110 break;
111 p++;
112 }
113 return 0;
114}
115
116int get_param_value(char *buf, int buf_size,
117 const char *tag, const char *str)
118{
119 return get_next_param_value(buf, buf_size, tag, &str);
120}
121
122int check_params(char *buf, int buf_size,
123 const char * const *params, const char *str)
124{
125 const char *p;
126 int i;
127
128 p = str;
129 while (*p != '\0') {
130 p = get_opt_name(buf, buf_size, p, '=');
131 if (*p != '=') {
132 return -1;
133 }
134 p++;
135 for (i = 0; params[i] != NULL; i++) {
136 if (!strcmp(params[i], buf)) {
137 break;
138 }
139 }
140 if (params[i] == NULL) {
141 return -1;
142 }
143 p = get_opt_value(NULL, 0, p);
144 if (*p != ',') {
145 break;
146 }
147 p++;
148 }
149 return 0;
150}
151
d3f24367
KW
152/*
153 * Searches an option list for an option with the given name
154 */
155QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list,
156 const char *name)
157{
158 while (list && list->name) {
159 if (!strcmp(list->name, name)) {
160 return list;
161 }
162 list++;
163 }
164
165 return NULL;
166}
167
67b1355b
GH
168static int parse_option_bool(const char *name, const char *value, int *ret)
169{
170 if (value != NULL) {
171 if (!strcmp(value, "on")) {
172 *ret = 1;
173 } else if (!strcmp(value, "off")) {
174 *ret = 0;
175 } else {
176 fprintf(stderr, "Option '%s': Use 'on' or 'off'\n", name);
177 return -1;
178 }
179 } else {
180 *ret = 1;
181 }
182 return 0;
183}
184
7695019b
GH
185static int parse_option_size(const char *name, const char *value, uint64_t *ret)
186{
187 char *postfix;
188 double sizef;
189
190 if (value != NULL) {
191 sizef = strtod(value, &postfix);
192 switch (*postfix) {
193 case 'T':
194 sizef *= 1024;
195 case 'G':
196 sizef *= 1024;
197 case 'M':
198 sizef *= 1024;
199 case 'K':
200 case 'k':
201 sizef *= 1024;
202 case 'b':
203 case '\0':
204 *ret = (uint64_t) sizef;
205 break;
206 default:
207 fprintf(stderr, "Option '%s' needs size as parameter\n", name);
208 fprintf(stderr, "You may use k, M, G or T suffixes for "
209 "kilobytes, megabytes, gigabytes and terabytes.\n");
210 return -1;
211 }
212 } else {
213 fprintf(stderr, "Option '%s' needs a parameter\n", name);
214 return -1;
215 }
216 return 0;
217}
218
d3f24367
KW
219/*
220 * Sets the value of a parameter in a given option list. The parsing of the
221 * value depends on the type of option:
222 *
223 * OPT_FLAG (uses value.n):
224 * If no value is given, the flag is set to 1.
225 * Otherwise the value must be "on" (set to 1) or "off" (set to 0)
226 *
227 * OPT_STRING (uses value.s):
228 * value is strdup()ed and assigned as option value
229 *
230 * OPT_SIZE (uses value.n):
231 * The value is converted to an integer. Suffixes for kilobytes etc. are
232 * allowed (powers of 1024).
233 *
234 * Returns 0 on succes, -1 in error cases
235 */
236int set_option_parameter(QEMUOptionParameter *list, const char *name,
237 const char *value)
238{
67b1355b
GH
239 int flag;
240
d3f24367
KW
241 // Find a matching parameter
242 list = get_option_parameter(list, name);
243 if (list == NULL) {
244 fprintf(stderr, "Unknown option '%s'\n", name);
245 return -1;
246 }
247
248 // Process parameter
249 switch (list->type) {
250 case OPT_FLAG:
67b1355b
GH
251 if (-1 == parse_option_bool(name, value, &flag))
252 return -1;
253 list->value.n = flag;
d3f24367
KW
254 break;
255
256 case OPT_STRING:
257 if (value != NULL) {
258 list->value.s = strdup(value);
259 } else {
260 fprintf(stderr, "Option '%s' needs a parameter\n", name);
261 return -1;
262 }
263 break;
264
265 case OPT_SIZE:
7695019b 266 if (-1 == parse_option_size(name, value, &list->value.n))
d3f24367 267 return -1;
d3f24367 268 break;
7695019b 269
d3f24367
KW
270 default:
271 fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name);
272 return -1;
273 }
274
275 return 0;
276}
277
278/*
279 * Sets the given parameter to an integer instead of a string.
280 * This function cannot be used to set string options.
281 *
282 * Returns 0 on success, -1 in error cases
283 */
284int set_option_parameter_int(QEMUOptionParameter *list, const char *name,
285 uint64_t value)
286{
287 // Find a matching parameter
288 list = get_option_parameter(list, name);
289 if (list == NULL) {
290 fprintf(stderr, "Unknown option '%s'\n", name);
291 return -1;
292 }
293
294 // Process parameter
295 switch (list->type) {
296 case OPT_FLAG:
297 case OPT_NUMBER:
298 case OPT_SIZE:
299 list->value.n = value;
300 break;
301
302 default:
303 return -1;
304 }
305
306 return 0;
307}
308
309/*
310 * Frees a option list. If it contains strings, the strings are freed as well.
311 */
312void free_option_parameters(QEMUOptionParameter *list)
313{
314 QEMUOptionParameter *cur = list;
315
316 while (cur && cur->name) {
317 if (cur->type == OPT_STRING) {
318 free(cur->value.s);
319 }
320 cur++;
321 }
322
323 free(list);
324}
325
326/*
327 * Parses a parameter string (param) into an option list (dest).
328 *
329 * list is the templace is. If dest is NULL, a new copy of list is created for
330 * it. If list is NULL, this function fails.
331 *
332 * A parameter string consists of one or more parameters, separated by commas.
333 * Each parameter consists of its name and possibly of a value. In the latter
334 * case, the value is delimited by an = character. To specify a value which
335 * contains commas, double each comma so it won't be recognized as the end of
336 * the parameter.
337 *
338 * For more details of the parsing see above.
339 *
340 * Returns a pointer to the first element of dest (or the newly allocated copy)
341 * or NULL in error cases
342 */
343QEMUOptionParameter *parse_option_parameters(const char *param,
344 QEMUOptionParameter *list, QEMUOptionParameter *dest)
345{
346 QEMUOptionParameter *cur;
347 QEMUOptionParameter *allocated = NULL;
348 char name[256];
349 char value[256];
350 char *param_delim, *value_delim;
351 char next_delim;
352 size_t num_options;
353
354 if (list == NULL) {
355 return NULL;
356 }
357
358 if (dest == NULL) {
359 // Count valid options
360 num_options = 0;
361 cur = list;
362 while (cur->name) {
363 num_options++;
364 cur++;
365 }
366
367 // Create a copy of the option list to fill in values
368 dest = qemu_mallocz((num_options + 1) * sizeof(QEMUOptionParameter));
369 allocated = dest;
370 memcpy(dest, list, (num_options + 1) * sizeof(QEMUOptionParameter));
371 }
372
373 while (*param) {
374
375 // Find parameter name and value in the string
376 param_delim = strchr(param, ',');
377 value_delim = strchr(param, '=');
378
379 if (value_delim && (value_delim < param_delim || !param_delim)) {
380 next_delim = '=';
381 } else {
382 next_delim = ',';
383 value_delim = NULL;
384 }
385
386 param = get_opt_name(name, sizeof(name), param, next_delim);
387 if (value_delim) {
388 param = get_opt_value(value, sizeof(value), param + 1);
389 }
390 if (*param != '\0') {
391 param++;
392 }
393
394 // Set the parameter
395 if (set_option_parameter(dest, name, value_delim ? value : NULL)) {
396 goto fail;
397 }
398 }
399
400 return dest;
401
402fail:
403 // Only free the list if it was newly allocated
404 free_option_parameters(allocated);
405 return NULL;
406}
407
408/*
409 * Prints all options of a list that have a value to stdout
410 */
411void print_option_parameters(QEMUOptionParameter *list)
412{
413 while (list && list->name) {
414 switch (list->type) {
415 case OPT_STRING:
416 if (list->value.s != NULL) {
417 printf("%s='%s' ", list->name, list->value.s);
418 }
419 break;
420 case OPT_FLAG:
421 printf("%s=%s ", list->name, list->value.n ? "on" : "off");
422 break;
423 case OPT_SIZE:
424 case OPT_NUMBER:
425 printf("%s=%" PRId64 " ", list->name, list->value.n);
426 break;
427 default:
428 printf("%s=(unkown type) ", list->name);
429 break;
430 }
431 list++;
432 }
433}
db08adf5
KW
434
435/*
436 * Prints an overview of all available options
437 */
438void print_option_help(QEMUOptionParameter *list)
439{
440 printf("Supported options:\n");
441 while (list && list->name) {
442 printf("%-16s %s\n", list->name,
443 list->help ? list->help : "No description available");
444 list++;
445 }
446}