Home | History | Annotate | Download | only in libvpx
      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