190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber/*
2f71323e297a928af368937089d3ed71239786f86Andreas Huber *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber *
4f71323e297a928af368937089d3ed71239786f86Andreas Huber *  Use of this source code is governed by a BSD-style license
5f71323e297a928af368937089d3ed71239786f86Andreas Huber *  that can be found in the LICENSE file in the root of the source
6f71323e297a928af368937089d3ed71239786f86Andreas Huber *  tree. An additional intellectual property rights grant can be found
7f71323e297a928af368937089d3ed71239786f86Andreas Huber *  in the file PATENTS.  All contributing project authors may
8f71323e297a928af368937089d3ed71239786f86Andreas Huber *  be found in the AUTHORS file in the root of the source tree.
990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber */
1090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
1190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
1290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include <stdlib.h>
1390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include <string.h>
1490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include <limits.h>
1590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include "args.h"
1690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
1790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#ifdef _MSC_VER
1890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define snprintf _snprintf
1990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif
2090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
2190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#if defined(__GNUC__) && __GNUC__
2290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberextern void die(const char *fmt, ...) __attribute__((noreturn));
2390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#else
2490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberextern void die(const char *fmt, ...);
2590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif
2690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
2790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
2890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstruct arg arg_init(char **argv)
2990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{
3090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    struct arg a;
3190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
3290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    a.argv      = argv;
3390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    a.argv_step = 1;
3490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    a.name      = NULL;
3590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    a.val       = NULL;
3690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    a.def       = NULL;
3790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return a;
3890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
3990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
4090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberint arg_match(struct arg *arg_, const struct arg_def *def, char **argv)
4190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{
4290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    struct arg arg;
4390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
4490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (!argv[0] || argv[0][0] != '-')
4590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        return 0;
4690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
4790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    arg = arg_init(argv);
4890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
4990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (def->short_name
5090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        && strlen(arg.argv[0]) == strlen(def->short_name) + 1
5190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        && !strcmp(arg.argv[0] + 1, def->short_name))
5290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    {
5390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
5490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        arg.name = arg.argv[0] + 1;
5590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        arg.val = def->has_val ? arg.argv[1] : NULL;
5690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        arg.argv_step = def->has_val ? 2 : 1;
5790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
5890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    else if (def->long_name)
5990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    {
6090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        int name_len = strlen(def->long_name);
6190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
6290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        if (strlen(arg.argv[0]) >= name_len + 2
6390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            && arg.argv[0][1] == '-'
6490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            && !strncmp(arg.argv[0] + 2, def->long_name, name_len)
6590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            && (arg.argv[0][name_len+2] == '='
6690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                || arg.argv[0][name_len+2] == '\0'))
6790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        {
6890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
6990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            arg.name = arg.argv[0] + 2;
7090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            arg.val = arg.name[name_len] == '=' ? arg.name + name_len + 1 : NULL;
7190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            arg.argv_step = 1;
7290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        }
7390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
7490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
7590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (arg.name && !arg.val && def->has_val)
7690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        die("Error: option %s requires argument.\n", arg.name);
7790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
7890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (arg.name && arg.val && !def->has_val)
7990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        die("Error: option %s requires no argument.\n", arg.name);
8090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
8190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (arg.name
8290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        && (arg.val || !def->has_val))
8390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    {
8490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        arg.def = def;
8590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        *arg_ = arg;
8690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        return 1;
8790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
8890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
8990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return 0;
9090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
9190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
9290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
9390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberconst char *arg_next(struct arg *arg)
9490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{
9590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (arg->argv[0])
9690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        arg->argv += arg->argv_step;
9790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
9890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return *arg->argv;
9990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
10090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
10190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
10290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberchar **argv_dup(int argc, const char **argv)
10390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{
10490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    char **new_argv = malloc((argc + 1) * sizeof(*argv));
10590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
10690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    memcpy(new_argv, argv, argc * sizeof(*argv));
10790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    new_argv[argc] = NULL;
10890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return new_argv;
10990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
11090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
11190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
11290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Hubervoid arg_show_usage(FILE *fp, const struct arg_def *const *defs)
11390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{
11490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    char option_text[40] = {0};
11590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
11690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    for (; *defs; defs++)
11790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    {
11890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        const struct arg_def *def = *defs;
11990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        char *short_val = def->has_val ? " <arg>" : "";
12090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        char *long_val = def->has_val ? "=<arg>" : "";
12190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
12290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        if (def->short_name && def->long_name)
123538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        {
124538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber            char *comma = def->has_val ? "," : ",      ";
125538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
126538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber            snprintf(option_text, 37, "-%s%s%s --%s%6s",
127538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber                     def->short_name, short_val, comma,
12890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                     def->long_name, long_val);
129538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        }
13090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        else if (def->short_name)
13190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            snprintf(option_text, 37, "-%s%s",
13290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                     def->short_name, short_val);
13390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        else if (def->long_name)
13490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            snprintf(option_text, 37, "          --%s%s",
13590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                     def->long_name, long_val);
13690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
13790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        fprintf(fp, "  %-37s\t%s\n", option_text, def->desc);
13879f15823c34ae1e423108295e416213200bb280fAndreas Huber
13979f15823c34ae1e423108295e416213200bb280fAndreas Huber        if(def->enums)
14079f15823c34ae1e423108295e416213200bb280fAndreas Huber        {
14179f15823c34ae1e423108295e416213200bb280fAndreas Huber            const struct arg_enum_list *listptr;
14279f15823c34ae1e423108295e416213200bb280fAndreas Huber
14379f15823c34ae1e423108295e416213200bb280fAndreas Huber            fprintf(fp, "  %-37s\t  ", "");
14479f15823c34ae1e423108295e416213200bb280fAndreas Huber
14579f15823c34ae1e423108295e416213200bb280fAndreas Huber            for(listptr = def->enums; listptr->name; listptr++)
14679f15823c34ae1e423108295e416213200bb280fAndreas Huber                fprintf(fp, "%s%s", listptr->name,
14779f15823c34ae1e423108295e416213200bb280fAndreas Huber                        listptr[1].name ? ", " : "\n");
14879f15823c34ae1e423108295e416213200bb280fAndreas Huber        }
14990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
15090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
15190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
15290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
15390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberunsigned int arg_parse_uint(const struct arg *arg)
15490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{
15590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    long int   rawval;
15690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    char      *endptr;
15790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
15890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    rawval = strtol(arg->val, &endptr, 10);
15990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
16090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (arg->val[0] != '\0' && endptr[0] == '\0')
16190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    {
16290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        if (rawval >= 0 && rawval <= UINT_MAX)
16390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            return rawval;
16490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
16590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        die("Option %s: Value %ld out of range for unsigned int\n",
16690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            arg->name, rawval);
16790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
16890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
16990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
17090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return 0;
17190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
17290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
17390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
17490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberint arg_parse_int(const struct arg *arg)
17590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{
17690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    long int   rawval;
17790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    char      *endptr;
17890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
17990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    rawval = strtol(arg->val, &endptr, 10);
18090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
18190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (arg->val[0] != '\0' && endptr[0] == '\0')
18290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    {
18390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        if (rawval >= INT_MIN && rawval <= INT_MAX)
18490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            return rawval;
18590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
18690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        die("Option %s: Value %ld out of range for signed int\n",
18790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            arg->name, rawval);
18890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
18990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
19090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
19190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return 0;
19290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
19390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
19490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
19590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstruct vpx_rational
19690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{
19790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    int num; /**< fraction numerator */
19890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    int den; /**< fraction denominator */
19990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber};
20090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstruct vpx_rational arg_parse_rational(const struct arg *arg)
20190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{
20290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    long int             rawval;
20390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    char                *endptr;
20490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    struct vpx_rational  rat;
20590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
20690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    /* parse numerator */
20790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    rawval = strtol(arg->val, &endptr, 10);
20890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
20990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (arg->val[0] != '\0' && endptr[0] == '/')
21090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    {
21190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        if (rawval >= INT_MIN && rawval <= INT_MAX)
21290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            rat.num = rawval;
21390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        else die("Option %s: Value %ld out of range for signed int\n",
21490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                     arg->name, rawval);
21590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
21690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    else die("Option %s: Expected / at '%c'\n", arg->name, *endptr);
21790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
21890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    /* parse denominator */
21990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    rawval = strtol(endptr + 1, &endptr, 10);
22090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
22190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (arg->val[0] != '\0' && endptr[0] == '\0')
22290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    {
22390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        if (rawval >= INT_MIN && rawval <= INT_MAX)
22490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            rat.den = rawval;
22590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        else die("Option %s: Value %ld out of range for signed int\n",
22690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                     arg->name, rawval);
22790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
22890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    else die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
22990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
23090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return rat;
23190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
23279f15823c34ae1e423108295e416213200bb280fAndreas Huber
23379f15823c34ae1e423108295e416213200bb280fAndreas Huber
23479f15823c34ae1e423108295e416213200bb280fAndreas Huberint arg_parse_enum(const struct arg *arg)
23579f15823c34ae1e423108295e416213200bb280fAndreas Huber{
23679f15823c34ae1e423108295e416213200bb280fAndreas Huber    const struct arg_enum_list *listptr;
23779f15823c34ae1e423108295e416213200bb280fAndreas Huber    long int                    rawval;
23879f15823c34ae1e423108295e416213200bb280fAndreas Huber    char                       *endptr;
23979f15823c34ae1e423108295e416213200bb280fAndreas Huber
24079f15823c34ae1e423108295e416213200bb280fAndreas Huber    /* First see if the value can be parsed as a raw value */
24179f15823c34ae1e423108295e416213200bb280fAndreas Huber    rawval = strtol(arg->val, &endptr, 10);
24279f15823c34ae1e423108295e416213200bb280fAndreas Huber    if (arg->val[0] != '\0' && endptr[0] == '\0')
24379f15823c34ae1e423108295e416213200bb280fAndreas Huber    {
24479f15823c34ae1e423108295e416213200bb280fAndreas Huber        /* Got a raw value, make sure it's valid */
24579f15823c34ae1e423108295e416213200bb280fAndreas Huber        for(listptr = arg->def->enums; listptr->name; listptr++)
24679f15823c34ae1e423108295e416213200bb280fAndreas Huber            if(listptr->val == rawval)
24779f15823c34ae1e423108295e416213200bb280fAndreas Huber                return rawval;
24879f15823c34ae1e423108295e416213200bb280fAndreas Huber    }
24979f15823c34ae1e423108295e416213200bb280fAndreas Huber
25079f15823c34ae1e423108295e416213200bb280fAndreas Huber    /* Next see if it can be parsed as a string */
25179f15823c34ae1e423108295e416213200bb280fAndreas Huber    for(listptr = arg->def->enums; listptr->name; listptr++)
25279f15823c34ae1e423108295e416213200bb280fAndreas Huber        if(!strcmp(arg->val, listptr->name))
25379f15823c34ae1e423108295e416213200bb280fAndreas Huber            return listptr->val;
25479f15823c34ae1e423108295e416213200bb280fAndreas Huber
25579f15823c34ae1e423108295e416213200bb280fAndreas Huber    die("Option %s: Invalid value '%s'\n", arg->name, arg->val);
25679f15823c34ae1e423108295e416213200bb280fAndreas Huber    return 0;
25779f15823c34ae1e423108295e416213200bb280fAndreas Huber}
25879f15823c34ae1e423108295e416213200bb280fAndreas Huber
25979f15823c34ae1e423108295e416213200bb280fAndreas Huber
26079f15823c34ae1e423108295e416213200bb280fAndreas Huberint arg_parse_enum_or_int(const struct arg *arg)
26179f15823c34ae1e423108295e416213200bb280fAndreas Huber{
26279f15823c34ae1e423108295e416213200bb280fAndreas Huber    if(arg->def->enums)
26379f15823c34ae1e423108295e416213200bb280fAndreas Huber        return arg_parse_enum(arg);
26479f15823c34ae1e423108295e416213200bb280fAndreas Huber    return arg_parse_int(arg);
26579f15823c34ae1e423108295e416213200bb280fAndreas Huber}
266