in src/framework/consoleui.cpp [122:235]
void ConsoleUI::handleUsageHelp(const char * cpszUsage, const char * cpszHelp, const char * cpszHelpFlags) {
std::vector<const char *> opts; // Vector of possible option (start points)
unsigned int i;
apr_status_t rv;
unsigned int nHelpFlags;
if (cpszHelpFlags == NULL)
cpszHelpFlags = "[--help | -?]\t\n";
iv_cpszUsage[0] = cpszHelpFlags;
iv_cpszUsage[1] = cpszUsage;
iv_cpszHelp = cpszHelp;
// Step thru the usage msg to and create a vector addressing the start of each option
// Options can be switches or take a value, and be marked as optional (most options are
// are optional [!] but taftest_app requires one and only one of --config & --configs)
// --opt --opt <val> --opt=<val>
// [--opt] [--opt <val>] [--opt=<val>] [-c] [-f foo] [-x | -y]
// Assume a long option starts with -- preceeded by [ or whitespace
// Assume a short option starts with - preceeded by [ or space and is followed by ] or space
// First process help flags then the remainder of the usage message.
for ( i = 0; i < 2; ++i ) {
const char * str = iv_cpszUsage[i];
if ( *str == '-' && *++str == '-' ) // Check for initial -- where str[-1] would be bad!
opts.push_back(str);
while ((str = strchr(str+1, '-')) != NULL) {
if ( ( str[1]=='-' && (str[-1]=='[' || isspace(str[-1])) ) ||
( str[1]!='-' && isgraph(str[1]) && (str[-1]=='[' || str[-1]==' ') && (str[2]==']' || str[2]==' ') ) )
opts.push_back(++str);
}
if (i == 0)
nHelpFlags = opts.size();
}
iv_pOpts = (apr_getopt_option_t *)apr_palloc( consPool, (opts.size()+1) * sizeof(apr_getopt_option_t) );
// Process short and long options in two passes as must use a wierd value for optch to
// locate long options, so can have no more than 47 long options (1 - '0')
int j = 0;
const char * opt, * str;
int k = 0;
char helpChars[20];
for ( i = 0; i < opts.size(); ++i ) {
opt = opts[i];
if ( *opt == '-' ) { // Long option
str = strpbrk( ++opt, "]= \n" );
if (str == NULL) // Must be last option!
str = opt + strlen(opt);
iv_pOpts[j].name = apr_pstrndup(consPool, opt, str - opt);
iv_pOpts[j].has_arg = (*str == '=' || (*str == ' ' && *(str+1) == '<'));
iv_pOpts[j].optch = j+1; // Use 1-based index as "short" option
if (i < nHelpFlags)
helpChars[k++] = j+1;
++j;
}
}
iv_maxOptIndex = j; // Largest wierd value marking a long option
// NOTE: should check that this is < any alphanumeric char, i.e. < 48 ('0')
for ( i = 0; i < opts.size(); ++i ) {
opt = opts[i];
if ( *opt != '-' ) { // Short option
iv_pOpts[j].optch = *opt; // Use real character
iv_pOpts[j].name = NULL;
iv_pOpts[j++].has_arg = (opt[1] == ' ' && opt[2] != '|' );
if (i < nHelpFlags)
helpChars[k++] = *opt;
}
}
iv_pOpts[j].optch = 0; // Mark end of list
helpChars[k] = '\0';
#ifndef NDEBUG
// Dump all legal options when called with just 1 arg of "--"
if ( iv_argc == 2 && strcmp(iv_argv[1],"--")==0 )
debugDisplayOptions(j);
#endif
// Set up processing of interleaved options and arguments
apr_getopt_init(&iv_hGetopt, consPool, iv_argc, iv_argv);
iv_hGetopt->interleave = 1;
// Can't have more options than args!
iv_pFoundOpts = (found_opt_t *)apr_palloc(consPool, iv_argc * sizeof(found_opt_t));
iv_nFoundOpts = 0;
// Check that provided options are valid and save them.
int index;
const char * optarg;
bool needHelp = false;
while ((rv = apr_getopt_long(iv_hGetopt, iv_pOpts, &index, &optarg)) == APR_SUCCESS) {
iv_pFoundOpts[iv_nFoundOpts].index = index;
iv_pFoundOpts[iv_nFoundOpts++].value = optarg;
if (strchr(helpChars,index) != NULL)
needHelp = true;
}
// Two errors are: Invalid option & missing argument
// getopt prints these on error streamwith fprintf(stderr but can override
// via iv_hGetopt->errfn typedef void( apr_getopt_err_fn_t)(void *arg, const char *err,...)
if ( rv != APR_EOF )
displayUsage();
// Args are valid ... now check for the help flags
else
if (needHelp)
displayHelp();
}