]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/cmdline.cpp
Compilation fix for r74440 and STL builds.
[wxWidgets.git] / src / common / cmdline.cpp
index ffa7e5ba36eadb7addeab7962664097d219a2306..2d6feae46b7082a1af04b6814f896a51f5939703 100644 (file)
@@ -106,7 +106,7 @@ struct wxCmdLineOption
         type = typ;
         flags = fl;
 
         type = typ;
         flags = fl;
 
-        m_hasVal = false;
+        Reset();
     }
 
     // can't use union easily here, so just store all possible data fields, we
     }
 
     // can't use union easily here, so just store all possible data fields, we
@@ -141,9 +141,19 @@ struct wxCmdLineOption
         { Check(wxCMD_LINE_VAL_DATE); m_dateVal = val; m_hasVal = true; }
 #endif // wxUSE_DATETIME
 
         { Check(wxCMD_LINE_VAL_DATE); m_dateVal = val; m_hasVal = true; }
 #endif // wxUSE_DATETIME
 
-    void SetHasValue(bool hasValue = true) { m_hasVal = hasValue; }
+    void SetHasValue() { m_hasVal = true; }
     bool HasValue() const { return m_hasVal; }
 
     bool HasValue() const { return m_hasVal; }
 
+    void SetNegated() { m_isNegated = true; }
+    bool IsNegated() const { return m_isNegated; }
+
+    // Reset to the initial state, called before parsing another command line.
+    void Reset()
+    {
+        m_hasVal =
+        m_isNegated = false;
+    }
+
 public:
     wxCmdLineEntryType kind;
     wxString shortName,
 public:
     wxCmdLineEntryType kind;
     wxString shortName,
@@ -154,6 +164,7 @@ public:
 
 private:
     bool m_hasVal;
 
 private:
     bool m_hasVal;
+    bool m_isNegated;
 
     double m_doubleVal;
     long m_longVal;
 
     double m_doubleVal;
     long m_longVal;
@@ -518,18 +529,23 @@ void wxCmdLineParser::AddUsageText(const wxString& text)
 // ----------------------------------------------------------------------------
 
 bool wxCmdLineParser::Found(const wxString& name) const
 // ----------------------------------------------------------------------------
 
 bool wxCmdLineParser::Found(const wxString& name) const
+{
+    return FoundSwitch(name) != wxCMD_SWITCH_NOT_FOUND;
+}
+
+wxCmdLineSwitchState wxCmdLineParser::FoundSwitch(const wxString& name) const
 {
     int i = m_data->FindOption(name);
     if ( i == wxNOT_FOUND )
         i = m_data->FindOptionByLongName(name);
 
 {
     int i = m_data->FindOption(name);
     if ( i == wxNOT_FOUND )
         i = m_data->FindOptionByLongName(name);
 
-    wxCHECK_MSG( i != wxNOT_FOUND, false, wxT("unknown switch") );
+    wxCHECK_MSG( i != wxNOT_FOUND, wxCMD_SWITCH_NOT_FOUND, wxT("unknown switch") );
 
     wxCmdLineOption& opt = m_data->m_options[(size_t)i];
     if ( !opt.HasValue() )
 
     wxCmdLineOption& opt = m_data->m_options[(size_t)i];
     if ( !opt.HasValue() )
-        return false;
+        return wxCMD_SWITCH_NOT_FOUND;
 
 
-    return true;
+    return opt.IsNegated() ? wxCMD_SWITCH_OFF : wxCMD_SWITCH_ON;
 }
 
 bool wxCmdLineParser::Found(const wxString& name, wxString *value) const
 }
 
 bool wxCmdLineParser::Found(const wxString& name, wxString *value) const
@@ -627,8 +643,7 @@ void wxCmdLineParser::Reset()
 {
     for ( size_t i = 0; i < m_data->m_options.GetCount(); i++ )
     {
 {
     for ( size_t i = 0; i < m_data->m_options.GetCount(); i++ )
     {
-        wxCmdLineOption& opt = m_data->m_options[i];
-        opt.SetHasValue(false);
+        m_data->m_options[i].Reset();
     }
 }
 
     }
 }
 
@@ -692,11 +707,45 @@ int wxCmdLineParser::Parse(bool showUsage)
 
                 if (longOptionsEnabled)
                 {
 
                 if (longOptionsEnabled)
                 {
+                    wxString errorOpt;
+
                     optInd = m_data->FindOptionByLongName(name);
                     if ( optInd == wxNOT_FOUND )
                     {
                     optInd = m_data->FindOptionByLongName(name);
                     if ( optInd == wxNOT_FOUND )
                     {
-                        errorMsg << wxString::Format(_("Unknown long option '%s'"), name.c_str())
-                                 << wxT('\n');
+                        // Check if this could be a negatable long option.
+                        if ( name.Last() == '-' )
+                        {
+                            name.RemoveLast();
+
+                            optInd = m_data->FindOptionByLongName(name);
+                            if ( optInd != wxNOT_FOUND )
+                            {
+                                if ( !(m_data->m_options[optInd].flags &
+                                        wxCMD_LINE_SWITCH_NEGATABLE) )
+                                {
+                                    errorOpt.Printf
+                                             (
+                                              _("Option '%s' can't be negated"),
+                                              name
+                                             );
+                                    optInd = wxNOT_FOUND;
+                                }
+                            }
+                        }
+
+                        if ( optInd == wxNOT_FOUND )
+                        {
+                            if ( errorOpt.empty() )
+                            {
+                                errorOpt.Printf
+                                         (
+                                          _("Unknown long option '%s'"),
+                                          name
+                                         );
+                            }
+
+                            errorMsg << errorOpt << wxT('\n');
+                        }
                     }
                 }
                 else
                     }
                 }
                 else
@@ -755,6 +804,14 @@ int wxCmdLineParser::Parse(bool showUsage)
                     if ( m_data->m_options[(size_t)optInd].kind
                             == wxCMD_LINE_SWITCH )
                     {
                     if ( m_data->m_options[(size_t)optInd].kind
                             == wxCMD_LINE_SWITCH )
                     {
+                        // if the switch is negatable and it is just followed
+                        // by '-' the '-' is considered to be part of this
+                        // switch
+                        if ( (m_data->m_options[(size_t)optInd].flags &
+                                    wxCMD_LINE_SWITCH_NEGATABLE) &&
+                                arg[len] == '-' )
+                            ++len;
+
                         // pretend that all the rest of the argument is the
                         // next argument, in fact
                         wxString arg2 = arg[0u];
                         // pretend that all the rest of the argument is the
                         // next argument, in fact
                         wxString arg2 = arg[0u];
@@ -792,7 +849,10 @@ int wxCmdLineParser::Parse(bool showUsage)
             if ( opt.kind == wxCMD_LINE_SWITCH )
             {
                 // we must check that there is no value following the switch
             if ( opt.kind == wxCMD_LINE_SWITCH )
             {
                 // we must check that there is no value following the switch
-                if ( p != arg.end() )
+                bool negated = (opt.flags & wxCMD_LINE_SWITCH_NEGATABLE) &&
+                                    p != arg.end() && *p == '-';
+
+                if ( !negated && p != arg.end() )
                 {
                     errorMsg << wxString::Format(_("Unexpected characters following option '%s'."), name.c_str())
                              << wxT('\n');
                 {
                     errorMsg << wxString::Format(_("Unexpected characters following option '%s'."), name.c_str())
                              << wxT('\n');
@@ -802,6 +862,8 @@ int wxCmdLineParser::Parse(bool showUsage)
                 {
                     // nothing more to do
                     opt.SetHasValue();
                 {
                     // nothing more to do
                     opt.SetHasValue();
+                    if ( negated )
+                        opt.SetNegated();
 
                     if ( opt.flags & wxCMD_LINE_OPTION_HELP )
                     {
 
                     if ( opt.flags & wxCMD_LINE_OPTION_HELP )
                     {
@@ -907,8 +969,8 @@ int wxCmdLineParser::Parse(bool showUsage)
                         case wxCMD_LINE_VAL_DATE:
                             {
                                 wxDateTime dt;
                         case wxCMD_LINE_VAL_DATE:
                             {
                                 wxDateTime dt;
-                                wxString::const_iterator end;
-                                if ( !dt.ParseDate(value, &end) || end != value.end() )
+                                wxString::const_iterator endDate;
+                                if ( !dt.ParseDate(value, &endDate) || endDate != value.end() )
                                 {
                                     errorMsg << wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
                                                                  name.c_str(), value.c_str())
                                 {
                                     errorMsg << wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
                                                                  name.c_str(), value.c_str())
@@ -1095,7 +1157,7 @@ wxString wxCmdLineParser::GetUsageString() const
     for ( n = 0; n < count; n++ )
     {
         wxCmdLineOption& opt = m_data->m_options[n];
     for ( n = 0; n < count; n++ )
     {
         wxCmdLineOption& opt = m_data->m_options[n];
-        wxString option;
+        wxString option, negator;
 
         if ( opt.kind != wxCMD_LINE_USAGE_TEXT )
         {
 
         if ( opt.kind != wxCMD_LINE_USAGE_TEXT )
         {
@@ -1105,13 +1167,16 @@ wxString wxCmdLineParser::GetUsageString() const
                 usage << wxT('[');
             }
 
                 usage << wxT('[');
             }
 
+            if ( opt.flags & wxCMD_LINE_SWITCH_NEGATABLE )
+                negator = wxT("[-]");
+
             if ( !opt.shortName.empty() )
             {
             if ( !opt.shortName.empty() )
             {
-                usage << chSwitch << opt.shortName;
+                usage << chSwitch << opt.shortName << negator;
             }
             else if ( areLongOptionsEnabled && !opt.longName.empty() )
             {
             }
             else if ( areLongOptionsEnabled && !opt.longName.empty() )
             {
-                usage << wxT("--") << opt.longName;
+                usage << wxT("--") << opt.longName << negator;
             }
             else
             {
             }
             else
             {
@@ -1312,6 +1377,23 @@ static wxString GetLongOptionName(wxString::const_iterator p,
    Windows conventions for the command line handling, not Unix ones. For
    instance, backslash is not special except when it precedes double quote when
    it does quote it.
    Windows conventions for the command line handling, not Unix ones. For
    instance, backslash is not special except when it precedes double quote when
    it does quote it.
+
+   TODO: Rewrite this to follow the even more complicated rule used by Windows
+         CommandLineToArgv():
+
+    * A string of backslashes not followed by a quotation mark has no special
+      meaning.
+    * An even number of backslashes followed by a quotation mark is treated as
+      pairs of protected backslashes, followed by a word terminator.
+    * An odd number of backslashes followed by a quotation mark is treated as
+      pairs of protected backslashes, followed by a protected quotation mark.
+
+    See http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063629.aspx
+
+    It could also be useful to provide a converse function which is also
+    non-trivial, see
+
+    http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx
  */
 
 /* static */
  */
 
 /* static */