1 /* 2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 12 #include <stdlib.h> 13 #include <string.h> 14 #include <limits.h> 15 #include "args.h" 16 17 #ifdef _MSC_VER 18 #define snprintf _snprintf 19 #endif 20 21 #if defined(__GNUC__) && __GNUC__ 22 extern void die(const char *fmt, ...) __attribute__((noreturn)); 23 #else 24 extern void die(const char *fmt, ...); 25 #endif 26 27 28 struct arg arg_init(char **argv) { 29 struct arg a; 30 31 a.argv = argv; 32 a.argv_step = 1; 33 a.name = NULL; 34 a.val = NULL; 35 a.def = NULL; 36 return a; 37 } 38 39 int arg_match(struct arg *arg_, const struct arg_def *def, char **argv) { 40 struct arg arg; 41 42 if (!argv[0] || argv[0][0] != '-') 43 return 0; 44 45 arg = arg_init(argv); 46 47 if (def->short_name 48 && strlen(arg.argv[0]) == strlen(def->short_name) + 1 49 && !strcmp(arg.argv[0] + 1, def->short_name)) { 50 51 arg.name = arg.argv[0] + 1; 52 arg.val = def->has_val ? arg.argv[1] : NULL; 53 arg.argv_step = def->has_val ? 2 : 1; 54 } else if (def->long_name) { 55 const size_t name_len = strlen(def->long_name); 56 57 if (strlen(arg.argv[0]) >= name_len + 2 58 && arg.argv[0][1] == '-' 59 && !strncmp(arg.argv[0] + 2, def->long_name, name_len) 60 && (arg.argv[0][name_len + 2] == '=' 61 || arg.argv[0][name_len + 2] == '\0')) { 62 63 arg.name = arg.argv[0] + 2; 64 arg.val = arg.name[name_len] == '=' ? arg.name + name_len + 1 : NULL; 65 arg.argv_step = 1; 66 } 67 } 68 69 if (arg.name && !arg.val && def->has_val) 70 die("Error: option %s requires argument.\n", arg.name); 71 72 if (arg.name && arg.val && !def->has_val) 73 die("Error: option %s requires no argument.\n", arg.name); 74 75 if (arg.name 76 && (arg.val || !def->has_val)) { 77 arg.def = def; 78 *arg_ = arg; 79 return 1; 80 } 81 82 return 0; 83 } 84 85 86 const char *arg_next(struct arg *arg) { 87 if (arg->argv[0]) 88 arg->argv += arg->argv_step; 89 90 return *arg->argv; 91 } 92 93 94 char **argv_dup(int argc, const char **argv) { 95 char **new_argv = malloc((argc + 1) * sizeof(*argv)); 96 97 memcpy(new_argv, argv, argc * sizeof(*argv)); 98 new_argv[argc] = NULL; 99 return new_argv; 100 } 101 102 103 void arg_show_usage(FILE *fp, const struct arg_def *const *defs) { 104 char option_text[40] = {0}; 105 106 for (; *defs; defs++) { 107 const struct arg_def *def = *defs; 108 char *short_val = def->has_val ? " <arg>" : ""; 109 char *long_val = def->has_val ? "=<arg>" : ""; 110 111 if (def->short_name && def->long_name) { 112 char *comma = def->has_val ? "," : ", "; 113 114 snprintf(option_text, 37, "-%s%s%s --%s%6s", 115 def->short_name, short_val, comma, 116 def->long_name, long_val); 117 } else if (def->short_name) 118 snprintf(option_text, 37, "-%s%s", 119 def->short_name, short_val); 120 else if (def->long_name) 121 snprintf(option_text, 37, " --%s%s", 122 def->long_name, long_val); 123 124 fprintf(fp, " %-37s\t%s\n", option_text, def->desc); 125 126 if (def->enums) { 127 const struct arg_enum_list *listptr; 128 129 fprintf(fp, " %-37s\t ", ""); 130 131 for (listptr = def->enums; listptr->name; listptr++) 132 fprintf(fp, "%s%s", listptr->name, 133 listptr[1].name ? ", " : "\n"); 134 } 135 } 136 } 137 138 139 unsigned int arg_parse_uint(const struct arg *arg) { 140 long int rawval; 141 char *endptr; 142 143 rawval = strtol(arg->val, &endptr, 10); 144 145 if (arg->val[0] != '\0' && endptr[0] == '\0') { 146 if (rawval >= 0 && rawval <= UINT_MAX) 147 return rawval; 148 149 die("Option %s: Value %ld out of range for unsigned int\n", 150 arg->name, rawval); 151 } 152 153 die("Option %s: Invalid character '%c'\n", arg->name, *endptr); 154 return 0; 155 } 156 157 158 int arg_parse_int(const struct arg *arg) { 159 long int rawval; 160 char *endptr; 161 162 rawval = strtol(arg->val, &endptr, 10); 163 164 if (arg->val[0] != '\0' && endptr[0] == '\0') { 165 if (rawval >= INT_MIN && rawval <= INT_MAX) 166 return rawval; 167 168 die("Option %s: Value %ld out of range for signed int\n", 169 arg->name, rawval); 170 } 171 172 die("Option %s: Invalid character '%c'\n", arg->name, *endptr); 173 return 0; 174 } 175 176 177 struct vpx_rational { 178 int num; /**< fraction numerator */ 179 int den; /**< fraction denominator */ 180 }; 181 struct vpx_rational arg_parse_rational(const struct arg *arg) { 182 long int rawval; 183 char *endptr; 184 struct vpx_rational rat; 185 186 /* parse numerator */ 187 rawval = strtol(arg->val, &endptr, 10); 188 189 if (arg->val[0] != '\0' && endptr[0] == '/') { 190 if (rawval >= INT_MIN && rawval <= INT_MAX) 191 rat.num = rawval; 192 else die("Option %s: Value %ld out of range for signed int\n", 193 arg->name, rawval); 194 } else die("Option %s: Expected / at '%c'\n", arg->name, *endptr); 195 196 /* parse denominator */ 197 rawval = strtol(endptr + 1, &endptr, 10); 198 199 if (arg->val[0] != '\0' && endptr[0] == '\0') { 200 if (rawval >= INT_MIN && rawval <= INT_MAX) 201 rat.den = rawval; 202 else die("Option %s: Value %ld out of range for signed int\n", 203 arg->name, rawval); 204 } else die("Option %s: Invalid character '%c'\n", arg->name, *endptr); 205 206 return rat; 207 } 208 209 210 int arg_parse_enum(const struct arg *arg) { 211 const struct arg_enum_list *listptr; 212 long int rawval; 213 char *endptr; 214 215 /* First see if the value can be parsed as a raw value */ 216 rawval = strtol(arg->val, &endptr, 10); 217 if (arg->val[0] != '\0' && endptr[0] == '\0') { 218 /* Got a raw value, make sure it's valid */ 219 for (listptr = arg->def->enums; listptr->name; listptr++) 220 if (listptr->val == rawval) 221 return rawval; 222 } 223 224 /* Next see if it can be parsed as a string */ 225 for (listptr = arg->def->enums; listptr->name; listptr++) 226 if (!strcmp(arg->val, listptr->name)) 227 return listptr->val; 228 229 die("Option %s: Invalid value '%s'\n", arg->name, arg->val); 230 return 0; 231 } 232 233 234 int arg_parse_enum_or_int(const struct arg *arg) { 235 if (arg->def->enums) 236 return arg_parse_enum(arg); 237 return arg_parse_int(arg); 238 } 239