blob: 14b031040a4b70057e5fa9485c3d4e045c9842d0 [file] [log] [blame]
John Koleszar0ea50ce2010-05-18 11:58:33 -04001/*
John Koleszarc2140b82010-09-09 08:16:39 -04002 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar0ea50ce2010-05-18 11:58:33 -04003 *
John Koleszar94c52e42010-06-18 12:39:21 -04004 * Use of this source code is governed by a BSD-style license
John Koleszar09202d82010-06-04 16:19:40 -04005 * 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
John Koleszar94c52e42010-06-18 12:39:21 -04007 * in the file PATENTS. All contributing project authors may
John Koleszar09202d82010-06-04 16:19:40 -04008 * be found in the AUTHORS file in the root of the source tree.
John Koleszar0ea50ce2010-05-18 11:58:33 -04009 */
10
11
12#include <stdlib.h>
13#include <string.h>
14#include <limits.h>
15#include "args.h"
16
Johanncad0eca2015-05-07 16:41:33 -070017#include "vpx_ports/msvc.h"
John Koleszar0ea50ce2010-05-18 11:58:33 -040018
19#if defined(__GNUC__) && __GNUC__
20extern void die(const char *fmt, ...) __attribute__((noreturn));
21#else
22extern void die(const char *fmt, ...);
23#endif
24
25
John Koleszarc6b90392012-07-13 15:21:29 -070026struct arg arg_init(char **argv) {
27 struct arg a;
John Koleszar0ea50ce2010-05-18 11:58:33 -040028
John Koleszarc6b90392012-07-13 15:21:29 -070029 a.argv = argv;
30 a.argv_step = 1;
31 a.name = NULL;
32 a.val = NULL;
33 a.def = NULL;
34 return a;
John Koleszar0ea50ce2010-05-18 11:58:33 -040035}
36
John Koleszarc6b90392012-07-13 15:21:29 -070037int arg_match(struct arg *arg_, const struct arg_def *def, char **argv) {
38 struct arg arg;
John Koleszar0ea50ce2010-05-18 11:58:33 -040039
John Koleszarc6b90392012-07-13 15:21:29 -070040 if (!argv[0] || argv[0][0] != '-')
41 return 0;
John Koleszar0ea50ce2010-05-18 11:58:33 -040042
John Koleszarc6b90392012-07-13 15:21:29 -070043 arg = arg_init(argv);
John Koleszar0ea50ce2010-05-18 11:58:33 -040044
John Koleszarc6b90392012-07-13 15:21:29 -070045 if (def->short_name
46 && strlen(arg.argv[0]) == strlen(def->short_name) + 1
47 && !strcmp(arg.argv[0] + 1, def->short_name)) {
John Koleszar0ea50ce2010-05-18 11:58:33 -040048
John Koleszarc6b90392012-07-13 15:21:29 -070049 arg.name = arg.argv[0] + 1;
50 arg.val = def->has_val ? arg.argv[1] : NULL;
51 arg.argv_step = def->has_val ? 2 : 1;
52 } else if (def->long_name) {
John Koleszar82b1a342012-11-06 12:08:05 -080053 const size_t name_len = strlen(def->long_name);
John Koleszarc6b90392012-07-13 15:21:29 -070054
55 if (strlen(arg.argv[0]) >= name_len + 2
56 && arg.argv[0][1] == '-'
57 && !strncmp(arg.argv[0] + 2, def->long_name, name_len)
58 && (arg.argv[0][name_len + 2] == '='
59 || arg.argv[0][name_len + 2] == '\0')) {
60
61 arg.name = arg.argv[0] + 2;
62 arg.val = arg.name[name_len] == '=' ? arg.name + name_len + 1 : NULL;
63 arg.argv_step = 1;
John Koleszar0ea50ce2010-05-18 11:58:33 -040064 }
John Koleszarc6b90392012-07-13 15:21:29 -070065 }
66
67 if (arg.name && !arg.val && def->has_val)
68 die("Error: option %s requires argument.\n", arg.name);
69
70 if (arg.name && arg.val && !def->has_val)
71 die("Error: option %s requires no argument.\n", arg.name);
72
73 if (arg.name
74 && (arg.val || !def->has_val)) {
75 arg.def = def;
76 *arg_ = arg;
77 return 1;
78 }
79
80 return 0;
81}
82
83
84const char *arg_next(struct arg *arg) {
85 if (arg->argv[0])
86 arg->argv += arg->argv_step;
87
88 return *arg->argv;
89}
90
91
92char **argv_dup(int argc, const char **argv) {
93 char **new_argv = malloc((argc + 1) * sizeof(*argv));
94
95 memcpy(new_argv, argv, argc * sizeof(*argv));
96 new_argv[argc] = NULL;
97 return new_argv;
98}
99
100
101void arg_show_usage(FILE *fp, const struct arg_def *const *defs) {
102 char option_text[40] = {0};
103
104 for (; *defs; defs++) {
105 const struct arg_def *def = *defs;
106 char *short_val = def->has_val ? " <arg>" : "";
107 char *long_val = def->has_val ? "=<arg>" : "";
108
109 if (def->short_name && def->long_name) {
110 char *comma = def->has_val ? "," : ", ";
111
112 snprintf(option_text, 37, "-%s%s%s --%s%6s",
113 def->short_name, short_val, comma,
114 def->long_name, long_val);
115 } else if (def->short_name)
116 snprintf(option_text, 37, "-%s%s",
117 def->short_name, short_val);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400118 else if (def->long_name)
John Koleszarc6b90392012-07-13 15:21:29 -0700119 snprintf(option_text, 37, " --%s%s",
120 def->long_name, long_val);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400121
John Koleszarc6b90392012-07-13 15:21:29 -0700122 fprintf(fp, " %-37s\t%s\n", option_text, def->desc);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400123
John Koleszarc6b90392012-07-13 15:21:29 -0700124 if (def->enums) {
125 const struct arg_enum_list *listptr;
126
127 fprintf(fp, " %-37s\t ", "");
128
129 for (listptr = def->enums; listptr->name; listptr++)
130 fprintf(fp, "%s%s", listptr->name,
131 listptr[1].name ? ", " : "\n");
John Koleszar0ea50ce2010-05-18 11:58:33 -0400132 }
John Koleszarc6b90392012-07-13 15:21:29 -0700133 }
John Koleszar0ea50ce2010-05-18 11:58:33 -0400134}
135
136
John Koleszarc6b90392012-07-13 15:21:29 -0700137unsigned int arg_parse_uint(const struct arg *arg) {
138 long int rawval;
139 char *endptr;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400140
John Koleszarc6b90392012-07-13 15:21:29 -0700141 rawval = strtol(arg->val, &endptr, 10);
142
143 if (arg->val[0] != '\0' && endptr[0] == '\0') {
144 if (rawval >= 0 && rawval <= UINT_MAX)
145 return rawval;
146
147 die("Option %s: Value %ld out of range for unsigned int\n",
148 arg->name, rawval);
149 }
150
151 die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
152 return 0;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400153}
154
155
John Koleszarc6b90392012-07-13 15:21:29 -0700156int arg_parse_int(const struct arg *arg) {
157 long int rawval;
158 char *endptr;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400159
John Koleszarc6b90392012-07-13 15:21:29 -0700160 rawval = strtol(arg->val, &endptr, 10);
161
162 if (arg->val[0] != '\0' && endptr[0] == '\0') {
163 if (rawval >= INT_MIN && rawval <= INT_MAX)
164 return rawval;
165
166 die("Option %s: Value %ld out of range for signed int\n",
167 arg->name, rawval);
168 }
169
170 die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
171 return 0;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400172}
173
174
John Koleszarc6b90392012-07-13 15:21:29 -0700175struct vpx_rational {
176 int num; /**< fraction numerator */
177 int den; /**< fraction denominator */
John Koleszar0ea50ce2010-05-18 11:58:33 -0400178};
John Koleszarc6b90392012-07-13 15:21:29 -0700179struct vpx_rational arg_parse_rational(const struct arg *arg) {
180 long int rawval;
181 char *endptr;
182 struct vpx_rational rat;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400183
John Koleszarc6b90392012-07-13 15:21:29 -0700184 /* parse numerator */
185 rawval = strtol(arg->val, &endptr, 10);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400186
John Koleszarc6b90392012-07-13 15:21:29 -0700187 if (arg->val[0] != '\0' && endptr[0] == '/') {
188 if (rawval >= INT_MIN && rawval <= INT_MAX)
189 rat.num = rawval;
190 else die("Option %s: Value %ld out of range for signed int\n",
191 arg->name, rawval);
192 } else die("Option %s: Expected / at '%c'\n", arg->name, *endptr);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400193
John Koleszarc6b90392012-07-13 15:21:29 -0700194 /* parse denominator */
195 rawval = strtol(endptr + 1, &endptr, 10);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400196
John Koleszarc6b90392012-07-13 15:21:29 -0700197 if (arg->val[0] != '\0' && endptr[0] == '\0') {
198 if (rawval >= INT_MIN && rawval <= INT_MAX)
199 rat.den = rawval;
200 else die("Option %s: Value %ld out of range for signed int\n",
201 arg->name, rawval);
202 } else die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400203
John Koleszarc6b90392012-07-13 15:21:29 -0700204 return rat;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400205}
John Koleszarb0da9b32010-12-17 09:43:39 -0500206
207
John Koleszarc6b90392012-07-13 15:21:29 -0700208int arg_parse_enum(const struct arg *arg) {
209 const struct arg_enum_list *listptr;
210 long int rawval;
211 char *endptr;
John Koleszarb0da9b32010-12-17 09:43:39 -0500212
John Koleszarc6b90392012-07-13 15:21:29 -0700213 /* First see if the value can be parsed as a raw value */
214 rawval = strtol(arg->val, &endptr, 10);
215 if (arg->val[0] != '\0' && endptr[0] == '\0') {
216 /* Got a raw value, make sure it's valid */
217 for (listptr = arg->def->enums; listptr->name; listptr++)
218 if (listptr->val == rawval)
219 return rawval;
220 }
John Koleszarb0da9b32010-12-17 09:43:39 -0500221
John Koleszarc6b90392012-07-13 15:21:29 -0700222 /* Next see if it can be parsed as a string */
223 for (listptr = arg->def->enums; listptr->name; listptr++)
224 if (!strcmp(arg->val, listptr->name))
225 return listptr->val;
John Koleszarb0da9b32010-12-17 09:43:39 -0500226
John Koleszarc6b90392012-07-13 15:21:29 -0700227 die("Option %s: Invalid value '%s'\n", arg->name, arg->val);
228 return 0;
John Koleszarb0da9b32010-12-17 09:43:39 -0500229}
230
231
John Koleszarc6b90392012-07-13 15:21:29 -0700232int arg_parse_enum_or_int(const struct arg *arg) {
233 if (arg->def->enums)
234 return arg_parse_enum(arg);
235 return arg_parse_int(arg);
John Koleszarb0da9b32010-12-17 09:43:39 -0500236}