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 { 30 struct arg a; 31 32 a.argv = argv; 33 a.argv_step = 1; 34 a.name = NULL; 35 a.val = NULL; 36 a.def = NULL; 37 return a; 38 } 39 40 int arg_match(struct arg *arg_, const struct arg_def *def, char **argv) 41 { 42 struct arg arg; 43 44 if (!argv[0] || argv[0][0] != '-') 45 return 0; 46 47 arg = arg_init(argv); 48 49 if (def->short_name 50 && strlen(arg.argv[0]) == strlen(def->short_name) + 1 51 && !strcmp(arg.argv[0] + 1, def->short_name)) 52 { 53 54 arg.name = arg.argv[0] + 1; 55 arg.val = def->has_val ? arg.argv[1] : NULL; 56 arg.argv_step = def->has_val ? 2 : 1; 57 } 58 else if (def->long_name) 59 { 60 int name_len = strlen(def->long_name); 61 62 if (strlen(arg.argv[0]) >= name_len + 2 63 && arg.argv[0][1] == '-' 64 && !strncmp(arg.argv[0] + 2, def->long_name, name_len) 65 && (arg.argv[0][name_len+2] == '=' 66 || arg.argv[0][name_len+2] == '\0')) 67 { 68 69 arg.name = arg.argv[0] + 2; 70 arg.val = arg.name[name_len] == '=' ? arg.name + name_len + 1 : NULL; 71 arg.argv_step = 1; 72 } 73 } 74 75 if (arg.name && !arg.val && def->has_val) 76 die("Error: option %s requires argument.\n", arg.name); 77 78 if (arg.name && arg.val && !def->has_val) 79 die("Error: option %s requires no argument.\n", arg.name); 80 81 if (arg.name 82 && (arg.val || !def->has_val)) 83 { 84 arg.def = def; 85 *arg_ = arg; 86 return 1; 87 } 88 89 return 0; 90 } 91 92 93 const char *arg_next(struct arg *arg) 94 { 95 if (arg->argv[0]) 96 arg->argv += arg->argv_step; 97 98 return *arg->argv; 99 } 100 101 102 char **argv_dup(int argc, const char **argv) 103 { 104 char **new_argv = malloc((argc + 1) * sizeof(*argv)); 105 106 memcpy(new_argv, argv, argc * sizeof(*argv)); 107 new_argv[argc] = NULL; 108 return new_argv; 109 } 110 111 112 void arg_show_usage(FILE *fp, const struct arg_def *const *defs) 113 { 114 char option_text[40] = {0}; 115 116 for (; *defs; defs++) 117 { 118 const struct arg_def *def = *defs; 119 char *short_val = def->has_val ? " <arg>" : ""; 120 char *long_val = def->has_val ? "=<arg>" : ""; 121 122 if (def->short_name && def->long_name) 123 { 124 char *comma = def->has_val ? "," : ", "; 125 126 snprintf(option_text, 37, "-%s%s%s --%s%6s", 127 def->short_name, short_val, comma, 128 def->long_name, long_val); 129 } 130 else if (def->short_name) 131 snprintf(option_text, 37, "-%s%s", 132 def->short_name, short_val); 133 else if (def->long_name) 134 snprintf(option_text, 37, " --%s%s", 135 def->long_name, long_val); 136 137 fprintf(fp, " %-37s\t%s\n", option_text, def->desc); 138 139 if(def->enums) 140 { 141 const struct arg_enum_list *listptr; 142 143 fprintf(fp, " %-37s\t ", ""); 144 145 for(listptr = def->enums; listptr->name; listptr++) 146 fprintf(fp, "%s%s", listptr->name, 147 listptr[1].name ? ", " : "\n"); 148 } 149 } 150 } 151 152 153 unsigned int arg_parse_uint(const struct arg *arg) 154 { 155 long int rawval; 156 char *endptr; 157 158 rawval = strtol(arg->val, &endptr, 10); 159 160 if (arg->val[0] != '\0' && endptr[0] == '\0') 161 { 162 if (rawval >= 0 && rawval <= UINT_MAX) 163 return rawval; 164 165 die("Option %s: Value %ld out of range for unsigned int\n", 166 arg->name, rawval); 167 } 168 169 die("Option %s: Invalid character '%c'\n", arg->name, *endptr); 170 return 0; 171 } 172 173 174 int arg_parse_int(const struct arg *arg) 175 { 176 long int rawval; 177 char *endptr; 178 179 rawval = strtol(arg->val, &endptr, 10); 180 181 if (arg->val[0] != '\0' && endptr[0] == '\0') 182 { 183 if (rawval >= INT_MIN && rawval <= INT_MAX) 184 return rawval; 185 186 die("Option %s: Value %ld out of range for signed int\n", 187 arg->name, rawval); 188 } 189 190 die("Option %s: Invalid character '%c'\n", arg->name, *endptr); 191 return 0; 192 } 193 194 195 struct vpx_rational 196 { 197 int num; /**< fraction numerator */ 198 int den; /**< fraction denominator */ 199 }; 200 struct vpx_rational arg_parse_rational(const struct arg *arg) 201 { 202 long int rawval; 203 char *endptr; 204 struct vpx_rational rat; 205 206 /* parse numerator */ 207 rawval = strtol(arg->val, &endptr, 10); 208 209 if (arg->val[0] != '\0' && endptr[0] == '/') 210 { 211 if (rawval >= INT_MIN && rawval <= INT_MAX) 212 rat.num = rawval; 213 else die("Option %s: Value %ld out of range for signed int\n", 214 arg->name, rawval); 215 } 216 else die("Option %s: Expected / at '%c'\n", arg->name, *endptr); 217 218 /* parse denominator */ 219 rawval = strtol(endptr + 1, &endptr, 10); 220 221 if (arg->val[0] != '\0' && endptr[0] == '\0') 222 { 223 if (rawval >= INT_MIN && rawval <= INT_MAX) 224 rat.den = rawval; 225 else die("Option %s: Value %ld out of range for signed int\n", 226 arg->name, rawval); 227 } 228 else die("Option %s: Invalid character '%c'\n", arg->name, *endptr); 229 230 return rat; 231 } 232 233 234 int arg_parse_enum(const struct arg *arg) 235 { 236 const struct arg_enum_list *listptr; 237 long int rawval; 238 char *endptr; 239 240 /* First see if the value can be parsed as a raw value */ 241 rawval = strtol(arg->val, &endptr, 10); 242 if (arg->val[0] != '\0' && endptr[0] == '\0') 243 { 244 /* Got a raw value, make sure it's valid */ 245 for(listptr = arg->def->enums; listptr->name; listptr++) 246 if(listptr->val == rawval) 247 return rawval; 248 } 249 250 /* Next see if it can be parsed as a string */ 251 for(listptr = arg->def->enums; listptr->name; listptr++) 252 if(!strcmp(arg->val, listptr->name)) 253 return listptr->val; 254 255 die("Option %s: Invalid value '%s'\n", arg->name, arg->val); 256 return 0; 257 } 258 259 260 int arg_parse_enum_or_int(const struct arg *arg) 261 { 262 if(arg->def->enums) 263 return arg_parse_enum(arg); 264 return arg_parse_int(arg); 265 } 266