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 } 140 141 142 unsigned int arg_parse_uint(const struct arg *arg) 143 { 144 long int rawval; 145 char *endptr; 146 147 rawval = strtol(arg->val, &endptr, 10); 148 149 if (arg->val[0] != '\0' && endptr[0] == '\0') 150 { 151 if (rawval >= 0 && rawval <= UINT_MAX) 152 return rawval; 153 154 die("Option %s: Value %ld out of range for unsigned int\n", 155 arg->name, rawval); 156 } 157 158 die("Option %s: Invalid character '%c'\n", arg->name, *endptr); 159 return 0; 160 } 161 162 163 int arg_parse_int(const struct arg *arg) 164 { 165 long int rawval; 166 char *endptr; 167 168 rawval = strtol(arg->val, &endptr, 10); 169 170 if (arg->val[0] != '\0' && endptr[0] == '\0') 171 { 172 if (rawval >= INT_MIN && rawval <= INT_MAX) 173 return rawval; 174 175 die("Option %s: Value %ld out of range for signed int\n", 176 arg->name, rawval); 177 } 178 179 die("Option %s: Invalid character '%c'\n", arg->name, *endptr); 180 return 0; 181 } 182 183 184 struct vpx_rational 185 { 186 int num; /**< fraction numerator */ 187 int den; /**< fraction denominator */ 188 }; 189 struct vpx_rational arg_parse_rational(const struct arg *arg) 190 { 191 long int rawval; 192 char *endptr; 193 struct vpx_rational rat; 194 195 /* parse numerator */ 196 rawval = strtol(arg->val, &endptr, 10); 197 198 if (arg->val[0] != '\0' && endptr[0] == '/') 199 { 200 if (rawval >= INT_MIN && rawval <= INT_MAX) 201 rat.num = rawval; 202 else die("Option %s: Value %ld out of range for signed int\n", 203 arg->name, rawval); 204 } 205 else die("Option %s: Expected / at '%c'\n", arg->name, *endptr); 206 207 /* parse denominator */ 208 rawval = strtol(endptr + 1, &endptr, 10); 209 210 if (arg->val[0] != '\0' && endptr[0] == '\0') 211 { 212 if (rawval >= INT_MIN && rawval <= INT_MAX) 213 rat.den = rawval; 214 else die("Option %s: Value %ld out of range for signed int\n", 215 arg->name, rawval); 216 } 217 else die("Option %s: Invalid character '%c'\n", arg->name, *endptr); 218 219 return rat; 220 } 221