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