This changes how the --source driver argument works.  I split this into four arguments:

-S : Specifies a command file which will get sourced after the ~/.lldbinit but before file arguments are processed
-O : Specifies a single (one-line) command that will get ditto

and

-s : Specifies a command file which will get sourced after `pwd`/.lldbinit
-o : Specifies a command file which ditto

I also changed it so that by default these sourced commands will print their command result, but there's a
-q option to change that if you wish.

llvm-svn: 190734
diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp
index 875adc2..36e5651 100644
--- a/lldb/tools/driver/Driver.cpp
+++ b/lldb/tools/driver/Driver.cpp
@@ -99,13 +99,21 @@
         "extensions have been implemented." },
     { LLDB_3_TO_5,       false, "debug"          , 'd', no_argument      , 0,  eArgTypeNone,
         "Tells the debugger to print out extra information for debugging itself." },
+    { LLDB_3_TO_5,       false, "source-quietly"          , 'b', no_argument      , 0,  eArgTypeNone,
+        "Tells the debugger to print out extra information for debugging itself." },
     { LLDB_3_TO_5,       false, "source"         , 's', required_argument, 0,  eArgTypeFilename,
         "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." },
+    { LLDB_3_TO_5,       false, "one-line"         , 'o', required_argument, 0,  eArgTypeNone,
+        "Tells the debugger to execute this one-line lldb command." },
+    { LLDB_3_TO_5,       false, "source-before-file"         , 'S', required_argument, 0,  eArgTypeFilename,
+        "Tells the debugger to read in and execute the file <file>, which should contain lldb commands." },
+    { LLDB_3_TO_5,       false, "one-line-before-file"         , 'O', required_argument, 0,  eArgTypeNone,
+        "Tells the debugger to execute this one-line lldb command." },
     { LLDB_3_TO_5,       false, "editor"         , 'e', no_argument      , 0,  eArgTypeNone,
         "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
     { LLDB_3_TO_5,       false, "no-lldbinit"    , 'x', no_argument      , 0,  eArgTypeNone,
         "Do not automatically parse any '.lldbinit' files." },
-    { LLDB_3_TO_5,       false, "no-use-colors"  , 'o', no_argument      , 0,  eArgTypeNone,
+    { LLDB_3_TO_5,       false, "no-use-colors"  , 'X', no_argument      , 0,  eArgTypeNone,
         "Do not use colors." },
     { LLDB_OPT_SET_6,    true , "python-path"    , 'P', no_argument      , 0,  eArgTypeNone,
         "Prints out the path to the lldb.py file for this version of lldb." },
@@ -390,8 +398,10 @@
     m_script_lang (lldb::eScriptLanguageDefault),
     m_core_file (),
     m_crash_log (),
-    m_source_command_files (),
+    m_initial_commands (),
+    m_after_file_commands (),
     m_debug_mode (false),
+    m_source_quietly(false),
     m_print_version (false),
     m_print_python_path (false),
     m_print_help (false),
@@ -412,8 +422,10 @@
 {
     m_args.clear ();
     m_script_lang = lldb::eScriptLanguageDefault;
-    m_source_command_files.clear ();
+    m_initial_commands.clear ();
+    m_after_file_commands.clear ();
     m_debug_mode = false;
+    m_source_quietly = false;
     m_print_help = false;
     m_print_version = false;
     m_print_python_path = false;
@@ -424,6 +436,34 @@
 }
 
 void
+Driver::OptionData::AddInitialCommand (const char *command, bool before_file, bool is_file, SBError &error)
+{
+    std::vector<std::pair<bool, std::string> > *command_set;
+    if (before_file)
+        command_set = &(m_initial_commands);
+    else
+        command_set = &(m_after_file_commands);
+
+    if (is_file)
+    {
+        SBFileSpec file(command);
+        if (file.Exists())
+            command_set->push_back (std::pair<bool, std::string> (true, optarg));
+        else if (file.ResolveExecutableLocation())
+        {
+            char final_path[PATH_MAX];
+            file.GetPath (final_path, sizeof(final_path));
+            std::string path_str (final_path);
+            command_set->push_back (std::pair<bool, std::string> (true, path_str));
+        }
+        else
+            error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
+    }
+    else
+        command_set->push_back (std::pair<bool, std::string> (false, optarg));
+}
+
+void
 Driver::ResetOptionValues ()
 {
     m_option_data.Clear ();
@@ -451,18 +491,60 @@
     return m_option_data.m_script_lang;
 }
 
-size_t
-Driver::GetNumSourceCommandFiles () const
+void
+Driver::ExecuteInitialCommands (bool before_file)
 {
-    return m_option_data.m_source_command_files.size();
-}
-
-const char *
-Driver::GetSourceCommandFileAtIndex (uint32_t idx) const
-{
-    if (idx < m_option_data.m_source_command_files.size())
-        return m_option_data.m_source_command_files[idx].c_str();
-    return NULL;
+    size_t num_commands;
+    std::vector<std::pair<bool, std::string> > *command_set;
+    if (before_file)
+        command_set = &(m_option_data.m_initial_commands);
+    else
+        command_set = &(m_option_data.m_after_file_commands);
+    
+    num_commands = command_set->size();
+    SBCommandReturnObject result;
+    bool old_async = GetDebugger().GetAsync();
+    GetDebugger().SetAsync(false);
+    for (size_t idx = 0; idx < num_commands; idx++)
+    {
+        bool is_file = (*command_set)[idx].first;
+        const char *command = (*command_set)[idx].second.c_str();
+        char command_string[PATH_MAX * 2];
+        const bool dump_stream_only_if_no_immediate = true;
+        const char *executed_command = command;
+        if (is_file)
+        {
+            ::snprintf (command_string, sizeof(command_string), "command source '%s'", command);
+            executed_command = command_string;
+        }
+        
+        m_debugger.GetCommandInterpreter().HandleCommand (executed_command, result, false);
+        if (!m_option_data.m_source_quietly || result.Succeeded() == false)
+        {
+            const size_t output_size = result.GetOutputSize();
+            if (output_size > 0)
+                m_io_channel_ap->OutWrite (result.GetOutput(dump_stream_only_if_no_immediate), output_size, NO_ASYNC);
+            const size_t error_size = result.GetErrorSize();
+            if (error_size > 0)
+                m_io_channel_ap->OutWrite (result.GetError(dump_stream_only_if_no_immediate), error_size, NO_ASYNC);
+        }
+        
+        if (result.Succeeded() == false)
+        {
+            char error_buffer[1024];
+            size_t error_size;
+            const char *type = before_file ? "before file" : "after_file";
+            if (is_file)
+                error_size = ::snprintf(error_buffer, sizeof(error_buffer), "Aborting %s command execution, command file: '%s' failed.\n", type, command);
+            else
+                error_size = ::snprintf(error_buffer, sizeof(error_buffer), "Aborting %s command execution, command: '%s' failed.\n", type, command);
+            
+            m_io_channel_ap->OutWrite(error_buffer, error_size, NO_ASYNC);
+            break;
+        }
+        result.Clear();
+    }
+    GetDebugger().SetAsync(old_async);
 }
 
 bool
@@ -623,7 +705,7 @@
                         m_debugger.SkipAppInitFiles (true);
                         break;
 
-                    case 'o':
+                    case 'X':
                         m_debugger.SetUseColor (false);
                         break;
 
@@ -658,6 +740,10 @@
                         m_option_data.m_debug_mode = true;
                         break;
 
+                    case 'q':
+                        m_option_data.m_source_quietly = true;
+                        break;
+
                     case 'n':
                         m_option_data.m_process_name = optarg;
                         break;
@@ -676,22 +762,17 @@
                         }
                         break;
                     case 's':
-                        {
-                            SBFileSpec file(optarg);
-                            if (file.Exists())
-                                m_option_data.m_source_command_files.push_back (optarg);
-                            else if (file.ResolveExecutableLocation())
-                            {
-                                char final_path[PATH_MAX];
-                                file.GetPath (final_path, sizeof(final_path));
-                                std::string path_str (final_path);
-                                m_option_data.m_source_command_files.push_back (path_str);
-                            }
-                            else
-                                error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
-                        }
+                        m_option_data.AddInitialCommand(optarg, false, true, error);
                         break;
-
+                    case 'o':
+                        m_option_data.AddInitialCommand(optarg, false, false, error);
+                        break;
+                    case 'S':
+                        m_option_data.AddInitialCommand(optarg, true, true, error);
+                        break;
+                    case 'O':
+                        m_option_data.AddInitialCommand(optarg, true, false, error);
+                        break;
                     default:
                         m_option_data.m_print_help = true;
                         error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
@@ -1400,42 +1481,15 @@
             }
 
             // Now we handle options we got from the command line
-            char command_string[PATH_MAX * 2];
-            const size_t num_source_command_files = GetNumSourceCommandFiles();
-            const bool dump_stream_only_if_no_immediate = true;
-            if (num_source_command_files > 0)
-            {
-                for (size_t i=0; i < num_source_command_files; ++i)
-                {
-                    const char *command_file = GetSourceCommandFileAtIndex(i);
-                    ::snprintf (command_string, sizeof(command_string), "command source '%s'", command_file);
-                    m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, false);
-                    if (GetDebugMode())
-                    {
-                        result.PutError (m_debugger.GetErrorFileHandle());
-                        result.PutOutput (m_debugger.GetOutputFileHandle());
-                    }
-                    
-                    // if the command sourcing generated an error - dump the result object
-                    if (result.Succeeded() == false)
-                    {
-                        const size_t output_size = result.GetOutputSize();
-                        if (output_size > 0)
-                            m_io_channel_ap->OutWrite (result.GetOutput(dump_stream_only_if_no_immediate), output_size, NO_ASYNC);
-                        const size_t error_size = result.GetErrorSize();
-                        if (error_size > 0)
-                            m_io_channel_ap->OutWrite (result.GetError(dump_stream_only_if_no_immediate), error_size, NO_ASYNC);
-                    }
-                    
-                    result.Clear();
-                }
-            }
-
+            // First source in the commands specified to be run before the file arguments are processed.
+            ExecuteInitialCommands(true);
+            
             // Was there a core file specified?
             std::string core_file_spec("");
             if (!m_option_data.m_core_file.empty())
                 core_file_spec.append("--core ").append(m_option_data.m_core_file);
 
+            char command_string[PATH_MAX * 2];
             const size_t num_args = m_option_data.m_args.size();
             if (num_args > 0)
             {
@@ -1487,6 +1541,9 @@
                 result.PutError(m_debugger.GetErrorFileHandle());
                 result.PutOutput(m_debugger.GetOutputFileHandle());
             }
+            
+            // Now execute the commands specified for after the file arguments are processed.
+            ExecuteInitialCommands(false);
 
             SBEvent event;