Closed by commit rL212500 (authored by @zturner).

REPOSITORY
  rL LLVM

http://reviews.llvm.org/D4373

Files:
  lldb/trunk/include/lldb/Host/OptionParser.h
  lldb/trunk/include/lldb/Interpreter/CommandOptionValidators.h
  lldb/trunk/include/lldb/Interpreter/Options.h
  lldb/trunk/include/lldb/lldb-private-types.h
  lldb/trunk/source/Commands/CommandObjectPlatform.cpp
  lldb/trunk/source/Interpreter/Args.cpp
  lldb/trunk/source/Interpreter/CMakeLists.txt
  lldb/trunk/source/Interpreter/CommandOptionValidators.cpp
  lldb/trunk/source/Interpreter/Options.cpp
Index: lldb/trunk/include/lldb/Interpreter/Options.h
===================================================================
--- lldb/trunk/include/lldb/Interpreter/Options.h
+++ lldb/trunk/include/lldb/Interpreter/Options.h
@@ -159,7 +159,7 @@
 
     void
     OutputFormattedUsageText (Stream &strm,
-                              const char *text,
+                              const OptionDefinition &option_def,
                               uint32_t output_max_columns);
 
     void
@@ -301,6 +301,12 @@
                                     int max_return_elements,
                                     bool &word_complete,
                                     StringList &matches);
+
+    CommandInterpreter&
+    GetInterpreter()
+    {
+        return m_interpreter;
+    }
     
 protected:
     // This is a set of options expressed as indexes into the options table for this Option.
Index: lldb/trunk/include/lldb/Interpreter/CommandOptionValidators.h
===================================================================
--- lldb/trunk/include/lldb/Interpreter/CommandOptionValidators.h
+++ lldb/trunk/include/lldb/Interpreter/CommandOptionValidators.h
@@ -0,0 +1,30 @@
+//===-- CommandOptionValidators.h -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandOptionValidators_h_
+#define liblldb_CommandOptionValidators_h_
+
+#include "lldb/lldb-private-types.h"
+
+namespace lldb_private {
+
+class Platform;
+class ExecutionContext;
+
+class PosixPlatformCommandOptionValidator : public OptionValidator
+{
+    virtual bool IsValid(Platform &platform, ExecutionContext &target) const;
+    virtual const char* ShortConditionString() const;
+    virtual const char* LongConditionString() const;
+};
+
+} // namespace lldb_private
+
+
+#endif  // liblldb_CommandOptionValidators_h_
Index: lldb/trunk/include/lldb/Host/OptionParser.h
===================================================================
--- lldb/trunk/include/lldb/Host/OptionParser.h
+++ lldb/trunk/include/lldb/Host/OptionParser.h
@@ -16,18 +16,17 @@
 
 namespace lldb_private {
 
-typedef struct Option
+struct OptionDefinition;
+
+struct Option
 {
-    // name of long option
-    const char *name;
-    // one of no_argument, required_argument, and optional_argument:
-    // whether option takes an argument
-    int has_arg;
+    // The definition of the option that this refers to.
+    const OptionDefinition *definition;
     // if not NULL, set *flag to val when option found
     int *flag;
     // if flag not NULL, value to set *flag to; else return value
     int val;
-} Option;
+};
 
 class OptionParser
 {
Index: lldb/trunk/include/lldb/lldb-private-types.h
===================================================================
--- lldb/trunk/include/lldb/lldb-private-types.h
+++ lldb/trunk/include/lldb/lldb-private-types.h
@@ -16,6 +16,9 @@
 
 namespace lldb_private
 {
+    class Platform;
+    class ExecutionContext;
+
     //----------------------------------------------------------------------
     // Every register is described in detail including its name, alternate
     // name (optional), encoding, size in bytes and the default display
@@ -55,11 +58,12 @@
     struct OptionValidator
     {
         virtual ~OptionValidator() { }
-        virtual bool IsValid() const = 0;
-        virtual const char * ValidConditionString() const = 0;
+        virtual bool IsValid(Platform &platform, ExecutionContext &target) const = 0;
+        virtual const char * ShortConditionString() const = 0;
+        virtual const char * LongConditionString() const = 0;
     };
     
-    typedef struct
+    struct OptionDefinition
     {
         uint32_t usage_mask;                     // Used to mark options that can be used together.  If (1 << n & usage_mask) != 0
                                                  // then this option belongs to option set n.
@@ -73,7 +77,7 @@
         lldb::CommandArgumentType argument_type; // Type of argument this option takes
         const char *usage_text;                  // Full text explaining what this options does and what (if any) argument to
                                                  // pass it.
-    } OptionDefinition;
+    };
 
 } // namespace lldb_private
 
Index: lldb/trunk/source/Commands/CommandObjectPlatform.cpp
===================================================================
--- lldb/trunk/source/Commands/CommandObjectPlatform.cpp
+++ lldb/trunk/source/Commands/CommandObjectPlatform.cpp
@@ -21,6 +21,7 @@
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Interpreter/Args.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandOptionValidators.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
 #include "lldb/Interpreter/OptionGroupFile.h"
 #include "lldb/Interpreter/OptionGroupPlatform.h"
@@ -1644,6 +1645,11 @@
     CommandOptions m_options;
 };
 
+namespace
+{
+    PosixPlatformCommandOptionValidator g_posix_validator;
+}
+
 OptionDefinition
 CommandObjectPlatformProcessList::CommandOptions::g_option_table[] =
 {
@@ -1654,10 +1660,10 @@
 { LLDB_OPT_SET_5            , true , "contains"   , 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName      , "Find processes with executable basenames that contain a string." },
 { LLDB_OPT_SET_6            , true , "regex"      , 'r', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." },
 { LLDB_OPT_SET_FROM_TO(2, 6), false, "parent"     , 'P', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid              , "Find processes that have a matching parent process ID." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "uid"        , 'u', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching user ID." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "euid"       , 'U', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching effective user ID." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "gid"        , 'g', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching group ID." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "egid"       , 'G', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching effective group ID." },
+{ LLDB_OPT_SET_FROM_TO(2, 6), false, "uid"        , 'u', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching user ID." },
+{ LLDB_OPT_SET_FROM_TO(2, 6), false, "euid"       , 'U', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching effective user ID." },
+{ LLDB_OPT_SET_FROM_TO(2, 6), false, "gid"        , 'g', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching group ID." },
+{ LLDB_OPT_SET_FROM_TO(2, 6), false, "egid"       , 'G', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching effective group ID." },
 { LLDB_OPT_SET_FROM_TO(2, 6), false, "arch"       , 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeArchitecture     , "Find processes that have a matching architecture." },
 { LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args"  , 'A', OptionParser::eNoArgument      , NULL, NULL, 0, eArgTypeNone             , "Show process arguments instead of the process executable basename." },
 { LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose"    , 'v', OptionParser::eNoArgument      , NULL, NULL, 0, eArgTypeNone             , "Enable verbose output." },
Index: lldb/trunk/source/Interpreter/CMakeLists.txt
===================================================================
--- lldb/trunk/source/Interpreter/CMakeLists.txt
+++ lldb/trunk/source/Interpreter/CMakeLists.txt
@@ -7,6 +7,7 @@
   CommandObject.cpp
   CommandObjectRegexCommand.cpp
   CommandObjectScript.cpp
+  CommandOptionValidators.cpp
   CommandReturnObject.cpp
   OptionGroupArchitecture.cpp
   OptionGroupBoolean.cpp
Index: lldb/trunk/source/Interpreter/Options.cpp
===================================================================
--- lldb/trunk/source/Interpreter/Options.cpp
+++ lldb/trunk/source/Interpreter/Options.cpp
@@ -277,8 +277,7 @@
         {
             const int short_opt = opt_defs[i].short_option;
 
-            m_getopt_table[i].name    = opt_defs[i].long_option;
-            m_getopt_table[i].has_arg = opt_defs[i].option_has_arg;
+            m_getopt_table[i].definition = &opt_defs[i];
             m_getopt_table[i].flag    = nullptr;
             m_getopt_table[i].val     = short_opt;
 
@@ -297,25 +296,24 @@
                                 opt_defs[i].long_option,
                                 short_opt,
                                 pos->second,
-                                m_getopt_table[pos->second].name,
+                                m_getopt_table[pos->second].definition->long_option,
                                 opt_defs[i].long_option);
                 else
                     Host::SystemLog (Host::eSystemLogError, "option[%u] --%s has a short option 0x%x that conflicts with option[%u] --%s, short option won't be used for --%s\n",
                                 i,
                                 opt_defs[i].long_option,
                                 short_opt,
                                 pos->second,
-                                m_getopt_table[pos->second].name,
+                                m_getopt_table[pos->second].definition->long_option,
                                 opt_defs[i].long_option);
             }
         }
 
         //getopt_long_only requires a NULL final entry in the table:
 
-        m_getopt_table[i].name    = nullptr;
-        m_getopt_table[i].has_arg = 0;
-        m_getopt_table[i].flag    = nullptr;
-        m_getopt_table[i].val     = 0;
+        m_getopt_table[i].definition    = nullptr;
+        m_getopt_table[i].flag          = nullptr;
+        m_getopt_table[i].val           = 0;
     }
 
     if (m_getopt_table.empty())
@@ -336,18 +334,29 @@
 Options::OutputFormattedUsageText
 (
     Stream &strm,
-    const char *text,
+    const OptionDefinition &option_def,
     uint32_t output_max_columns
 )
 {
-    int len = strlen (text);
+    std::string actual_text;
+    if (option_def.validator)
+    {
+        const char *condition = option_def.validator->ShortConditionString();
+        if (condition)
+        {
+            actual_text = "[";
+            actual_text.append(condition);
+            actual_text.append("] ");
+        }
+    }
+    actual_text.append(option_def.usage_text);
 
     // Will it all fit on one line?
 
-    if (static_cast<uint32_t>(len + strm.GetIndentLevel()) < output_max_columns)
+    if (static_cast<uint32_t>(actual_text.length() + strm.GetIndentLevel()) < output_max_columns)
     {
         // Output it as a single line.
-        strm.Indent (text);
+        strm.Indent (actual_text.c_str());
         strm.EOL();
     }
     else
@@ -357,13 +366,13 @@
         int text_width = output_max_columns - strm.GetIndentLevel() - 1;
         int start = 0;
         int end = start;
-        int final_end = strlen (text);
+        int final_end = actual_text.length();
         int sub_len;
 
         while (end < final_end)
         {
             // Don't start the 'text' on a space, since we're already outputting the indentation.
-            while ((start < final_end) && (text[start] == ' '))
+            while ((start < final_end) && (actual_text[start] == ' '))
                 start++;
 
             end = start + text_width;
@@ -373,7 +382,7 @@
             {
                 // If we're not at the end of the text, make sure we break the line on white space.
                 while (end > start
-                       && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
+                       && actual_text[end] != ' ' && actual_text[end] != '\t' && actual_text[end] != '\n')
                     end--;
             }
 
@@ -383,7 +392,7 @@
             strm.Indent();
             assert (start < final_end);
             assert (start + sub_len <= final_end);
-            strm.Write(text + start, sub_len);
+            strm.Write(actual_text.c_str() + start, sub_len);
             start = end + 1;
         }
         strm.EOL();
@@ -630,7 +639,7 @@
     strm.Printf ("\n\n");
 
     // Now print out all the detailed information about the various options:  long form, short form and help text:
-    //   --long_name <argument>  ( -short <argument> )
+    //   -short <argument> ( --long_name <argument> )
     //   help text
 
     // This variable is used to keep track of which options' info we've printed out, because some options can be in
@@ -683,7 +692,7 @@
         
         if (opt_defs[i].usage_text)
             OutputFormattedUsageText (strm,
-                                      opt_defs[i].usage_text,
+                                      opt_defs[i],
                                       screen_width);
         if (opt_defs[i].enum_values != nullptr)
         {
Index: lldb/trunk/source/Interpreter/Args.cpp
===================================================================
--- lldb/trunk/source/Interpreter/Args.cpp
+++ lldb/trunk/source/Interpreter/Args.cpp
@@ -20,6 +20,7 @@
 #include "lldb/Core/StreamString.h"
 #include "lldb/DataFormatters/FormatManager.h"
 #include "lldb/Interpreter/Options.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
 #include "lldb/Target/Process.h"
 //#include "lldb/Target/RegisterContext.h"
@@ -627,14 +628,14 @@
         return error;
     }
 
-    for (int i=0; long_options[i].name != nullptr; ++i)
+    for (int i=0; long_options[i].definition != nullptr; ++i)
     {
         if (long_options[i].flag == nullptr)
         {
             if (isprint8(long_options[i].val))
             {
                 sstr << (char)long_options[i].val;
-                switch (long_options[i].has_arg)
+                switch (long_options[i].definition->option_has_arg)
                 {
                 default:
                 case OptionParser::eNoArgument:                       break;
@@ -673,7 +674,7 @@
         if (long_options_index == -1)
         {
             for (int i=0;
-                 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
+                 long_options[i].definition || long_options[i].flag || long_options[i].val;
                  ++i)
             {
                 if (long_options[i].val == val)
@@ -686,8 +687,18 @@
         // Call the callback with the option
         if (long_options_index >= 0)
         {
-            error = options.SetOptionValue(long_options_index,
-                                           long_options[long_options_index].has_arg == OptionParser::eNoArgument ? nullptr : OptionParser::GetOptionArgument());
+            const OptionDefinition *def = long_options[long_options_index].definition;
+            CommandInterpreter &interpreter = options.GetInterpreter();
+            OptionValidator *validator = def->validator;
+            if (validator && !validator->IsValid(*interpreter.GetPlatform(true), interpreter.GetExecutionContext()))
+            {
+                error.SetErrorStringWithFormat("Option \"%s\" invalid.  %s", def->long_option, def->validator->LongConditionString());
+            }
+            else
+            {
+                error = options.SetOptionValue(long_options_index,
+                                               (def->option_has_arg == OptionParser::eNoArgument) ? nullptr : OptionParser::GetOptionArgument());
+            }
         }
         else
         {
@@ -1222,7 +1233,7 @@
     char short_buffer[3];
     char long_buffer[255];
     ::snprintf (short_buffer, sizeof (short_buffer), "-%c", long_options[long_options_index].val);
-    ::snprintf (long_buffer, sizeof (long_buffer),  "--%s", long_options[long_options_index].name);
+    ::snprintf (long_buffer, sizeof (long_buffer),  "--%s", long_options[long_options_index].definition->long_option);
     size_t end = GetArgumentCount ();
     size_t idx = 0;
     while (idx < end)
@@ -1278,12 +1289,12 @@
         return;
     }
 
-    for (i = 0; long_options[i].name != nullptr; ++i)
+    for (i = 0; long_options[i].definition != nullptr; ++i)
     {
         if (long_options[i].flag == nullptr)
         {
             sstr << (char) long_options[i].val;
-            switch (long_options[i].has_arg)
+            switch (long_options[i].definition->option_has_arg)
             {
                 default:
                 case OptionParser::eNoArgument:
@@ -1328,7 +1339,7 @@
         if (long_options_index == -1)
         {
             for (int j = 0;
-                 long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
+                 long_options[j].definition || long_options[j].flag || long_options[j].val;
                  ++j)
             {
                 if (long_options[j].val == val)
@@ -1344,8 +1355,10 @@
         {
             StreamString option_str;
             option_str.Printf ("-%c", val);
+            const OptionDefinition *def = long_options[long_options_index].definition;
+            int has_arg = (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
 
-            switch (long_options[long_options_index].has_arg)
+            switch (has_arg)
             {
             case OptionParser::eNoArgument:
                 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()), 
@@ -1410,7 +1423,7 @@
                         raw_input_string.erase (pos, strlen (tmp_arg));
                 }
                 ReplaceArgumentAtIndex (idx, "");
-                if ((long_options[long_options_index].has_arg != OptionParser::eNoArgument)
+                if ((long_options[long_options_index].definition->option_has_arg != OptionParser::eNoArgument)
                     && (OptionParser::GetOptionArgument() != nullptr)
                     && (idx+1 < GetArgumentCount())
                     && (strcmp (OptionParser::GetOptionArgument(), GetArgumentAtIndex(idx+1)) == 0))
@@ -1453,12 +1466,12 @@
     // to suppress error messages.
 
     sstr << ":";
-    for (int i = 0; long_options[i].name != nullptr; ++i)
+    for (int i = 0; long_options[i].definition != nullptr; ++i)
     {
         if (long_options[i].flag == nullptr)
         {
             sstr << (char) long_options[i].val;
-            switch (long_options[i].has_arg)
+            switch (long_options[i].definition->option_has_arg)
             {
                 default:
                 case OptionParser::eNoArgument:
@@ -1555,7 +1568,7 @@
         if (long_options_index == -1)
         {
             for (int j = 0;
-                 long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
+                 long_options[j].definition || long_options[j].flag || long_options[j].val;
                  ++j)
             {
                 if (long_options[j].val == val)
@@ -1581,7 +1594,9 @@
                 }
             }
 
-            switch (long_options[long_options_index].has_arg)
+            const OptionDefinition *def = long_options[long_options_index].definition;
+            int has_arg = (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
+            switch (has_arg)
             {
             case OptionParser::eNoArgument:
                 option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 1, 0));
Index: lldb/trunk/source/Interpreter/CommandOptionValidators.cpp
===================================================================
--- lldb/trunk/source/Interpreter/CommandOptionValidators.cpp
+++ lldb/trunk/source/Interpreter/CommandOptionValidators.cpp
@@ -0,0 +1,39 @@
+//===-- CommandOptionValidators.cpp -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Interpreter/CommandOptionValidators.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Target/Platform.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+bool PosixPlatformCommandOptionValidator::IsValid(Platform &platform, ExecutionContext &target) const
+{
+    llvm::Triple::OSType os = platform.GetSystemArchitecture().GetTriple().getOS();
+    switch (os)
+    {
+    // Are there any other platforms that are not POSIX-compatible?
+    case llvm::Triple::Win32:
+        return false;
+    default:
+        return true;
+    }
+}
+
+const char* PosixPlatformCommandOptionValidator::ShortConditionString() const 
+{ 
+    return "POSIX"; 
+}
+
+const char* PosixPlatformCommandOptionValidator::LongConditionString() const 
+{ 
+    return "Option only valid for POSIX-compliant hosts."; 
+}
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits

Reply via email to