void ConsoleUI::handleUsageHelp()

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