args.c 6.08 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 16
 */


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

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

#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
26 27 28 29 30 31 32 33 34
struct arg arg_init(char **argv) {
  struct arg a;

  a.argv      = argv;
  a.argv_step = 1;
  a.name      = NULL;
  a.val       = NULL;
  a.def       = NULL;
  return a;
John Koleszar's avatar
John Koleszar committed
35 36
}

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

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

John Koleszar's avatar
John Koleszar committed
43
  arg = arg_init(argv);
John Koleszar's avatar
John Koleszar committed
44

John Koleszar's avatar
John Koleszar committed
45 46 47
  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
48

John Koleszar's avatar
John Koleszar committed
49 50 51 52
    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) {
53
    const size_t name_len = strlen(def->long_name);
John Koleszar's avatar
John Koleszar committed
54 55 56 57 58 59 60 61 62 63

    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')) {

      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
64
    }
John Koleszar's avatar
John Koleszar committed
65
  }
John Koleszar's avatar
John Koleszar committed
66

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

John Koleszar's avatar
John Koleszar committed
70 71
  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
72

John Koleszar's avatar
John Koleszar committed
73 74 75 76 77 78
  if (arg.name
      && (arg.val || !def->has_val)) {
    arg.def = def;
    *arg_ = arg;
    return 1;
  }
John Koleszar's avatar
John Koleszar committed
79

John Koleszar's avatar
John Koleszar committed
80
  return 0;
John Koleszar's avatar
John Koleszar committed
81 82 83
}


John Koleszar's avatar
John Koleszar committed
84 85 86
const char *arg_next(struct arg *arg) {
  if (arg->argv[0])
    arg->argv += arg->argv_step;
John Koleszar's avatar
John Koleszar committed
87

John Koleszar's avatar
John Koleszar committed
88
  return *arg->argv;
John Koleszar's avatar
John Koleszar committed
89 90 91
}


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

John Koleszar's avatar
John Koleszar committed
95 96 97
  memcpy(new_argv, argv, argc * sizeof(*argv));
  new_argv[argc] = NULL;
  return new_argv;
John Koleszar's avatar
John Koleszar committed
98 99 100
}


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

John Koleszar's avatar
John Koleszar committed
104 105 106 107
  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
108

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

John Koleszar's avatar
John Koleszar committed
112 113 114 115 116 117 118 119 120
      snprintf(option_text, 37, "-%s%s%s --%s%6s",
               def->short_name, short_val, comma,
               def->long_name, long_val);
    } else if (def->short_name)
      snprintf(option_text, 37, "-%s%s",
               def->short_name, short_val);
    else if (def->long_name)
      snprintf(option_text, 37, "          --%s%s",
               def->long_name, long_val);
John Koleszar's avatar
John Koleszar committed
121

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

John Koleszar's avatar
John Koleszar committed
124 125
    if (def->enums) {
      const struct arg_enum_list *listptr;
126

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

John Koleszar's avatar
John Koleszar committed
129 130 131
      for (listptr = def->enums; listptr->name; listptr++)
        fprintf(fp, "%s%s", listptr->name,
                listptr[1].name ? ", " : "\n");
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 136
}


John Koleszar's avatar
John Koleszar committed
137 138 139
unsigned int arg_parse_uint(const struct arg *arg) {
  long int   rawval;
  char      *endptr;
John Koleszar's avatar
John Koleszar committed
140

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

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

John Koleszar's avatar
John Koleszar committed
147 148 149
    die("Option %s: Value %ld out of range for unsigned int\n",
        arg->name, rawval);
  }
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 155
}


John Koleszar's avatar
John Koleszar committed
156 157 158
int arg_parse_int(const struct arg *arg) {
  long int   rawval;
  char      *endptr;
John Koleszar's avatar
John Koleszar committed
159

John Koleszar's avatar
John Koleszar committed
160
  rawval = strtol(arg->val, &endptr, 10);
John Koleszar's avatar
John Koleszar committed
161

John Koleszar's avatar
John Koleszar committed
162 163 164
  if (arg->val[0] != '\0' && endptr[0] == '\0') {
    if (rawval >= INT_MIN && rawval <= INT_MAX)
      return rawval;
John Koleszar's avatar
John Koleszar committed
165

John Koleszar's avatar
John Koleszar committed
166 167 168
    die("Option %s: Value %ld out of range for signed int\n",
        arg->name, rawval);
  }
John Koleszar's avatar
John Koleszar committed
169

John Koleszar's avatar
John Koleszar committed
170 171
  die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
  return 0;
John Koleszar's avatar
John Koleszar committed
172 173 174
}


John Koleszar's avatar
John Koleszar committed
175 176 177
struct vpx_rational {
  int num; /**< fraction numerator */
  int den; /**< fraction denominator */
John Koleszar's avatar
John Koleszar committed
178
};
John Koleszar's avatar
John Koleszar committed
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
struct vpx_rational arg_parse_rational(const struct arg *arg) {
  long int             rawval;
  char                *endptr;
  struct vpx_rational  rat;

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

  if (arg->val[0] != '\0' && endptr[0] == '/') {
    if (rawval >= INT_MIN && rawval <= INT_MAX)
      rat.num = rawval;
    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);

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

  if (arg->val[0] != '\0' && endptr[0] == '\0') {
    if (rawval >= INT_MIN && rawval <= INT_MAX)
      rat.den = rawval;
    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);

  return rat;
John Koleszar's avatar
John Koleszar committed
205
}
206 207


John Koleszar's avatar
John Koleszar committed
208 209 210 211
int arg_parse_enum(const struct arg *arg) {
  const struct arg_enum_list *listptr;
  long int                    rawval;
  char                       *endptr;
212

John Koleszar's avatar
John Koleszar committed
213 214 215 216 217 218 219 220
  /* 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++)
      if (listptr->val == rawval)
        return rawval;
  }
221

John Koleszar's avatar
John Koleszar committed
222 223 224 225 226 227 228
  /* Next see if it can be parsed as a string */
  for (listptr = arg->def->enums; listptr->name; listptr++)
    if (!strcmp(arg->val, listptr->name))
      return listptr->val;

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


John Koleszar's avatar
John Koleszar committed
232 233 234 235
int arg_parse_enum_or_int(const struct arg *arg) {
  if (arg->def->enums)
    return arg_parse_enum(arg);
  return arg_parse_int(arg);
236
}