[Lldb-commits] [PATCH] lldb-mi support for CLI commands and -s option

dawn at burble.org dawn at burble.org
Tue Nov 18 23:27:30 PST 2014


Doh!  Let's try this again...

On Tue, Nov 18, 2014 at 11:13:32AM -0800, jingham at apple.com wrote:
> I didn't see a patch attached to this.
> 
> Jim
> 
> > On Nov 18, 2014, at 8:32 AM, dawn at burble.org wrote:
> > 
> > Adds support for using command files in lldb-mi via option -s, and
> > allows for non-MI commands to be entered in interpreter mode by
> > embedding them inside "-interpreter-exec" commands.
> > 
> > Please review and commit?
> > 
> > Thanks,
> > -Dawn
> > _______________________________________________
> > lldb-commits mailing list
> > lldb-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
-------------- next part --------------
Index: tools/lldb-mi/MIDriver.cpp
===================================================================
--- tools/lldb-mi/MIDriver.cpp	(revision 222209)
+++ tools/lldb-mi/MIDriver.cpp	(working copy)
@@ -22,6 +22,7 @@
 // Third party headers:
 #include <stdarg.h> // va_list, va_start, var_end
 #include <iostream>
+#include <fstream>
 #include <lldb/API/SBError.h>
 
 // In-house headers:
@@ -68,6 +69,7 @@
     , m_eCurrentDriverState(eDriverState_NotRunning)
     , m_bHaveExecutableFileNamePathOnCmdLine(false)
     , m_bDriverDebuggingArgExecutable(false)
+    , m_bHaveCommandFileNamePathOnCmdLine(false)
 {
 }
 
@@ -410,16 +412,17 @@
 
 //++ ------------------------------------------------------------------------------------
 // Details: Check the arguments that were passed to this program to make sure they are
-//          valid and to get their argument values (if any). The following are options
-//          that are only handled by *this driver:
+//          valid and to get their argument values (if any). The following are the only
+//          options handled by this driver:
 //              --executable
+//              --source
 //          The application's options --interpreter and --executable in code act very similar.
 //          The --executable is necessary to differentiate whither the MI Driver is being
-//          using by a client i.e. Eclipse or from the command line. Eclipse issues the option
+//          using by a client (e.g. Eclipse) or from the command line. Eclipse issues the option
 //          --interpreter and also passes additional arguments which can be interpreted as an
-//          executable if called from the command line. Using --executable tells the MI
-//          Driver is being called the command line and that the executable argument is indeed
-//          a specified executable an so actions commands to set up the executable for a
+//          executable if called from the command line. Using --executable tells the MI Driver
+//          it is being called from the command line and that the executable argument is indeed
+//          a specified executable and should so actions commands to set up the executable for a
 //          debug session. Using --interpreter on the commnd line does not action additional
 //          commands to initialise a debug session and so be able to launch the process.
 // Type:    Overridden.
@@ -451,20 +454,40 @@
 
     if (bHaveArgs)
     {
-        // Search right to left to look for the executable
+        // Search right to left to look for filenames
         for (MIint i = argc - 1; i > 0; i--)
         {
             const CMIUtilString strArg(argv[i]);
             const CMICmdArgValFile argFile;
+
+            // Check for a filename
             if (argFile.IsFilePath(strArg) || CMICmdArgValString(true, false, true).IsStringArg(strArg))
             {
+                // Is this the command file for the '-s' option?
+                const CMIUtilString strPrevArg(argv[i - 1]);
+                if (strPrevArg.compare("-s") == 0 || strPrevArg.compare("--source") == 0)
+                {
+                    m_strCmdLineArgCommandFileNamePath = argFile.GetFileNamePath(strArg);
+                    m_bHaveCommandFileNamePathOnCmdLine = true;
+                    i--; // skip '-s' on the next loop
+                    continue;
+                }
+                // Else, must be the executable
                 bHaveExecutableFileNamePath = true;
                 m_strCmdLineArgExecuteableFileNamePath = argFile.GetFileNamePath(strArg);
                 m_bHaveExecutableFileNamePathOnCmdLine = true;
             }
-            // This argument is also check for in CMIDriverMgr::ParseArgs()
-            if (0 == strArg.compare("--executable")) // Used to specify that there is executable argument also on the command line
-            {                                        // See fn description.
+            // Report error if no command file was specified for the '-s' option
+            else if (strArg.compare("-s") == 0 || strArg.compare("--source") == 0)
+            {
+                vwbExiting = true;
+                const CMIUtilString errMsg = CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF), "-s");
+                errStatus.SetErrorString(errMsg.c_str());
+                break;
+            }
+            // This argument is also checked for in CMIDriverMgr::ParseArgs()
+            else if (strArg.compare("--executable") == 0) // Used to specify that there is executable argument also on the command line
+            {                                             // See fn description.
                 bHaveExecutableLongOption = true;
             }
         }
@@ -623,6 +646,35 @@
     }
 #endif // MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION
 
+    // Handle '-s <file>' option
+    bool bOk = MIstatus::success;
+    if (m_bHaveCommandFileNamePathOnCmdLine)
+    {
+        std::ifstream startScript(m_strCmdLineArgCommandFileNamePath.c_str());
+        if (!startScript.is_open())
+        {
+            m_bExitApp = true;
+            const CMIUtilString errMsg(
+                CMIUtilString::Format(MIRSRC(IDS_UTIL_FILE_ERR_OPENING_FILE_UNKNOWN), m_strCmdLineArgCommandFileNamePath.c_str()));
+            SetErrorDescription(errMsg.c_str());
+            bOk = MIstatus::failure;
+        }
+        else
+        {
+            CMIUtilString executedCommand;
+            while (std::getline(startScript, executedCommand))
+            {
+                bOk = QueueMICommand(executedCommand);
+                if (!bOk)
+                {
+                    m_bExitApp = true;
+                    bOk = MIstatus::failure;
+                    break;
+                }
+            }
+        }
+    }
+
     // While the app is active
     while (!m_bExitApp)
     {
@@ -643,7 +695,7 @@
     // Ensure that a new line is sent as the last act of the dying driver
     m_rStdOut.WriteMIResponse("\n", false);
 
-    return MIstatus::success;
+    return bOk;
 }
 
 //++ ------------------------------------------------------------------------------------
@@ -977,6 +1029,25 @@
     return bOk;
 }
 
+// Helper function for CMIDriver::InterpretCommandThisDriver.
+// Turn the string into something that can be embedded in a string.
+static std::string
+stringify(const std::string &s)
+{
+    std::string result;
+    result.reserve(s.length() + 2);
+    result += '"';
+    const std::string::const_iterator last = s.end();
+    for (std::string::const_iterator p = s.begin(); p != last; ++p)
+    {
+        if (*p == '"' || *p == '\\')
+            result += '\\';
+        result += *p;
+    }
+    result += '"';
+    return result;
+}
+
 //++ ------------------------------------------------------------------------------------
 // Details: Interpret the text data and match against current commands to see if there
 //          is a match. If a match then the command is issued and actioned on. If a
@@ -985,7 +1056,7 @@
 //          This function is used by the application's main thread.
 // Type:    Method.
 // Args:    vTextLine           - (R) Text data representing a possible command.
-//          vwbCmdYesValid      - (W) True = Command invalid, false = command acted on.
+//          vwbCmdYesValid      - (W) True = Command valid, false = command not handled.
 // Return:  MIstatus::success - Functional succeeded.
 //          MIstatus::failure - Functional failed.
 // Throws:  None.
@@ -993,12 +1064,29 @@
 bool
 CMIDriver::InterpretCommandThisDriver(const CMIUtilString &vTextLine, bool &vwbCmdYesValid)
 {
+    // Make sure we have a valid MI command
+    CMIUtilString vMITextLine(vTextLine);
+    if (vTextLine.at(0) != '-')
+    {
+        static const CMIUtilString strTargetCreate("target create ");
+        if (vTextLine.compare(0, strTargetCreate.size(), strTargetCreate) == 0)
+        {
+            // Replace 'target create <file>' with '-file-exec-and-symbols <file>'.
+            vMITextLine = "-file-exec-and-symbols ";
+            vMITextLine.append(vTextLine.begin() + strTargetCreate.size(), vTextLine.end());
+        }
+        else
+        {
+            // Wrap non-MI commands to make them MI-compatible.
+            vMITextLine = "-interpreter-exec command " + stringify(vTextLine);
+        }
+    }
+        
     vwbCmdYesValid = false;
-
     bool bCmdNotInCmdFactor = false;
     SMICmdData cmdData;
     CMICmdMgr &rCmdMgr = CMICmdMgr::Instance();
-    if (!rCmdMgr.CmdInterpret(vTextLine, vwbCmdYesValid, bCmdNotInCmdFactor, cmdData))
+    if (!rCmdMgr.CmdInterpret(vMITextLine, vwbCmdYesValid, bCmdNotInCmdFactor, cmdData))
         return MIstatus::failure;
 
     if (vwbCmdYesValid)
@@ -1012,12 +1100,12 @@
     // Check for escape character, may be cursor control characters
     // This code is not necessary for application operation, just want to keep tabs on what
     // is been given to the driver to try and intepret.
-    if (vTextLine.at(0) == 27)
+    if (vMITextLine.at(0) == 27)
     {
         CMIUtilString logInput(MIRSRC(IDS_STDIN_INPUT_CTRL_CHARS));
-        for (MIuint i = 0; i < vTextLine.length(); i++)
+        for (MIuint i = 0; i < vMITextLine.length(); i++)
         {
-            logInput += CMIUtilString::Format("%d ", vTextLine.at(i));
+            logInput += CMIUtilString::Format("%d ", vMITextLine.at(i));
         }
         m_pLog->WriteLog(logInput);
         return MIstatus::success;
@@ -1030,7 +1118,7 @@
         strNotInCmdFactory = CMIUtilString::Format(MIRSRC(IDS_DRIVER_CMD_NOT_IN_FACTORY), cmdData.strMiCmd.c_str());
     const CMIUtilString strNot(CMIUtilString::Format("%s ", MIRSRC(IDS_WORD_NOT)));
     const CMIUtilString msg(
-        CMIUtilString::Format(MIRSRC(IDS_DRIVER_CMD_RECEIVED), vTextLine.c_str(), strNot.c_str(), strNotInCmdFactory.c_str()));
+        CMIUtilString::Format(MIRSRC(IDS_DRIVER_CMD_RECEIVED), vMITextLine.c_str(), strNot.c_str(), strNotInCmdFactory.c_str()));
     const CMICmnMIValueConst vconst = CMICmnMIValueConst(msg);
     const CMICmnMIValueResult valueResult("msg", vconst);
     const CMICmnMIResultRecord miResultRecord(cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, valueResult);
Index: tools/lldb-mi/MIDriver.h
===================================================================
--- tools/lldb-mi/MIDriver.h	(revision 222209)
+++ tools/lldb-mi/MIDriver.h	(working copy)
@@ -175,8 +175,10 @@
     CMICmnLLDBDebugger &m_rLldbDebugger;
     CMICmnStreamStdout &m_rStdOut;
     DriverState_e m_eCurrentDriverState;
-    bool m_bHaveExecutableFileNamePathOnCmdLine; // True = Yes executable given as one of the parameters to the MI Driver, false = not found
+    bool m_bHaveExecutableFileNamePathOnCmdLine; // True = yes, executable given as one of the parameters to the MI Driver, false = not found
     CMIUtilString m_strCmdLineArgExecuteableFileNamePath;
-    bool m_bDriverDebuggingArgExecutable; // True = The MI Driver (MI mode) is debugging executable passed as argument, false = running via
-                                          // a client i.e Eclipse
+    bool m_bDriverDebuggingArgExecutable; // True = the MI Driver (MI mode) is debugging executable passed as argument,
+                                          // false = running via a client (e.g. Eclipse)
+    bool m_bHaveCommandFileNamePathOnCmdLine; // True = file with initial commands given as one of the parameters to the MI Driver, false = not found
+    CMIUtilString m_strCmdLineArgCommandFileNamePath;
 };


More information about the lldb-commits mailing list