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; }