[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

New apr_getopt_long implementation

From: Greg Hudson <ghudson_at_mit.edu>
Date: 2000-11-24 02:33:41 CET

So, I'm having no luck getting at the new apr repository to construct
a proper patch. (If anyone answered my earlier question to the apr
list, then I missed it; are there archives for that list anywhere?)

In the meantime, here is my implementation of the new apr_getopt_long
interface for people's review. (I didn't use fitz's code as a base
mostly because I couldn't easily get at it given my apr repository
problems. No intended slight.)

static apr_status_t serr(apr_getopt_t *os, const char *err, const char *str,
                         apr_status_t status)
{
    const char *progname;

    if (os->err) {
        progname = strrchr(os->argv[0], '/');
        progname = (progname != NULL) ? progname + 1 : os->argv[0];
        fprintf(stderr, "%s: %s: %s\n", progname, err, str);
    }
    return status;
}

static apr_status_t cerr(apr_getopt_t *os, const char *err, int ch,
                         apr_status_t status)
{
    char s[2];

    s[0] = ch;
    s[1] = '\0';
    return serr(os, err, s, status);
}

APR_DECLARE(apr_status_t) apr_getopt_long(apr_getopt_t *os,
                                          const apr_option_t *opts,
                                          int *optch, const char **optarg)
{
    const char *p;
    int i, len;

    /*
     * We can be in one of two states: in the middle of processing a
     * run of short options, or about to process a new argument.
     * Since the second case can lead to the first one, handle that
     * one first.
     */
    p = os->place;
    if (*p == '\0') {
        /* We're about to process a new argument. Make sure it's an option. */
        if (os->ind >= os->argc || *os->argv[os->ind] != '-')
            return APR_EOF;

        p = os->argv[os->ind++] + 1;
        if (*p == '-' && p[1] != '\0') { /* Long option */
            /* Search for the long option name in the caller's table. */
            p++;
            for (i = 0; opts[i].optch != 0; i++) {
                len = strlen(opts[i].name);
                if (strncmp(p, opts[i].name, len) == 0
                    && (p[len] == '\0' || p[len] == '='))
                    break;
            }
            if (opts[i].optch == 0) /* No match */
                return serr(os, "invalid option", p - 2, APR_BADCH);
            *optch = opts[i].optch;

            if (opts[i].has_arg) {
                if (p[len] == '=') /* Argument inline */
                    *optarg = p + len + 1;
                else if (os->ind >= os->argc) /* Argument missing */
                    return serr(os, "missing argument", p - 2, APR_BADARG);
                else /* Argument in next arg */
                    *optarg = os->argv[os->ind++];
            } else {
                *optarg = NULL;
                if (p[len] == '=')
                    return serr(os, "erroneous argument", p - 2, APR_BADARG);
            }
            return APR_SUCCESS;
        } else if (*p == '-') /* Bare "--"; we're done */
            return APR_EOF;
        else if (*p == '\0') /* Bare "-" is illegal */
            return serr(os, "invalid option", p, APR_BADCH);
    }

    /*
     * Now we're in a run of short options, and *p is the next one.
     * Look for it in the caller's table.
     */
    for (i = 0; opts[i].optch != 0; i++) {
        if (*p == opts[i].optch)
            break;
    }
    if (opts[i].optch == 0) /* No match */
        return cerr(os, "invalid option character", *p, APR_BADCH);
    *optch = *p++;

    if (opts[i].has_arg) {
        if (*p != '\0') /* Argument inline */
            *optarg = p;
        else if (os->ind >= os->argc) /* Argument missing */
            return cerr(os, "option requires an argument", *optch, APR_BADARG);
        else /* Argument in next arg */
            *optarg = os->argv[os->ind++];
        os->place = "";
    } else {
        *optarg = NULL;
        os->place = p;
    }

    return APR_SUCCESS;
}
Received on Sat Oct 21 14:36:15 2006

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.