args.c 5.91 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5 6
 *  that can be found in the LICENSE file in the root of the source
 *  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.
John Koleszar's avatar
John Koleszar committed
9 10 11 12 13 14 15
 */

#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "args.h"

16
#include "vpx/vpx_integer.h"
17
#include "vpx_ports/msvc.h"
John Koleszar's avatar
John Koleszar committed
18 19 20 21 22 23 24

#if defined(__GNUC__) && __GNUC__
extern void die(const char *fmt, ...) __attribute__((noreturn));
#else
extern void die(const char *fmt, ...);
#endif

John Koleszar's avatar
John Koleszar committed
25 26 27
struct arg arg_init(char **argv) {
  struct arg a;

28
  a.argv = argv;
John Koleszar's avatar
John Koleszar committed
29
  a.argv_step = 1;
30 31 32
  a.name = NULL;
  a.val = NULL;
  a.def = NULL;
John Koleszar's avatar
John Koleszar committed
33
  return a;
John Koleszar's avatar
John Koleszar committed
34 35
}

John Koleszar's avatar
John Koleszar committed
36 37
int arg_match(struct arg *arg_, const struct arg_def *def, char **argv) {
  struct arg arg;
John Koleszar's avatar
John Koleszar committed
38

39
  if (!argv[0] || argv[0][0] != '-') return 0;
John Koleszar's avatar
John Koleszar committed
40

John Koleszar's avatar
John Koleszar committed
41
  arg = arg_init(argv);
John Koleszar's avatar
John Koleszar committed
42

43 44
  if (def->short_name && strlen(arg.argv[0]) == strlen(def->short_name) + 1 &&
      !strcmp(arg.argv[0] + 1, def->short_name)) {
John Koleszar's avatar
John Koleszar committed
45 46 47 48
    arg.name = arg.argv[0] + 1;
    arg.val = def->has_val ? arg.argv[1] : NULL;
    arg.argv_step = def->has_val ? 2 : 1;
  } else if (def->long_name) {
49
    const size_t name_len = strlen(def->long_name);
John Koleszar's avatar
John Koleszar committed
50

51 52 53 54
    if (strlen(arg.argv[0]) >= name_len + 2 && arg.argv[0][1] == '-' &&
        !strncmp(arg.argv[0] + 2, def->long_name, name_len) &&
        (arg.argv[0][name_len + 2] == '=' ||
         arg.argv[0][name_len + 2] == '\0')) {
John Koleszar's avatar
John Koleszar committed
55 56 57
      arg.name = arg.argv[0] + 2;
      arg.val = arg.name[name_len] == '=' ? arg.name + name_len + 1 : NULL;
      arg.argv_step = 1;
John Koleszar's avatar
John Koleszar committed
58
    }
John Koleszar's avatar
John Koleszar committed
59
  }
John Koleszar's avatar
John Koleszar committed
60

John Koleszar's avatar
John Koleszar committed
61 62
  if (arg.name && !arg.val && def->has_val)
    die("Error: option %s requires argument.\n", arg.name);
John Koleszar's avatar
John Koleszar committed
63

John Koleszar's avatar
John Koleszar committed
64 65
  if (arg.name && arg.val && !def->has_val)
    die("Error: option %s requires no argument.\n", arg.name);
John Koleszar's avatar
John Koleszar committed
66

67
  if (arg.name && (arg.val || !def->has_val)) {
John Koleszar's avatar
John Koleszar committed
68 69 70 71
    arg.def = def;
    *arg_ = arg;
    return 1;
  }
John Koleszar's avatar
John Koleszar committed
72

John Koleszar's avatar
John Koleszar committed
73
  return 0;
John Koleszar's avatar
John Koleszar committed
74 75
}

John Koleszar's avatar
John Koleszar committed
76
const char *arg_next(struct arg *arg) {
77
  if (arg->argv[0]) arg->argv += arg->argv_step;
John Koleszar's avatar
John Koleszar committed
78

John Koleszar's avatar
John Koleszar committed
79
  return *arg->argv;
John Koleszar's avatar
John Koleszar committed
80 81
}

John Koleszar's avatar
John Koleszar committed
82 83
char **argv_dup(int argc, const char **argv) {
  char **new_argv = malloc((argc + 1) * sizeof(*argv));
John Koleszar's avatar
John Koleszar committed
84

John Koleszar's avatar
John Koleszar committed
85 86 87
  memcpy(new_argv, argv, argc * sizeof(*argv));
  new_argv[argc] = NULL;
  return new_argv;
John Koleszar's avatar
John Koleszar committed
88 89
}

John Koleszar's avatar
John Koleszar committed
90
void arg_show_usage(FILE *fp, const struct arg_def *const *defs) {
91
  char option_text[40] = { 0 };
John Koleszar's avatar
John Koleszar committed
92

John Koleszar's avatar
John Koleszar committed
93 94 95 96
  for (; *defs; defs++) {
    const struct arg_def *def = *defs;
    char *short_val = def->has_val ? " <arg>" : "";
    char *long_val = def->has_val ? "=<arg>" : "";
John Koleszar's avatar
John Koleszar committed
97

John Koleszar's avatar
John Koleszar committed
98 99
    if (def->short_name && def->long_name) {
      char *comma = def->has_val ? "," : ",      ";
100

101 102
      snprintf(option_text, 37, "-%s%s%s --%s%6s", def->short_name, short_val,
               comma, def->long_name, long_val);
John Koleszar's avatar
John Koleszar committed
103
    } else if (def->short_name)
104
      snprintf(option_text, 37, "-%s%s", def->short_name, short_val);
John Koleszar's avatar
John Koleszar committed
105
    else if (def->long_name)
106
      snprintf(option_text, 37, "          --%s%s", def->long_name, long_val);
John Koleszar's avatar
John Koleszar committed
107

John Koleszar's avatar
John Koleszar committed
108
    fprintf(fp, "  %-37s\t%s\n", option_text, def->desc);
109

John Koleszar's avatar
John Koleszar committed
110 111
    if (def->enums) {
      const struct arg_enum_list *listptr;
112

John Koleszar's avatar
John Koleszar committed
113
      fprintf(fp, "  %-37s\t  ", "");
114

John Koleszar's avatar
John Koleszar committed
115
      for (listptr = def->enums; listptr->name; listptr++)
116
        fprintf(fp, "%s%s", listptr->name, listptr[1].name ? ", " : "\n");
John Koleszar's avatar
John Koleszar committed
117
    }
John Koleszar's avatar
John Koleszar committed
118
  }
John Koleszar's avatar
John Koleszar committed
119 120
}

John Koleszar's avatar
John Koleszar committed
121
unsigned int arg_parse_uint(const struct arg *arg) {
122
  uint32_t rawval;
123
  char *endptr;
John Koleszar's avatar
John Koleszar committed
124

Johann's avatar
Johann committed
125
  rawval = (uint32_t)strtoul(arg->val, &endptr, 10);
John Koleszar's avatar
John Koleszar committed
126

John Koleszar's avatar
John Koleszar committed
127
  if (arg->val[0] != '\0' && endptr[0] == '\0') {
128
    if (rawval <= UINT_MAX) return rawval;
John Koleszar's avatar
John Koleszar committed
129

130 131
    die("Option %s: Value %ld out of range for unsigned int\n", arg->name,
        rawval);
John Koleszar's avatar
John Koleszar committed
132
  }
John Koleszar's avatar
John Koleszar committed
133

John Koleszar's avatar
John Koleszar committed
134 135
  die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
  return 0;
John Koleszar's avatar
John Koleszar committed
136 137
}

John Koleszar's avatar
John Koleszar committed
138
int arg_parse_int(const struct arg *arg) {
139
  int32_t rawval;
140
  char *endptr;
John Koleszar's avatar
John Koleszar committed
141

Johann's avatar
Johann committed
142
  rawval = (int32_t)strtol(arg->val, &endptr, 10);
John Koleszar's avatar
John Koleszar committed
143

John Koleszar's avatar
John Koleszar committed
144
  if (arg->val[0] != '\0' && endptr[0] == '\0') {
145
    if (rawval >= INT_MIN && rawval <= INT_MAX) return (int)rawval;
John Koleszar's avatar
John Koleszar committed
146

147 148
    die("Option %s: Value %ld out of range for signed int\n", arg->name,
        rawval);
John Koleszar's avatar
John Koleszar committed
149
  }
John Koleszar's avatar
John Koleszar committed
150

John Koleszar's avatar
John Koleszar committed
151 152
  die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
  return 0;
John Koleszar's avatar
John Koleszar committed
153 154
}

John Koleszar's avatar
John Koleszar committed
155 156 157
struct vpx_rational {
  int num; /**< fraction numerator */
  int den; /**< fraction denominator */
John Koleszar's avatar
John Koleszar committed
158
};
John Koleszar's avatar
John Koleszar committed
159
struct vpx_rational arg_parse_rational(const struct arg *arg) {
160 161 162
  long int rawval;
  char *endptr;
  struct vpx_rational rat;
John Koleszar's avatar
John Koleszar committed
163 164 165 166 167 168

  /* parse numerator */
  rawval = strtol(arg->val, &endptr, 10);

  if (arg->val[0] != '\0' && endptr[0] == '/') {
    if (rawval >= INT_MIN && rawval <= INT_MAX)
169
      rat.num = (int)rawval;
170 171 172 173 174
    else
      die("Option %s: Value %ld out of range for signed int\n", arg->name,
          rawval);
  } else
    die("Option %s: Expected / at '%c'\n", arg->name, *endptr);
John Koleszar's avatar
John Koleszar committed
175 176 177 178 179 180

  /* parse denominator */
  rawval = strtol(endptr + 1, &endptr, 10);

  if (arg->val[0] != '\0' && endptr[0] == '\0') {
    if (rawval >= INT_MIN && rawval <= INT_MAX)
181
      rat.den = (int)rawval;
182 183 184 185 186
    else
      die("Option %s: Value %ld out of range for signed int\n", arg->name,
          rawval);
  } else
    die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
John Koleszar's avatar
John Koleszar committed
187 188

  return rat;
John Koleszar's avatar
John Koleszar committed
189
}
190

John Koleszar's avatar
John Koleszar committed
191 192
int arg_parse_enum(const struct arg *arg) {
  const struct arg_enum_list *listptr;
193 194
  long int rawval;
  char *endptr;
195

John Koleszar's avatar
John Koleszar committed
196 197 198 199 200
  /* First see if the value can be parsed as a raw value */
  rawval = strtol(arg->val, &endptr, 10);
  if (arg->val[0] != '\0' && endptr[0] == '\0') {
    /* Got a raw value, make sure it's valid */
    for (listptr = arg->def->enums; listptr->name; listptr++)
201
      if (listptr->val == rawval) return (int)rawval;
John Koleszar's avatar
John Koleszar committed
202
  }
203

John Koleszar's avatar
John Koleszar committed
204 205
  /* Next see if it can be parsed as a string */
  for (listptr = arg->def->enums; listptr->name; listptr++)
206
    if (!strcmp(arg->val, listptr->name)) return listptr->val;
John Koleszar's avatar
John Koleszar committed
207 208 209

  die("Option %s: Invalid value '%s'\n", arg->name, arg->val);
  return 0;
210 211
}

John Koleszar's avatar
John Koleszar committed
212
int arg_parse_enum_or_int(const struct arg *arg) {
213
  if (arg->def->enums) return arg_parse_enum(arg);
John Koleszar's avatar
John Koleszar committed
214
  return arg_parse_int(arg);
215
}