Ejemplo n.º 1
0
    wxCmdLineOption(wxCmdLineEntryType k,
                    const wxString& shrt,
                    const wxString& lng,
                    const wxString& desc,
                    wxCmdLineParamType typ,
                    int fl)
    {
        wxASSERT_MSG( !shrt.empty() || !lng.empty(),
                      _T("option should have at least one name") );

        wxASSERT_MSG
            (
                GetShortOptionName(shrt).Len() == shrt.Len(),
                wxT("Short option contains invalid characters")
            );

        wxASSERT_MSG
            (
                GetLongOptionName(lng).Len() == lng.Len(),
                wxT("Long option contains invalid characters")
            );


        kind = k;

        shortName = shrt;
        longName = lng;
        description = desc;

        type = typ;
        flags = fl;

        m_hasVal = false;
    }
Ejemplo n.º 2
0
    wxCmdLineOption(wxCmdLineEntryType k,
                    const wxString& shrt,
                    const wxString& lng,
                    const wxString& desc,
                    wxCmdLineParamType typ,
                    int fl)
    {
        // wxCMD_LINE_USAGE_TEXT uses only description, shortName and longName is empty
        if ( k != wxCMD_LINE_USAGE_TEXT )
        {
            wxASSERT_MSG
            (
                !shrt.empty() || !lng.empty(),
                 wxT("option should have at least one name")
            );

            wxASSERT_MSG
            (
                GetShortOptionName(shrt.begin(), shrt.end()).Len() == shrt.Len(),
                wxT("Short option contains invalid characters")
            );

            wxASSERT_MSG
            (
                GetLongOptionName(lng.begin(), lng.end()).Len() == lng.Len(),
                wxT("Long option contains invalid characters")
            );
        }

        kind = k;

        shortName = shrt;
        longName = lng;
        description = desc;

        type = typ;
        flags = fl;

        m_hasVal = false;
        m_isNegated = false;
    }
Ejemplo n.º 3
0
int wxCmdLineParser::Parse(bool showUsage)
{
    bool maybeOption = true;    // can the following arg be an option?
    bool ok = true;             // true until an error is detected
    bool helpRequested = false; // true if "-h" was given
    bool hadRepeatableParam = false; // true if found param with MULTIPLE flag

    size_t currentParam = 0;    // the index in m_paramDesc

    size_t countParam = m_data->m_paramDesc.GetCount();
    wxString errorMsg;

    Reset();

    // parse everything
    wxString arg;
    size_t count = m_data->m_arguments.size();
    for ( size_t n = 1; ok && (n < count); n++ )    // 0 is program name
    {
        arg = m_data->m_arguments[n];

        // special case: "--" should be discarded and all following arguments
        // should be considered as parameters, even if they start with '-' and
        // not like options (this is POSIX-like)
        if ( arg == wxT("--") )
        {
            maybeOption = false;

            continue;
        }

        // empty argument or just '-' is not an option but a parameter
        if ( maybeOption && arg.length() > 1 &&
                // FIXME-UTF8: use wc_str() after removing ANSI build
                wxStrchr(m_data->m_switchChars.c_str(), arg[0u]) )
        {
            bool isLong;
            wxString name;
            int optInd = wxNOT_FOUND;   // init to suppress warnings

            // an option or a switch: find whether it's a long or a short one
            if ( arg.length() >= 3 && arg[0u] == wxT('-') && arg[1u] == wxT('-') )
            {
                // a long one
                isLong = true;

                // Skip leading "--"
                wxString::const_iterator p = arg.begin() + 2;

                bool longOptionsEnabled = AreLongOptionsEnabled();

                name = GetLongOptionName(p, arg.end());

                if (longOptionsEnabled)
                {
                    optInd = m_data->FindOptionByLongName(name);
                    if ( optInd == wxNOT_FOUND )
                    {
                        errorMsg << wxString::Format(_("Unknown long option '%s'"), name.c_str())
                                 << wxT('\n');
                    }
                }
                else
                {
                    optInd = wxNOT_FOUND; // Sanity check

                    // Print the argument including leading "--"
                    name.Prepend( wxT("--") );
                    errorMsg << wxString::Format(_("Unknown option '%s'"), name.c_str())
                             << wxT('\n');
                }

            }
            else // not a long option
            {
                isLong = false;

                // a short one: as they can be cumulated, we try to find the
                // longest substring which is a valid option
                wxString::const_iterator p = arg.begin() + 1;

                name = GetShortOptionName(p, arg.end());

                size_t len = name.length();
                do
                {
                    if ( len == 0 )
                    {
                        // we couldn't find a valid option name in the
                        // beginning of this string
                        errorMsg << wxString::Format(_("Unknown option '%s'"), name.c_str())
                                 << wxT('\n');

                        break;
                    }
                    else
                    {
                        optInd = m_data->FindOption(name.Left(len));

                        // will try with one character less the next time
                        len--;
                    }
                }
                while ( optInd == wxNOT_FOUND );

                len++;  // compensates extra len-- above
                if ( (optInd != wxNOT_FOUND) && (len != name.length()) )
                {
                    // first of all, the option name is only part of this
                    // string
                    name = name.Left(len);

                    // our option is only part of this argument, there is
                    // something else in it - it is either the value of this
                    // option or other switches if it is a switch
                    if ( m_data->m_options[(size_t)optInd].kind
                            == wxCMD_LINE_SWITCH )
                    {
                        // pretend that all the rest of the argument is the
                        // next argument, in fact
                        wxString arg2 = arg[0u];
                        arg2 += arg.Mid(len + 1); // +1 for leading '-'

                        m_data->m_arguments.insert
                            (m_data->m_arguments.begin() + n + 1, arg2);
                        count++;

                        // only leave the part which wasn't extracted into the
                        // next argument in this one
                        arg = arg.Left(len + 1);
                    }
                    //else: it's our value, we'll deal with it below
                }
            }

            if ( optInd == wxNOT_FOUND )
            {
                ok = false;

                continue;   // will break, in fact
            }

            // look at what follows:

            // +1 for leading '-'
            wxString::const_iterator p = arg.begin() + 1 + name.length();
            wxString::const_iterator end = arg.end();

            if ( isLong )
                ++p;    // for another leading '-'

            wxCmdLineOption& opt = m_data->m_options[(size_t)optInd];
            if ( opt.kind == wxCMD_LINE_SWITCH )
            {
                // we must check that there is no value following the switch
                if ( p != arg.end() )
                {
                    errorMsg << wxString::Format(_("Unexpected characters following option '%s'."), name.c_str())
                             << wxT('\n');
                    ok = false;
                }
                else // no value, as expected
                {
                    // nothing more to do
                    opt.SetHasValue();

                    if ( opt.flags & wxCMD_LINE_OPTION_HELP )
                    {
                        helpRequested = true;

                        // it's not an error, but we still stop here
                        ok = false;
                    }
                }
            }
            else // it's an option. not a switch
            {
                switch ( p == end ? '\0' : (*p).GetValue() )
                {
                    case '=':
                    case ':':
                        // the value follows
                        ++p;
                        break;

                    case '\0':
                        // the value is in the next argument
                        if ( ++n == count )
                        {
                            // ... but there is none
                            errorMsg << wxString::Format(_("Option '%s' requires a value."),
                                                         name.c_str())
                                     << wxT('\n');

                            ok = false;
                        }
                        else
                        {
                            // ... take it from there
                            p = m_data->m_arguments[n].begin();
                            end = m_data->m_arguments[n].end();
                        }
                        break;

                    default:
                        // the value is right here: this may be legal or
                        // not depending on the option style
                        if ( opt.flags & wxCMD_LINE_NEEDS_SEPARATOR )
                        {
                            errorMsg << wxString::Format(_("Separator expected after the option '%s'."),
                                                         name.c_str())
                                    << wxT('\n');

                            ok = false;
                        }
                }

                if ( ok )
                {
                    wxString value(p, end);
                    switch ( opt.type )
                    {
                        default:
                            wxFAIL_MSG( wxT("unknown option type") );
                            // still fall through

                        case wxCMD_LINE_VAL_STRING:
                            opt.SetStrVal(value);
                            break;

                        case wxCMD_LINE_VAL_NUMBER:
                            {
                                long val;
                                if ( value.ToLong(&val) )
                                {
                                    opt.SetLongVal(val);
                                }
                                else
                                {
                                    errorMsg << wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
                                                                 value.c_str(), name.c_str())
                                             << wxT('\n');

                                    ok = false;
                                }
                            }
                            break;

                        case wxCMD_LINE_VAL_DOUBLE:
                            {
                                double val;
                                if ( value.ToDouble(&val) )
                                {
                                    opt.SetDoubleVal(val);
                                }
                                else
                                {
                                    errorMsg << wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
                                                                 value.c_str(), name.c_str())
                                             << wxT('\n');

                                    ok = false;
                                }
                            }
                            break;

#if wxUSE_DATETIME
                        case wxCMD_LINE_VAL_DATE:
                            {
                                wxDateTime dt;
                                wxString::const_iterator end;
                                if ( !dt.ParseDate(value, &end) || end != value.end() )
                                {
                                    errorMsg << wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
                                                                 name.c_str(), value.c_str())
                                             << wxT('\n');

                                    ok = false;
                                }
                                else
                                {
                                    opt.SetDateVal(dt);
                                }
                            }
                            break;
#endif // wxUSE_DATETIME
                    }
                }
            }
        }
        else // not an option, must be a parameter
        {
            if ( currentParam < countParam )
            {
                wxCmdLineParam& param = m_data->m_paramDesc[currentParam];

                // TODO check the param type

                m_data->m_parameters.push_back(arg);

                if ( !(param.flags & wxCMD_LINE_PARAM_MULTIPLE) )
                {
                    currentParam++;
                }
                else
                {
                    wxASSERT_MSG( currentParam == countParam - 1,
                                  wxT("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );

                    // remember that we did have this last repeatable parameter
                    hadRepeatableParam = true;
                }
            }
            else
            {
                errorMsg << wxString::Format(_("Unexpected parameter '%s'"), arg.c_str())
                         << wxT('\n');

                ok = false;
            }
        }
    }

    // verify that all mandatory options were given
    if ( ok )
    {
        size_t countOpt = m_data->m_options.GetCount();
        for ( size_t n = 0; ok && (n < countOpt); n++ )
        {
            wxCmdLineOption& opt = m_data->m_options[n];
            if ( (opt.flags & wxCMD_LINE_OPTION_MANDATORY) && !opt.HasValue() )
            {
                wxString optName;
                if ( !opt.longName )
                {
                    optName = opt.shortName;
                }
                else
                {
                    if ( AreLongOptionsEnabled() )
                    {
                        optName.Printf( _("%s (or %s)"),
                                        opt.shortName.c_str(),
                                        opt.longName.c_str() );
                    }
                    else
                    {
                        optName.Printf( wxT("%s"),
                                        opt.shortName.c_str() );
                    }
                }

                errorMsg << wxString::Format(_("The value for the option '%s' must be specified."),
                                             optName.c_str())
                         << wxT('\n');

                ok = false;
            }
        }

        for ( ; ok && (currentParam < countParam); currentParam++ )
        {
            wxCmdLineParam& param = m_data->m_paramDesc[currentParam];
            if ( (currentParam == countParam - 1) &&
                 (param.flags & wxCMD_LINE_PARAM_MULTIPLE) &&
                 hadRepeatableParam )
            {
                // special case: currentParam wasn't incremented, but we did
                // have it, so don't give error
                continue;
            }

            if ( !(param.flags & wxCMD_LINE_PARAM_OPTIONAL) )
            {
                errorMsg << wxString::Format(_("The required parameter '%s' was not specified."),
                                             param.description.c_str())
                         << wxT('\n');

                ok = false;
            }
        }
    }

    // if there was an error during parsing the command line, show this error
    // and also the usage message if it had been requested
    if ( !ok && (!errorMsg.empty() || (helpRequested && showUsage)) )
    {
        wxMessageOutput* msgOut = wxMessageOutput::Get();
        if ( msgOut )
        {
            wxString usage;
            if ( showUsage )
                usage = GetUsageString();

            msgOut->Printf( wxT("%s%s"), usage.c_str(), errorMsg.c_str() );
        }
        else
        {
            wxFAIL_MSG( wxT("no wxMessageOutput object?") );
        }
    }

    return ok ? 0 : helpRequested ? -1 : 1;
}