15d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
25d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Commandline option parsing functions
35d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
45d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Copyright (c) 2003-2008 Fabrice Bellard
55d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Copyright (c) 2009 Kevin Wolf <kwolf@redhat.com>
65d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
75d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Permission is hereby granted, free of charge, to any person obtaining a copy
85d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * of this software and associated documentation files (the "Software"), to deal
95d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * in the Software without restriction, including without limitation the rights
105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * copies of the Software, and to permit persons to whom the Software is
125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * furnished to do so, subject to the following conditions:
135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * The above copyright notice and this permission notice shall be included in
155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * all copies or substantial portions of the Software.
165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * THE SOFTWARE.
245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <stdio.h>
275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <string.h>
285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h"
301c31e3e43ce4cca85a707dfff631e5e102fdecedDavid 'Digit' Turner#include "qemu/error-report.h"
312a7dde0b2f96b05048320a0840cde7ab3d4be9feDavid 'Digit' Turner#include "qapi/qmp/types.h"
3293e0d9cfb6d950b638ba93cf5318e5689e4ba64eDavid 'Digit' Turner#include "qemu/option.h"
331c31e3e43ce4cca85a707dfff631e5e102fdecedDavid 'Digit' Turner#include "qapi/qmp/qerror.h"
345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Extracts the name of an option from the parameter string (p points at the
375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * first byte of the option name)
385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * The option name is delimited by delim (usually , or =) or the string end
405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * and is copied into buf. If the option name is longer than buf_size, it is
415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * truncated. buf is always zero terminated.
425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * The return value is the position of the delimiter/zero byte after the option
445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * name in p.
455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerconst char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char *q;
495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    q = buf;
515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (*p != '\0' && *p != delim) {
525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (q && (q - buf) < buf_size - 1)
535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *q++ = *p;
545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        p++;
555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (q)
575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *q = '\0';
585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return p;
605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Extracts the value of an option from the parameter string p (p points at the
645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * first byte of the option value)
655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * This function is comparable to get_opt_name with the difference that the
675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * delimiter is fixed to be comma which starts a new option. To specify an
685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * option value that contains commas, double each comma.
695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerconst char *get_opt_value(char *buf, int buf_size, const char *p)
715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char *q;
735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    q = buf;
755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (*p != '\0') {
765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (*p == ',') {
775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (*(p + 1) != ',')
785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            p++;
805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (q && (q - buf) < buf_size - 1)
825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *q++ = *p;
835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        p++;
845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (q)
865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *q = '\0';
875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return p;
895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
912910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerint get_next_param_value(char *buf, int buf_size,
922910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                         const char *tag, const char **pstr)
932910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
942910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    const char *p;
952910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    char option[128];
962910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
972910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    p = *pstr;
982910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    for(;;) {
992910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        p = get_opt_name(option, sizeof(option), p, '=');
1002910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (*p != '=')
1012910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            break;
1022910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        p++;
1032910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (!strcmp(tag, option)) {
1042910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            *pstr = get_opt_value(buf, buf_size, p);
1052910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            if (**pstr == ',') {
1062910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                (*pstr)++;
1072910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            }
1082910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            return strlen(buf);
1092910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        } else {
1102910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            p = get_opt_value(NULL, 0, p);
1112910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
1122910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (*p != ',')
1132910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            break;
1142910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        p++;
1152910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
1162910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return 0;
1172910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
1182910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
1192910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerint get_param_value(char *buf, int buf_size,
1202910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    const char *tag, const char *str)
1212910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
1222910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return get_next_param_value(buf, buf_size, tag, &str);
1232910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
1242910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
1252910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerint check_params(char *buf, int buf_size,
1262910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                 const char * const *params, const char *str)
1272910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
1282910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    const char *p;
1292910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    int i;
1302910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
1312910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    p = str;
1322910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    while (*p != '\0') {
1332910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        p = get_opt_name(buf, buf_size, p, '=');
1342910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (*p != '=') {
1352910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            return -1;
1362910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
1372910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        p++;
1382910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        for (i = 0; params[i] != NULL; i++) {
1392910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            if (!strcmp(params[i], buf)) {
1402910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                break;
1412910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            }
1422910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
1432910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (params[i] == NULL) {
1442910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            return -1;
1452910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
1462910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        p = get_opt_value(NULL, 0, p);
1472910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (*p != ',') {
1482910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            break;
1492910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
1502910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        p++;
1512910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
1522910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return 0;
1532910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
1542910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Searches an option list for an option with the given name
1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerQEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list,
1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    const char *name)
1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (list && list->name) {
1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!strcmp(list->name, name)) {
1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return list;
1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        list++;
1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
1675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return NULL;
1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1712910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerstatic int parse_option_bool(const char *name, const char *value, int *ret)
1722910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
1732abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    if (value != NULL) {
1742abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        if (!strcmp(value, "on")) {
1752910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            *ret = 1;
1762abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        } else if (!strcmp(value, "off")) {
1772910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            *ret = 0;
1782910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        } else {
1792abe02c0511b2278af9386e7ac5e266d890a38b1David Turner            qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "'on' or 'off'");
1802abe02c0511b2278af9386e7ac5e266d890a38b1David Turner            return -1;
1812abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        }
1822abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    } else {
1832910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        *ret = 1;
1842910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
1852910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return 0;
1862910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
1872910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
1882910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerstatic int parse_option_number(const char *name, const char *value, uint64_t *ret)
1892910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
1902910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    char *postfix;
1912910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    uint64_t number;
1922910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
1932abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    if (value != NULL) {
1942910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        number = strtoull(value, &postfix, 0);
1952910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (*postfix != '\0') {
1962abe02c0511b2278af9386e7ac5e266d890a38b1David Turner            qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number");
1972910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            return -1;
1982910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
1992910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        *ret = number;
2002abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    } else {
2012abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number");
2022abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        return -1;
2032abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    }
2042910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return 0;
2052910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
2062910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
2072910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerstatic int parse_option_size(const char *name, const char *value, uint64_t *ret)
2082910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
2092910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    char *postfix;
2102910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    double sizef;
2112910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
2122abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    if (value != NULL) {
2132910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        sizef = strtod(value, &postfix);
2142910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        switch (*postfix) {
2152abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        case 'T':
2162abe02c0511b2278af9386e7ac5e266d890a38b1David Turner            sizef *= 1024;
2172abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        case 'G':
2182abe02c0511b2278af9386e7ac5e266d890a38b1David Turner            sizef *= 1024;
2192abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        case 'M':
2202abe02c0511b2278af9386e7ac5e266d890a38b1David Turner            sizef *= 1024;
2212abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        case 'K':
2222abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        case 'k':
2232abe02c0511b2278af9386e7ac5e266d890a38b1David Turner            sizef *= 1024;
2242abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        case 'b':
2252abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        case '\0':
2262910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            *ret = (uint64_t) sizef;
2272abe02c0511b2278af9386e7ac5e266d890a38b1David Turner            break;
2282abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        default:
2292abe02c0511b2278af9386e7ac5e266d890a38b1David Turner            qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
2302abe02c0511b2278af9386e7ac5e266d890a38b1David Turner            error_printf_unless_qmp("You may use k, M, G or T suffixes for "
2312910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    "kilobytes, megabytes, gigabytes and terabytes.\n");
2322910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            return -1;
2332910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
2342abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    } else {
2352abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
2362abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        return -1;
2372abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    }
2382910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return 0;
2392910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
2402910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
2415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
2425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Sets the value of a parameter in a given option list. The parsing of the
2435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * value depends on the type of option:
2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
2455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * OPT_FLAG (uses value.n):
2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *      If no value is given, the flag is set to 1.
2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *      Otherwise the value must be "on" (set to 1) or "off" (set to 0)
2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * OPT_STRING (uses value.s):
2505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *      value is strdup()ed and assigned as option value
2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * OPT_SIZE (uses value.n):
2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *      The value is converted to an integer. Suffixes for kilobytes etc. are
2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *      allowed (powers of 1024).
2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Returns 0 on succes, -1 in error cases
2575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
2585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint set_option_parameter(QEMUOptionParameter *list, const char *name,
2595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    const char *value)
2605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2612910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    int flag;
2622910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
2635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    // Find a matching parameter
2645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    list = get_option_parameter(list, name);
2655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (list == NULL) {
2665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "Unknown option '%s'\n", name);
2675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -1;
2685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
2695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    // Process parameter
2715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    switch (list->type) {
2725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case OPT_FLAG:
2732910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (parse_option_bool(name, value, &flag) == -1)
2742910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            return -1;
2752910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        list->value.n = flag;
2765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
2775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case OPT_STRING:
2795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (value != NULL) {
280aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner            list->value.s = g_strdup(value);
2815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
2825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            fprintf(stderr, "Option '%s' needs a parameter\n", name);
2835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return -1;
2845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
2855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
2865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case OPT_SIZE:
2882910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (parse_option_size(name, value, &list->value.n) == -1)
2895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return -1;
2905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
2912910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
2925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    default:
2935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name);
2945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -1;
2955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
2965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
2985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
3015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Sets the given parameter to an integer instead of a string.
3025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * This function cannot be used to set string options.
3035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
3045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Returns 0 on success, -1 in error cases
3055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
3065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint set_option_parameter_int(QEMUOptionParameter *list, const char *name,
3075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint64_t value)
3085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
3095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    // Find a matching parameter
3105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    list = get_option_parameter(list, name);
3115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (list == NULL) {
3125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "Unknown option '%s'\n", name);
3135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -1;
3145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
3155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    // Process parameter
3175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    switch (list->type) {
3185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case OPT_FLAG:
3195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case OPT_NUMBER:
3205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case OPT_SIZE:
3215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        list->value.n = value;
3225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
3235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    default:
3255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -1;
3265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
3275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
3325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Frees a option list. If it contains strings, the strings are freed as well.
3335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
3345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid free_option_parameters(QEMUOptionParameter *list)
3355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
3365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUOptionParameter *cur = list;
3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (cur && cur->name) {
3395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (cur->type == OPT_STRING) {
340aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner            g_free(cur->value.s);
3415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
3425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        cur++;
3435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
3445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
345aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(list);
3465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
3492abe02c0511b2278af9386e7ac5e266d890a38b1David Turner * Count valid options in list
3502abe02c0511b2278af9386e7ac5e266d890a38b1David Turner */
3512abe02c0511b2278af9386e7ac5e266d890a38b1David Turnerstatic size_t count_option_parameters(QEMUOptionParameter *list)
3522abe02c0511b2278af9386e7ac5e266d890a38b1David Turner{
3532abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    size_t num_options = 0;
3542abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
3552abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    while (list && list->name) {
3562abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        num_options++;
3572abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        list++;
3582abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    }
3592abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
3602abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    return num_options;
3612abe02c0511b2278af9386e7ac5e266d890a38b1David Turner}
3622abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
3632abe02c0511b2278af9386e7ac5e266d890a38b1David Turner/*
3642abe02c0511b2278af9386e7ac5e266d890a38b1David Turner * Append an option list (list) to an option list (dest).
3652abe02c0511b2278af9386e7ac5e266d890a38b1David Turner *
3662abe02c0511b2278af9386e7ac5e266d890a38b1David Turner * If dest is NULL, a new copy of list is created.
3672abe02c0511b2278af9386e7ac5e266d890a38b1David Turner *
3682abe02c0511b2278af9386e7ac5e266d890a38b1David Turner * Returns a pointer to the first element of dest (or the newly allocated copy)
3692abe02c0511b2278af9386e7ac5e266d890a38b1David Turner */
3702abe02c0511b2278af9386e7ac5e266d890a38b1David TurnerQEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
3712abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    QEMUOptionParameter *list)
3722abe02c0511b2278af9386e7ac5e266d890a38b1David Turner{
3732abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    size_t num_options, num_dest_options;
3742abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
3752abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    num_options = count_option_parameters(dest);
3762abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    num_dest_options = num_options;
3772abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
3782abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    num_options += count_option_parameters(list);
3792abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
380aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    dest = g_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter));
3812abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    dest[num_dest_options].name = NULL;
3822abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
3832abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    while (list && list->name) {
3842abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        if (get_option_parameter(dest, list->name) == NULL) {
3852abe02c0511b2278af9386e7ac5e266d890a38b1David Turner            dest[num_dest_options++] = *list;
3862abe02c0511b2278af9386e7ac5e266d890a38b1David Turner            dest[num_dest_options].name = NULL;
3872abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        }
3882abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        list++;
3892abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    }
3902abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
3912abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    return dest;
3922abe02c0511b2278af9386e7ac5e266d890a38b1David Turner}
3932abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
3942abe02c0511b2278af9386e7ac5e266d890a38b1David Turner/*
3955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Parses a parameter string (param) into an option list (dest).
3965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
397488bfd506a283c648f559140f51f125847d68664David 'Digit' Turner * list is the template option list. If dest is NULL, a new copy of list is
398488bfd506a283c648f559140f51f125847d68664David 'Digit' Turner * created. If list is NULL, this function fails.
3995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
4005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * A parameter string consists of one or more parameters, separated by commas.
4015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Each parameter consists of its name and possibly of a value. In the latter
4025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * case, the value is delimited by an = character. To specify a value which
4035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * contains commas, double each comma so it won't be recognized as the end of
4045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * the parameter.
4055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
4065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * For more details of the parsing see above.
4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
4085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Returns a pointer to the first element of dest (or the newly allocated copy)
4095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * or NULL in error cases
4105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
4115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerQEMUOptionParameter *parse_option_parameters(const char *param,
4125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUOptionParameter *list, QEMUOptionParameter *dest)
4135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUOptionParameter *allocated = NULL;
4155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char name[256];
4165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char value[256];
4175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char *param_delim, *value_delim;
4185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char next_delim;
4195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (list == NULL) {
4215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
4225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
4235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (dest == NULL) {
425488bfd506a283c648f559140f51f125847d68664David 'Digit' Turner        dest = allocated = append_option_parameters(NULL, list);
4265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
4275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (*param) {
4295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        // Find parameter name and value in the string
4315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        param_delim = strchr(param, ',');
4325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        value_delim = strchr(param, '=');
4335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (value_delim && (value_delim < param_delim || !param_delim)) {
4355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            next_delim = '=';
4365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
4375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            next_delim = ',';
4385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            value_delim = NULL;
4395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
4405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        param = get_opt_name(name, sizeof(name), param, next_delim);
4425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (value_delim) {
4435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            param = get_opt_value(value, sizeof(value), param + 1);
4445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
4455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (*param != '\0') {
4465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            param++;
4475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
4485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        // Set the parameter
4505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (set_option_parameter(dest, name, value_delim ? value : NULL)) {
4515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto fail;
4525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
4535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
4545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return dest;
4565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerfail:
4585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    // Only free the list if it was newly allocated
4595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    free_option_parameters(allocated);
4605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return NULL;
4615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
4645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Prints all options of a list that have a value to stdout
4655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
4665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid print_option_parameters(QEMUOptionParameter *list)
4675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (list && list->name) {
4695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        switch (list->type) {
4705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case OPT_STRING:
4715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                 if (list->value.s != NULL) {
4725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                     printf("%s='%s' ", list->name, list->value.s);
4735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                 }
4745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
4755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case OPT_FLAG:
4765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                printf("%s=%s ", list->name, list->value.n ? "on" : "off");
4775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
4785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case OPT_SIZE:
4795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case OPT_NUMBER:
4805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                printf("%s=%" PRId64 " ", list->name, list->value.n);
4815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
4825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            default:
4835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                printf("%s=(unkown type) ", list->name);
4845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
4855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
4865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        list++;
4875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
4885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
4915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Prints an overview of all available options
4925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
4935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid print_option_help(QEMUOptionParameter *list)
4945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    printf("Supported options:\n");
4965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (list && list->name) {
4975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        printf("%-16s %s\n", list->name,
4985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            list->help ? list->help : "No description available");
4995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        list++;
5005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
5015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5022910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
5032910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner/* ------------------------------------------------------------------ */
5042910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
5052910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerstruct QemuOpt {
5062910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    const char   *name;
5072910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    const char   *str;
5082910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
5099251866320b5f8329a043bb56b3a794f78d12849David 'Digit' Turner    const QemuOptDesc *desc;
5102910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    union {
5112910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        int      boolean;
5122910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        uint64_t uint;
5132910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    } value;
5142910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
5152910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QemuOpts     *opts;
5162910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QTAILQ_ENTRY(QemuOpt) next;
5172910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner};
5182910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
5192910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerstruct QemuOpts {
5202910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    char *id;
5212910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QemuOptsList *list;
5222abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    Location loc;
5232910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QTAILQ_HEAD(QemuOptHead, QemuOpt) head;
5242910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QTAILQ_ENTRY(QemuOpts) next;
5252910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner};
5262910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
5272910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerstatic QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
5282910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
5292910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QemuOpt *opt;
5302910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
5312910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
5322910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (strcmp(opt->name, name) != 0)
5332910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            continue;
5342910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        return opt;
5352910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
5362910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return NULL;
5372910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
5382910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
5392910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerconst char *qemu_opt_get(QemuOpts *opts, const char *name)
5402910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
5412910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QemuOpt *opt = qemu_opt_find(opts, name);
5422910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return opt ? opt->str : NULL;
5432910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
5442910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
5452910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerint qemu_opt_get_bool(QemuOpts *opts, const char *name, int defval)
5462910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
5472910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QemuOpt *opt = qemu_opt_find(opts, name);
5482910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
5492910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    if (opt == NULL)
5502910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        return defval;
5512910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
5522910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return opt->value.boolean;
5532910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
5542910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
5552910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turneruint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
5562910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
5572910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QemuOpt *opt = qemu_opt_find(opts, name);
5582910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
5592910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    if (opt == NULL)
5602910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        return defval;
5612910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER);
5622910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return opt->value.uint;
5632910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
5642910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
5652910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turneruint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
5662910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
5672910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QemuOpt *opt = qemu_opt_find(opts, name);
5682910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
5692910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    if (opt == NULL)
5702910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        return defval;
5712910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
5722910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return opt->value.uint;
5732910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
5742910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
5752910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerstatic int qemu_opt_parse(QemuOpt *opt)
5762910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
5772910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    if (opt->desc == NULL)
5782910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        return 0;
5792910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    switch (opt->desc->type) {
5802910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    case QEMU_OPT_STRING:
5812910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        /* nothing */
5822910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        return 0;
5832910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    case QEMU_OPT_BOOL:
5842910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        return parse_option_bool(opt->name, opt->str, &opt->value.boolean);
5852910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    case QEMU_OPT_NUMBER:
5862910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        return parse_option_number(opt->name, opt->str, &opt->value.uint);
5872910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    case QEMU_OPT_SIZE:
5882910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        return parse_option_size(opt->name, opt->str, &opt->value.uint);
5892910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    default:
5902910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        abort();
5912910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
5922910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
5932910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
5942910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerstatic void qemu_opt_del(QemuOpt *opt)
5952910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
5962910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QTAILQ_REMOVE(&opt->opts->head, opt, next);
597aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free((/* !const */ char*)opt->name);
598aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free((/* !const */ char*)opt->str);
599aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(opt);
6002910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
6012910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
6022910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerint qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
6032910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
6042910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QemuOpt *opt;
6059251866320b5f8329a043bb56b3a794f78d12849David 'Digit' Turner    const QemuOptDesc *desc = opts->list->desc;
6062910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    int i;
6072910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
6082910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    for (i = 0; desc[i].name != NULL; i++) {
6092910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (strcmp(desc[i].name, name) == 0) {
6102910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            break;
6112910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
6122910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
6132910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    if (desc[i].name == NULL) {
6142910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (i == 0) {
6152910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            /* empty list -> allow any */;
6162910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        } else {
6172abe02c0511b2278af9386e7ac5e266d890a38b1David Turner            qerror_report(QERR_INVALID_PARAMETER, name);
6182910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            return -1;
6192910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
6202910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
6212910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
622aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    opt = g_malloc0(sizeof(*opt));
623aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    opt->name = g_strdup(name);
6242910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    opt->opts = opts;
6252910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QTAILQ_INSERT_TAIL(&opts->head, opt, next);
6262910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    if (desc[i].name != NULL) {
6272910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        opt->desc = desc+i;
6282910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
6292910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    if (value) {
630aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner        opt->str = g_strdup(value);
6312910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
6322910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    if (qemu_opt_parse(opt) < 0) {
6332910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        qemu_opt_del(opt);
6342910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        return -1;
6352910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
6362910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return 0;
6372910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
6382910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
6392910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerint qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
6402910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                     int abort_on_failure)
6412910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
6422910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QemuOpt *opt;
6432910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    int rc = 0;
6442910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
6452910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QTAILQ_FOREACH(opt, &opts->head, next) {
6462910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        rc = func(opt->name, opt->str, opaque);
6472910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (abort_on_failure  &&  rc != 0)
6482910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            break;
6492910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
6502910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return rc;
6512910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
6522910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
6532910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' TurnerQemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
6542910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
6552910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QemuOpts *opts;
6562910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
6572910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QTAILQ_FOREACH(opts, &list->head, next) {
6582910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (!opts->id) {
6592910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            continue;
6602910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
6612910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (strcmp(opts->id, id) != 0) {
6622910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            continue;
6632910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
6642910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        return opts;
6652910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
6662910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return NULL;
6672910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
6682910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
6692abe02c0511b2278af9386e7ac5e266d890a38b1David Turnerstatic int id_wellformed(const char *id)
6702abe02c0511b2278af9386e7ac5e266d890a38b1David Turner{
6712abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    int i;
6722abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
6732abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    if (!qemu_isalpha(id[0])) {
6742abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        return 0;
6752abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    }
6762abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    for (i = 1; id[i]; i++) {
6772abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) {
6782abe02c0511b2278af9386e7ac5e266d890a38b1David Turner            return 0;
6792abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        }
6802abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    }
6812abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    return 1;
6822abe02c0511b2278af9386e7ac5e266d890a38b1David Turner}
6832abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
6842910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' TurnerQemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists)
6852910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
6862910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QemuOpts *opts = NULL;
6872910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
6882910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    if (id) {
6892abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        if (!id_wellformed(id)) {
6902abe02c0511b2278af9386e7ac5e266d890a38b1David Turner            qerror_report(QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
6912abe02c0511b2278af9386e7ac5e266d890a38b1David Turner            error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n");
6922abe02c0511b2278af9386e7ac5e266d890a38b1David Turner            return NULL;
6932abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        }
6942910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        opts = qemu_opts_find(list, id);
6952910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (opts != NULL) {
6962910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            if (fail_if_exists) {
6972abe02c0511b2278af9386e7ac5e266d890a38b1David Turner                qerror_report(QERR_DUPLICATE_ID, id, list->name);
6982910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                return NULL;
6992910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            } else {
7002910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                return opts;
7012910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            }
7022910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
7032910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
704aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    opts = g_malloc0(sizeof(*opts));
7052910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    if (id) {
706aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner        opts->id = g_strdup(id);
7072910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
7082910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    opts->list = list;
7092abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    loc_save(&opts->loc);
7102910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QTAILQ_INIT(&opts->head);
7112910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QTAILQ_INSERT_TAIL(&list->head, opts, next);
7122910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return opts;
7132910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
7142910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
7152abe02c0511b2278af9386e7ac5e266d890a38b1David Turnervoid qemu_opts_reset(QemuOptsList *list)
7162abe02c0511b2278af9386e7ac5e266d890a38b1David Turner{
7172abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    QemuOpts *opts, *next_opts;
7182abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
7192abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) {
7202abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        qemu_opts_del(opts);
7212abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    }
7222abe02c0511b2278af9386e7ac5e266d890a38b1David Turner}
7232abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
7242abe02c0511b2278af9386e7ac5e266d890a38b1David Turnervoid qemu_opts_loc_restore(QemuOpts *opts)
7252abe02c0511b2278af9386e7ac5e266d890a38b1David Turner{
7262abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    loc_restore(&opts->loc);
7272abe02c0511b2278af9386e7ac5e266d890a38b1David Turner}
7282abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
7292910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerint qemu_opts_set(QemuOptsList *list, const char *id,
7302910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                  const char *name, const char *value)
7312910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
7322910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QemuOpts *opts;
7332910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
7342910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    opts = qemu_opts_create(list, id, 1);
7352910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    if (opts == NULL) {
7362910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        return -1;
7372910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
7382910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return qemu_opt_set(opts, name, value);
7392910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
7402910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
7412910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerconst char *qemu_opts_id(QemuOpts *opts)
7422910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
7432910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return opts->id;
7442910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
7452910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
7462910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnervoid qemu_opts_del(QemuOpts *opts)
7472910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
7482910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QemuOpt *opt;
7492910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
7502910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    for (;;) {
7512910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        opt = QTAILQ_FIRST(&opts->head);
7522910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (opt == NULL)
7532910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            break;
7542910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        qemu_opt_del(opt);
7552910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
7562910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QTAILQ_REMOVE(&opts->list->head, opts, next);
757aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(opts->id);
758aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(opts);
7592910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
7602910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
7612910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerint qemu_opts_print(QemuOpts *opts, void *dummy)
7622910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
7632910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QemuOpt *opt;
7642910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
7652910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    fprintf(stderr, "%s: %s:", opts->list->name,
7662910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            opts->id ? opts->id : "<noid>");
7672910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QTAILQ_FOREACH(opt, &opts->head, next) {
7682910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        fprintf(stderr, " %s=\"%s\"", opt->name, opt->str);
7692910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
7702910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    fprintf(stderr, "\n");
7712910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return 0;
7722910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
7732910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
7742910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerint qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname)
7752910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
7762910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    char option[128], value[1024];
7772910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    const char *p,*pe,*pc;
7782910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
7792910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    for (p = params; *p != '\0'; p++) {
7802910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        pe = strchr(p, '=');
7812910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        pc = strchr(p, ',');
7822910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (!pe || (pc && pc < pe)) {
7832910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            /* found "foo,more" */
7842910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            if (p == params && firstname) {
7852910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                /* implicitly named first option */
7862910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                pstrcpy(option, sizeof(option), firstname);
7872910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                p = get_opt_value(value, sizeof(value), p);
7882910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            } else {
7892910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                /* option without value, probably a flag */
7902910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                p = get_opt_name(option, sizeof(option), p, ',');
7912910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                if (strncmp(option, "no", 2) == 0) {
7922910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    memmove(option, option+2, strlen(option+2)+1);
7932910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    pstrcpy(value, sizeof(value), "off");
7942910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                } else {
7952910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    pstrcpy(value, sizeof(value), "on");
7962910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                }
7972910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            }
7982910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        } else {
7992910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            /* found "foo=bar,more" */
8002910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            p = get_opt_name(option, sizeof(option), p, '=');
8012910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            if (*p != '=') {
8022910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                break;
8032910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            }
8042910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            p++;
8052910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            p = get_opt_value(value, sizeof(value), p);
8062910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
8072910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (strcmp(option, "id") != 0) {
8082910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            /* store and parse */
8092910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            if (qemu_opt_set(opts, option, value) == -1) {
8102910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                return -1;
8112910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            }
8122910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
8132910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (*p != ',') {
8142910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            break;
8152910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
8162910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
8172910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return 0;
8182910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
8192910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
8202abe02c0511b2278af9386e7ac5e266d890a38b1David TurnerQemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
8212abe02c0511b2278af9386e7ac5e266d890a38b1David Turner                          int permit_abbrev)
8222910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
8232abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    const char *firstname;
8242910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    char value[1024], *id = NULL;
8252910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    const char *p;
8262910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QemuOpts *opts;
8272910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
8282abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    assert(!permit_abbrev || list->implied_opt_name);
8292abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    firstname = permit_abbrev ? list->implied_opt_name : NULL;
8302abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
8312910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    if (strncmp(params, "id=", 3) == 0) {
8322910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        get_opt_value(value, sizeof(value), params+3);
8332abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        id = value;
8342910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    } else if ((p = strstr(params, ",id=")) != NULL) {
8352910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        get_opt_value(value, sizeof(value), p+4);
8362abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        id = value;
8372910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
8382910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    opts = qemu_opts_create(list, id, 1);
8392910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    if (opts == NULL)
8402910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        return NULL;
8412910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
8422910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    if (qemu_opts_do_parse(opts, params, firstname) != 0) {
8432910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        qemu_opts_del(opts);
8442910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        return NULL;
8452910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
8462910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
8472910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return opts;
8482910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
8492910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
8502abe02c0511b2278af9386e7ac5e266d890a38b1David Turnerstatic void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
8512abe02c0511b2278af9386e7ac5e266d890a38b1David Turner{
8522abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    char buf[32];
8532abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    const char *value;
8542abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    int n;
8552abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
8562abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    if (!strcmp(key, "id")) {
8572abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        return;
8582abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    }
8592abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
8602abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    switch (qobject_type(obj)) {
8612abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    case QTYPE_QSTRING:
8622abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        value = qstring_get_str(qobject_to_qstring(obj));
8632abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        break;
8642abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    case QTYPE_QINT:
8652abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        n = snprintf(buf, sizeof(buf), "%" PRId64,
8662abe02c0511b2278af9386e7ac5e266d890a38b1David Turner                     qint_get_int(qobject_to_qint(obj)));
8672abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        assert(n < sizeof(buf));
8682abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        value = buf;
8692abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        break;
8702abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    case QTYPE_QFLOAT:
8712abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        n = snprintf(buf, sizeof(buf), "%.17g",
8722abe02c0511b2278af9386e7ac5e266d890a38b1David Turner                     qfloat_get_double(qobject_to_qfloat(obj)));
8732abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        assert(n < sizeof(buf));
8742abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        value = buf;
8752abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        break;
8762abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    case QTYPE_QBOOL:
8772abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        pstrcpy(buf, sizeof(buf),
8782abe02c0511b2278af9386e7ac5e266d890a38b1David Turner                qbool_get_int(qobject_to_qbool(obj)) ? "on" : "off");
8792abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        value = buf;
8802abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        break;
8812abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    default:
8822abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        return;
8832abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    }
8842abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    qemu_opt_set(opaque, key, value);
8852abe02c0511b2278af9386e7ac5e266d890a38b1David Turner}
8862abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
8872abe02c0511b2278af9386e7ac5e266d890a38b1David Turner/*
8882abe02c0511b2278af9386e7ac5e266d890a38b1David Turner * Create QemuOpts from a QDict.
8892abe02c0511b2278af9386e7ac5e266d890a38b1David Turner * Use value of key "id" as ID if it exists and is a QString.
8902abe02c0511b2278af9386e7ac5e266d890a38b1David Turner * Only QStrings, QInts, QFloats and QBools are copied.  Entries with
8912abe02c0511b2278af9386e7ac5e266d890a38b1David Turner * other types are silently ignored.
8922abe02c0511b2278af9386e7ac5e266d890a38b1David Turner */
8932abe02c0511b2278af9386e7ac5e266d890a38b1David TurnerQemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict)
8942abe02c0511b2278af9386e7ac5e266d890a38b1David Turner{
8952abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    QemuOpts *opts;
8962abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
8972abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1);
8982abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    if (opts == NULL)
8992abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        return NULL;
9002abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
9012abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    qdict_iter(qdict, qemu_opts_from_qdict_1, opts);
9022abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    return opts;
9032abe02c0511b2278af9386e7ac5e266d890a38b1David Turner}
9042abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
9052abe02c0511b2278af9386e7ac5e266d890a38b1David Turner/*
9062abe02c0511b2278af9386e7ac5e266d890a38b1David Turner * Convert from QemuOpts to QDict.
9072abe02c0511b2278af9386e7ac5e266d890a38b1David Turner * The QDict values are of type QString.
9082abe02c0511b2278af9386e7ac5e266d890a38b1David Turner * TODO We'll want to use types appropriate for opt->desc->type, but
9092abe02c0511b2278af9386e7ac5e266d890a38b1David Turner * this is enough for now.
9102abe02c0511b2278af9386e7ac5e266d890a38b1David Turner */
9112abe02c0511b2278af9386e7ac5e266d890a38b1David TurnerQDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
9122abe02c0511b2278af9386e7ac5e266d890a38b1David Turner{
9132abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    QemuOpt *opt;
9142abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    QObject *val;
9152abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
9162abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    if (!qdict) {
9172abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        qdict = qdict_new();
9182abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    }
9192abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    if (opts->id) {
9202abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        qdict_put(qdict, "id", qstring_from_str(opts->id));
9212abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    }
9222abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    QTAILQ_FOREACH(opt, &opts->head, next) {
9232abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        val = QOBJECT(qstring_from_str(opt->str));
9242abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        qdict_put_obj(qdict, opt->name, val);
9252abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    }
9262abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    return qdict;
9272abe02c0511b2278af9386e7ac5e266d890a38b1David Turner}
9282abe02c0511b2278af9386e7ac5e266d890a38b1David Turner
9292910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner/* Validate parsed opts against descriptions where no
9302910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * descriptions were provided in the QemuOptsList.
9312910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner */
9329251866320b5f8329a043bb56b3a794f78d12849David 'Digit' Turnerint qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
9332910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
9342910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QemuOpt *opt;
9352910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
9362910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    assert(opts->list->desc[0].name == NULL);
9372910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
9382910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QTAILQ_FOREACH(opt, &opts->head, next) {
9392910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        int i;
9402910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
9412910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        for (i = 0; desc[i].name != NULL; i++) {
9422910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            if (strcmp(desc[i].name, opt->name) == 0) {
9432910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                break;
9442910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            }
9452910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
9462910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (desc[i].name == NULL) {
9472abe02c0511b2278af9386e7ac5e266d890a38b1David Turner            qerror_report(QERR_INVALID_PARAMETER, opt->name);
9482910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            return -1;
9492910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
9502910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
9512910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        opt->desc = &desc[i];
9522910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
9532910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (qemu_opt_parse(opt) < 0) {
9542910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            return -1;
9552910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
9562910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
9572910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
9582910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return 0;
9592910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
9602910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
9612910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerint qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
9622910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                      int abort_on_failure)
9632910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
9642abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    Location loc;
9652910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QemuOpts *opts;
9662910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    int rc = 0;
9672910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
9682abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    loc_push_none(&loc);
9692910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QTAILQ_FOREACH(opts, &list->head, next) {
9702abe02c0511b2278af9386e7ac5e266d890a38b1David Turner        loc_restore(&opts->loc);
9719251866320b5f8329a043bb56b3a794f78d12849David 'Digit' Turner        rc |= func(opts, opaque);
9722910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (abort_on_failure  &&  rc != 0)
9732910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            break;
9742910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
9752abe02c0511b2278af9386e7ac5e266d890a38b1David Turner    loc_pop(&loc);
9762910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return rc;
9772910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
978