1233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* 2233d2500723e5594f3e7c70896ffeeef32b9c950ywan * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 3233d2500723e5594f3e7c70896ffeeef32b9c950ywan * 4233d2500723e5594f3e7c70896ffeeef32b9c950ywan * Use of this source code is governed by a BSD-style license 5233d2500723e5594f3e7c70896ffeeef32b9c950ywan * that can be found in the LICENSE file in the root of the source 6233d2500723e5594f3e7c70896ffeeef32b9c950ywan * tree. An additional intellectual property rights grant can be found 7233d2500723e5594f3e7c70896ffeeef32b9c950ywan * in the file PATENTS. All contributing project authors may 8233d2500723e5594f3e7c70896ffeeef32b9c950ywan * be found in the AUTHORS file in the root of the source tree. 9233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 10233d2500723e5594f3e7c70896ffeeef32b9c950ywan 11233d2500723e5594f3e7c70896ffeeef32b9c950ywan 12233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdlib.h> 13233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <string.h> 14233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <limits.h> 15233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "args.h" 16233d2500723e5594f3e7c70896ffeeef32b9c950ywan 17233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _MSC_VER 18233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define snprintf _snprintf 19233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 20233d2500723e5594f3e7c70896ffeeef32b9c950ywan 21233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if defined(__GNUC__) && __GNUC__ 22233d2500723e5594f3e7c70896ffeeef32b9c950ywanextern void die(const char *fmt, ...) __attribute__((noreturn)); 23233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else 24233d2500723e5594f3e7c70896ffeeef32b9c950ywanextern void die(const char *fmt, ...); 25233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 26233d2500723e5594f3e7c70896ffeeef32b9c950ywan 27233d2500723e5594f3e7c70896ffeeef32b9c950ywan 28233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct arg arg_init(char **argv) { 29233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct arg a; 30233d2500723e5594f3e7c70896ffeeef32b9c950ywan 31233d2500723e5594f3e7c70896ffeeef32b9c950ywan a.argv = argv; 32233d2500723e5594f3e7c70896ffeeef32b9c950ywan a.argv_step = 1; 33233d2500723e5594f3e7c70896ffeeef32b9c950ywan a.name = NULL; 34233d2500723e5594f3e7c70896ffeeef32b9c950ywan a.val = NULL; 35233d2500723e5594f3e7c70896ffeeef32b9c950ywan a.def = NULL; 36233d2500723e5594f3e7c70896ffeeef32b9c950ywan return a; 37233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 38233d2500723e5594f3e7c70896ffeeef32b9c950ywan 39233d2500723e5594f3e7c70896ffeeef32b9c950ywanint arg_match(struct arg *arg_, const struct arg_def *def, char **argv) { 40233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct arg arg; 41233d2500723e5594f3e7c70896ffeeef32b9c950ywan 42233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!argv[0] || argv[0][0] != '-') 43233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 44233d2500723e5594f3e7c70896ffeeef32b9c950ywan 45233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg = arg_init(argv); 46233d2500723e5594f3e7c70896ffeeef32b9c950ywan 47233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (def->short_name 48233d2500723e5594f3e7c70896ffeeef32b9c950ywan && strlen(arg.argv[0]) == strlen(def->short_name) + 1 49233d2500723e5594f3e7c70896ffeeef32b9c950ywan && !strcmp(arg.argv[0] + 1, def->short_name)) { 50233d2500723e5594f3e7c70896ffeeef32b9c950ywan 51233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg.name = arg.argv[0] + 1; 52233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg.val = def->has_val ? arg.argv[1] : NULL; 53233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg.argv_step = def->has_val ? 2 : 1; 54233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (def->long_name) { 55233d2500723e5594f3e7c70896ffeeef32b9c950ywan const size_t name_len = strlen(def->long_name); 56233d2500723e5594f3e7c70896ffeeef32b9c950ywan 57233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (strlen(arg.argv[0]) >= name_len + 2 58233d2500723e5594f3e7c70896ffeeef32b9c950ywan && arg.argv[0][1] == '-' 59233d2500723e5594f3e7c70896ffeeef32b9c950ywan && !strncmp(arg.argv[0] + 2, def->long_name, name_len) 60233d2500723e5594f3e7c70896ffeeef32b9c950ywan && (arg.argv[0][name_len + 2] == '=' 61233d2500723e5594f3e7c70896ffeeef32b9c950ywan || arg.argv[0][name_len + 2] == '\0')) { 62233d2500723e5594f3e7c70896ffeeef32b9c950ywan 63233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg.name = arg.argv[0] + 2; 64233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg.val = arg.name[name_len] == '=' ? arg.name + name_len + 1 : NULL; 65233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg.argv_step = 1; 66233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 67233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 68233d2500723e5594f3e7c70896ffeeef32b9c950ywan 69233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (arg.name && !arg.val && def->has_val) 70233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Error: option %s requires argument.\n", arg.name); 71233d2500723e5594f3e7c70896ffeeef32b9c950ywan 72233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (arg.name && arg.val && !def->has_val) 73233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Error: option %s requires no argument.\n", arg.name); 74233d2500723e5594f3e7c70896ffeeef32b9c950ywan 75233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (arg.name 76233d2500723e5594f3e7c70896ffeeef32b9c950ywan && (arg.val || !def->has_val)) { 77233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg.def = def; 78233d2500723e5594f3e7c70896ffeeef32b9c950ywan *arg_ = arg; 79233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 1; 80233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 81233d2500723e5594f3e7c70896ffeeef32b9c950ywan 82233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 83233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 84233d2500723e5594f3e7c70896ffeeef32b9c950ywan 85233d2500723e5594f3e7c70896ffeeef32b9c950ywan 86233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst char *arg_next(struct arg *arg) { 87233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (arg->argv[0]) 88233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg->argv += arg->argv_step; 89233d2500723e5594f3e7c70896ffeeef32b9c950ywan 90233d2500723e5594f3e7c70896ffeeef32b9c950ywan return *arg->argv; 91233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 92233d2500723e5594f3e7c70896ffeeef32b9c950ywan 93233d2500723e5594f3e7c70896ffeeef32b9c950ywan 94233d2500723e5594f3e7c70896ffeeef32b9c950ywanchar **argv_dup(int argc, const char **argv) { 95233d2500723e5594f3e7c70896ffeeef32b9c950ywan char **new_argv = malloc((argc + 1) * sizeof(*argv)); 96233d2500723e5594f3e7c70896ffeeef32b9c950ywan 97233d2500723e5594f3e7c70896ffeeef32b9c950ywan memcpy(new_argv, argv, argc * sizeof(*argv)); 98233d2500723e5594f3e7c70896ffeeef32b9c950ywan new_argv[argc] = NULL; 99233d2500723e5594f3e7c70896ffeeef32b9c950ywan return new_argv; 100233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 101233d2500723e5594f3e7c70896ffeeef32b9c950ywan 102233d2500723e5594f3e7c70896ffeeef32b9c950ywan 103233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid arg_show_usage(FILE *fp, const struct arg_def *const *defs) { 104233d2500723e5594f3e7c70896ffeeef32b9c950ywan char option_text[40] = {0}; 105233d2500723e5594f3e7c70896ffeeef32b9c950ywan 106233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (; *defs; defs++) { 107233d2500723e5594f3e7c70896ffeeef32b9c950ywan const struct arg_def *def = *defs; 108233d2500723e5594f3e7c70896ffeeef32b9c950ywan char *short_val = def->has_val ? " <arg>" : ""; 109233d2500723e5594f3e7c70896ffeeef32b9c950ywan char *long_val = def->has_val ? "=<arg>" : ""; 110233d2500723e5594f3e7c70896ffeeef32b9c950ywan 111233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (def->short_name && def->long_name) { 112233d2500723e5594f3e7c70896ffeeef32b9c950ywan char *comma = def->has_val ? "," : ", "; 113233d2500723e5594f3e7c70896ffeeef32b9c950ywan 114233d2500723e5594f3e7c70896ffeeef32b9c950ywan snprintf(option_text, 37, "-%s%s%s --%s%6s", 115233d2500723e5594f3e7c70896ffeeef32b9c950ywan def->short_name, short_val, comma, 116233d2500723e5594f3e7c70896ffeeef32b9c950ywan def->long_name, long_val); 117233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else if (def->short_name) 118233d2500723e5594f3e7c70896ffeeef32b9c950ywan snprintf(option_text, 37, "-%s%s", 119233d2500723e5594f3e7c70896ffeeef32b9c950ywan def->short_name, short_val); 120233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (def->long_name) 121233d2500723e5594f3e7c70896ffeeef32b9c950ywan snprintf(option_text, 37, " --%s%s", 122233d2500723e5594f3e7c70896ffeeef32b9c950ywan def->long_name, long_val); 123233d2500723e5594f3e7c70896ffeeef32b9c950ywan 124233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(fp, " %-37s\t%s\n", option_text, def->desc); 125233d2500723e5594f3e7c70896ffeeef32b9c950ywan 126233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (def->enums) { 127233d2500723e5594f3e7c70896ffeeef32b9c950ywan const struct arg_enum_list *listptr; 128233d2500723e5594f3e7c70896ffeeef32b9c950ywan 129233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(fp, " %-37s\t ", ""); 130233d2500723e5594f3e7c70896ffeeef32b9c950ywan 131233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (listptr = def->enums; listptr->name; listptr++) 132233d2500723e5594f3e7c70896ffeeef32b9c950ywan fprintf(fp, "%s%s", listptr->name, 133233d2500723e5594f3e7c70896ffeeef32b9c950ywan listptr[1].name ? ", " : "\n"); 134233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 135233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 136233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 137233d2500723e5594f3e7c70896ffeeef32b9c950ywan 138233d2500723e5594f3e7c70896ffeeef32b9c950ywan 139233d2500723e5594f3e7c70896ffeeef32b9c950ywanunsigned int arg_parse_uint(const struct arg *arg) { 140233d2500723e5594f3e7c70896ffeeef32b9c950ywan long int rawval; 141233d2500723e5594f3e7c70896ffeeef32b9c950ywan char *endptr; 142233d2500723e5594f3e7c70896ffeeef32b9c950ywan 143233d2500723e5594f3e7c70896ffeeef32b9c950ywan rawval = strtol(arg->val, &endptr, 10); 144233d2500723e5594f3e7c70896ffeeef32b9c950ywan 145233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (arg->val[0] != '\0' && endptr[0] == '\0') { 146233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (rawval >= 0 && rawval <= UINT_MAX) 147233d2500723e5594f3e7c70896ffeeef32b9c950ywan return rawval; 148233d2500723e5594f3e7c70896ffeeef32b9c950ywan 149233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Option %s: Value %ld out of range for unsigned int\n", 150233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg->name, rawval); 151233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 152233d2500723e5594f3e7c70896ffeeef32b9c950ywan 153233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Option %s: Invalid character '%c'\n", arg->name, *endptr); 154233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 155233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 156233d2500723e5594f3e7c70896ffeeef32b9c950ywan 157233d2500723e5594f3e7c70896ffeeef32b9c950ywan 158233d2500723e5594f3e7c70896ffeeef32b9c950ywanint arg_parse_int(const struct arg *arg) { 159233d2500723e5594f3e7c70896ffeeef32b9c950ywan long int rawval; 160233d2500723e5594f3e7c70896ffeeef32b9c950ywan char *endptr; 161233d2500723e5594f3e7c70896ffeeef32b9c950ywan 162233d2500723e5594f3e7c70896ffeeef32b9c950ywan rawval = strtol(arg->val, &endptr, 10); 163233d2500723e5594f3e7c70896ffeeef32b9c950ywan 164233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (arg->val[0] != '\0' && endptr[0] == '\0') { 165233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (rawval >= INT_MIN && rawval <= INT_MAX) 166233d2500723e5594f3e7c70896ffeeef32b9c950ywan return rawval; 167233d2500723e5594f3e7c70896ffeeef32b9c950ywan 168233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Option %s: Value %ld out of range for signed int\n", 169233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg->name, rawval); 170233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 171233d2500723e5594f3e7c70896ffeeef32b9c950ywan 172233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Option %s: Invalid character '%c'\n", arg->name, *endptr); 173233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 174233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 175233d2500723e5594f3e7c70896ffeeef32b9c950ywan 176233d2500723e5594f3e7c70896ffeeef32b9c950ywan 177233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct vpx_rational { 178233d2500723e5594f3e7c70896ffeeef32b9c950ywan int num; /**< fraction numerator */ 179233d2500723e5594f3e7c70896ffeeef32b9c950ywan int den; /**< fraction denominator */ 180233d2500723e5594f3e7c70896ffeeef32b9c950ywan}; 181233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct vpx_rational arg_parse_rational(const struct arg *arg) { 182233d2500723e5594f3e7c70896ffeeef32b9c950ywan long int rawval; 183233d2500723e5594f3e7c70896ffeeef32b9c950ywan char *endptr; 184233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct vpx_rational rat; 185233d2500723e5594f3e7c70896ffeeef32b9c950ywan 186233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* parse numerator */ 187233d2500723e5594f3e7c70896ffeeef32b9c950ywan rawval = strtol(arg->val, &endptr, 10); 188233d2500723e5594f3e7c70896ffeeef32b9c950ywan 189233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (arg->val[0] != '\0' && endptr[0] == '/') { 190233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (rawval >= INT_MIN && rawval <= INT_MAX) 191233d2500723e5594f3e7c70896ffeeef32b9c950ywan rat.num = rawval; 192233d2500723e5594f3e7c70896ffeeef32b9c950ywan else die("Option %s: Value %ld out of range for signed int\n", 193233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg->name, rawval); 194233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else die("Option %s: Expected / at '%c'\n", arg->name, *endptr); 195233d2500723e5594f3e7c70896ffeeef32b9c950ywan 196233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* parse denominator */ 197233d2500723e5594f3e7c70896ffeeef32b9c950ywan rawval = strtol(endptr + 1, &endptr, 10); 198233d2500723e5594f3e7c70896ffeeef32b9c950ywan 199233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (arg->val[0] != '\0' && endptr[0] == '\0') { 200233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (rawval >= INT_MIN && rawval <= INT_MAX) 201233d2500723e5594f3e7c70896ffeeef32b9c950ywan rat.den = rawval; 202233d2500723e5594f3e7c70896ffeeef32b9c950ywan else die("Option %s: Value %ld out of range for signed int\n", 203233d2500723e5594f3e7c70896ffeeef32b9c950ywan arg->name, rawval); 204233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else die("Option %s: Invalid character '%c'\n", arg->name, *endptr); 205233d2500723e5594f3e7c70896ffeeef32b9c950ywan 206233d2500723e5594f3e7c70896ffeeef32b9c950ywan return rat; 207233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 208233d2500723e5594f3e7c70896ffeeef32b9c950ywan 209233d2500723e5594f3e7c70896ffeeef32b9c950ywan 210233d2500723e5594f3e7c70896ffeeef32b9c950ywanint arg_parse_enum(const struct arg *arg) { 211233d2500723e5594f3e7c70896ffeeef32b9c950ywan const struct arg_enum_list *listptr; 212233d2500723e5594f3e7c70896ffeeef32b9c950ywan long int rawval; 213233d2500723e5594f3e7c70896ffeeef32b9c950ywan char *endptr; 214233d2500723e5594f3e7c70896ffeeef32b9c950ywan 215233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* First see if the value can be parsed as a raw value */ 216233d2500723e5594f3e7c70896ffeeef32b9c950ywan rawval = strtol(arg->val, &endptr, 10); 217233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (arg->val[0] != '\0' && endptr[0] == '\0') { 218233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Got a raw value, make sure it's valid */ 219233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (listptr = arg->def->enums; listptr->name; listptr++) 220233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (listptr->val == rawval) 221233d2500723e5594f3e7c70896ffeeef32b9c950ywan return rawval; 222233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 223233d2500723e5594f3e7c70896ffeeef32b9c950ywan 224233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Next see if it can be parsed as a string */ 225233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (listptr = arg->def->enums; listptr->name; listptr++) 226233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!strcmp(arg->val, listptr->name)) 227233d2500723e5594f3e7c70896ffeeef32b9c950ywan return listptr->val; 228233d2500723e5594f3e7c70896ffeeef32b9c950ywan 229233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Option %s: Invalid value '%s'\n", arg->name, arg->val); 230233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 231233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 232233d2500723e5594f3e7c70896ffeeef32b9c950ywan 233233d2500723e5594f3e7c70896ffeeef32b9c950ywan 234233d2500723e5594f3e7c70896ffeeef32b9c950ywanint arg_parse_enum_or_int(const struct arg *arg) { 235233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (arg->def->enums) 236233d2500723e5594f3e7c70896ffeeef32b9c950ywan return arg_parse_enum(arg); 237233d2500723e5594f3e7c70896ffeeef32b9c950ywan return arg_parse_int(arg); 238233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 239