Annotation of qemu/qemu-option.c, revision 1.1

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

unix.superglobalmegacorp.com