[Lldb-commits] [lldb] r114467 - in /lldb/trunk/source: Commands/CommandObjectBreakpointCommand.cpp Interpreter/ScriptInterpreterPython.cpp

Caroline Tice ctice at apple.com
Tue Sep 21 12:25:28 PDT 2010


Author: ctice
Date: Tue Sep 21 14:25:28 2010
New Revision: 114467

URL: http://llvm.org/viewvc/llvm-project?rev=114467&view=rev
Log:
Re-write/clean up code that generated Python breakpoint commands.
Add a warning if no command was attached to the breakpoint.
Update the help slightly.


Modified:
    lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp
    lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp

Modified: lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp?rev=114467&r1=114466&r2=114467&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp Tue Sep 21 14:25:28 2010
@@ -225,6 +225,11 @@
  \n\
 (lldb)  \n\
  \n\
+ \n\
+Final Note:  If you get a warning that no breakpoint command was generated, \n\
+but you did not get any syntax errors, you probably forgot to add a call \n\
+to your functions. \n\
+ \n\
 Special information about debugger command breakpoint commands \n\
 -------------------------------------------------------------- \n\
  \n\

Modified: lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp?rev=114467&r1=114466&r2=114467&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp (original)
+++ lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp Tue Sep 21 14:25:28 2010
@@ -626,6 +626,8 @@
                             bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
                         }
                     }
+                    else
+                      ::fprintf (out_fh, "Warning: No command attached to breakpoint.\n");
                 }
                 else
                 {
@@ -714,150 +716,193 @@
 ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, StringList &callback_data)
 {
     static int num_created_functions = 0;
-
     user_input.RemoveBlankLines ();
     int num_lines = user_input.GetSize();
-    std::string last_function_call;
-
-    // Go through lines of input looking for any function definitions. For each function definition found,
-    // export the function definition to Python, create a potential function call for the function, and
-    // mark the lines of the function to be removed from the user input.
 
-    for (int i = 0; i < num_lines; ++i)
+    if (num_lines == 1)
     {
-        int function_start = i;
-        std::string current_str = user_input.GetStringAtIndex (i);
-        const char *current_line = current_str.c_str();
-        int len = 0;
-        if (current_line)
-            len = strlen (current_line);
+        callback_data.AppendString (user_input.GetStringAtIndex (0));
+        return true;
+    }
 
-        // Check to see if the current line is the start of a Python function definition.
-        if (len > 4 && strncmp (current_line, "def ", 4) == 0)
-        {
-            // We've found the first line of a function. First, get the function name.
+    // Traverse user_input exactly once.  At each line, either copy line into new, auto-generated function, 
+    // increasing indentation by 5 spaces...  ...or copy it exactly as is into the user-written 
+    // currently-to-be-pushed-to-Python function def.  At the end of each Python function def, push the function 
+    // to Python, and clear the function string, to start again.  At the end of it all, if there is anything in 
+    // the auto-generated function, push it to Python and add the function call to it to the callback data.
+
+    bool inside_user_python_function_def = false;
+    std::string whitespace = " \t";
 
-            // Skip over the 'def '.
-            char *start = (char *) current_line + 4;
+    StringList auto_generated_function;
+    StringList user_defined_function;
 
-            // Skip over white space.
-            while (start[0] == ' ' || start[0] == '\t')
-              ++start;
-
-            // Find the end of the function name.
-            char *end = start;
-            while (isalnum (end[0]) || end[0] == '_')
-              ++end;
-
-            int name_len = end - start;
-            std::string func_name = current_str.substr (4, name_len);
-
-            // Now to find the last line of the function.  That will be the first line that does not begin with
-            // any white space (thanks to Python's indentation rules).
-            ++i;
-            bool found = false;
-            while (i < num_lines && !found)
+    StringList *current_function_def = &auto_generated_function;
+    std::string auto_generated_function_name ("lldb_autogen_python_bp_callback_func_");
+
+    for (int i = 0; i < num_lines; ++i)
+    {
+        std::string current_line (user_input.GetStringAtIndex(i));
+        size_t idx = current_line.find_first_of (whitespace);
+        if (idx != std::string::npos)
+        {
+            if (idx == 0) // line starts with indentation...
             {
-                std::string next_str = user_input.GetStringAtIndex (i);
-                const char *next_line = next_str.c_str();
-                if (next_line[0] != ' ' && next_line[0] != '\t')
-                    found = true;
+                if (inside_user_python_function_def)
+                {
+                    // Add this line to the user's python function definition.
+                    current_function_def->AppendString (current_line.c_str());
+                }
                 else
-                    ++i;
+                {
+                    // Add this line to our auto-generated function; increase original indentation by 5.
+                    StreamString tmp_str;
+                    tmp_str.Printf ("     %s", current_line.c_str());
+                    current_function_def->AppendString (tmp_str.GetData());
+                }
             }
-            if (found)
-                --i;  // Make 'i' correspond to the last line of the function.
-            int function_end = i;
-
-            // Special case:  All of user_input is one big function definition.
-            if ((function_start == 0) && (function_end == (num_lines - 1)))
+            else  // line does not start with indentation...
             {
-                ExportFunctionDefinitionToInterpreter (user_input);
-                last_function_call = func_name + " ()";
-                callback_data.AppendString (last_function_call.c_str());
-                return callback_data.GetSize() > 0;
-            }
-            else
-              {
-                // Make a copy of the function definition:
-                StringList new_function;
-                for (int k = function_start; k <= function_end; ++k)
+                // First, check to see if we just finished a user-written function definition; if so,
+                // wrap it up and send it to Python.
+
+                if (inside_user_python_function_def && (user_defined_function.GetSize() > 0))
                 {
-                    new_function.AppendString (user_input.GetStringAtIndex (k));
-                    // Mark the string to be deleted from user_input.
-                    user_input.DeleteStringAtIndex (k);
-                    user_input.InsertStringAtIndex (k, "<lldb_delete>");
+                    if (! ExportFunctionDefinitionToInterpreter (user_defined_function))
+                    {
+                        // User entered incorrect Python syntax.  We should not attempt to continue.
+                        // Clear the callback data, and return immediately.
+                        callback_data.Clear();
+                        return false;
+                    }
+
+                    // User defined function was successfully sent to Python.  Clean up after it.
+                    user_defined_function.Clear();
+                    inside_user_python_function_def = false;
+                    current_function_def = &auto_generated_function;
                 }
-                ExportFunctionDefinitionToInterpreter (new_function);
-                last_function_call = func_name + " ()";
-            }
+
+                // Next, check to see if we are at the start of a user-defined Python function.
+                std::string first_word = current_line.substr (0, idx);
+                if (first_word.compare ("def") == 0)
+                {
+                    // Start the user defined function properly:
+                    inside_user_python_function_def = true;
+                    current_function_def = &user_defined_function;
+                    current_function_def->AppendString (current_line.c_str());
+                }
+                else
+                {
+                    // We are in "loose" Python code that we need to collect and put into the auto-generated
+                    // function.
+                    StreamString tmp_str;
+                    current_function_def = &auto_generated_function;
+                    if (current_function_def->GetSize() == 0)
+                    {
+                        // Create the function name, and add insert the function def line.
+                        tmp_str.Printf ("%d", num_created_functions);
+                        ++num_created_functions;
+                        auto_generated_function_name.append (tmp_str.GetData());
+
+                        tmp_str.Clear();
+                        tmp_str.Printf ("def %s ():", auto_generated_function_name.c_str());
+                        current_function_def->AppendString (tmp_str.GetData());
+                    }
+                    tmp_str.Clear();
+                    
+                    // Indent the line an extra 5 spaces and add it to our auto-generated function.
+                    tmp_str.Printf ("     %s", current_line.c_str());
+                    current_function_def->AppendString (tmp_str.GetData());
+                } // else we are in loose Python code
+            } // else current line does not start with indentatin
         }
-    }
+        else
+        {
+            // There was no white space on the line (and therefore no indentation either).
 
-    // Now instead of trying to really delete the marked lines from user_input, we will just copy all the
-    // unmarked lines into a new StringList.
+            // First, check to see if we just finished a user-written function definition; if so,
+            // wrap it up and send it to Python.
+            
+            if (inside_user_python_function_def && (user_defined_function.GetSize() > 0))
+            {
+                if (! ExportFunctionDefinitionToInterpreter (user_defined_function))
+                {
+                    // User entered incorrect Python syntax.  We should not attempt to continue.
+                    // Clear the callback data, and return immediately.
+                    callback_data.Clear();
+                    return false;
+                }
+                
+                // User defined function was successfully sent to Python.  Clean up after it.
+                user_defined_function.Clear();
+                inside_user_python_function_def = false;
+                current_function_def = &auto_generated_function;
+            }
+            
+            // We cannot be at the start of a function definition (they contain white space) so we
+            // must have "loose" python code.
+            
+            StreamString tmp_str;
+            current_function_def = &auto_generated_function;
+            if (current_function_def->GetSize() == 0)
+            {
+                // Create the function name, and add insert the function def line.
+                tmp_str.Printf ("%d", num_created_functions);
+                ++num_created_functions;
+                auto_generated_function_name.append (tmp_str.GetData());
+                
+                tmp_str.Clear();
+                tmp_str.Printf ("def %s ():", auto_generated_function_name.c_str());
+                current_function_def->AppendString (tmp_str.GetData());
+            }
+            tmp_str.Clear();
+            
+            // Indent the line an extra 5 spaces and add it to our auto-generated function.
+            tmp_str.Printf ("     %s", current_line.c_str());
+            current_function_def->AppendString (tmp_str.GetData());
+            
+        } // else there was no white space on the line.
+    } 
 
-    StringList new_user_input;
+    // Perhaps the last line of input was also the last line of a user-defined function; if so,
+    // attempt to push the function down to Python.
 
-    for (int i = 0; i < num_lines; ++i)
+    if (inside_user_python_function_def && (user_defined_function.GetSize() > 0))
     {
-        std::string current_string = user_input.GetStringAtIndex (i);
-        if (current_string.compare (0, 13, "<lldb_delete>") == 0)
-            continue;
-
-        new_user_input.AppendString (current_string.c_str());
+        if (! ExportFunctionDefinitionToInterpreter (user_defined_function))
+        {
+            callback_data.Clear();
+            return false;
+        }
     }
 
-    num_lines = new_user_input.GetSize();
 
-    if (num_lines > 0)
+    if (auto_generated_function.GetSize() > 0)
     {
-        if (num_lines == 1
-            && strchr (new_user_input.GetStringAtIndex(0), '\n') == NULL)
+        // Export the auto-generated function to Python.
+        if (ExportFunctionDefinitionToInterpreter (auto_generated_function))
         {
-            // If there's only one line of input, and it doesn't contain any newline characters....
-            callback_data.AppendString (new_user_input.GetStringAtIndex (0));
+            // The export succeeded; the syntax must be ok. Generate the function call and put
+            // it in the callback data.
+            StreamString tmp_str;
+            tmp_str.Printf ("%s ()", auto_generated_function_name.c_str());
+            callback_data.AppendString (tmp_str.GetData());
+            return true;
         }
         else
         {
-            // Create the new function name.
-            StreamString func_name;
-            func_name.Printf ("lldb_bp_callback_func_%d", num_created_functions);
-            //std::string func_name = "lldb_bp_callback_func_" + num_created_functions;
-            ++num_created_functions;
-
-            // Create the function call for the new function.
-            last_function_call = func_name.GetString() + " ()";
-
-            // Create the Python function definition line (which will have to be inserted at the beginning of
-            // the function).
-            std::string def_line = "def " + func_name.GetString() + " ():";
-
-
-            // Indent all lines an additional four spaces (as they are now being put inside a function definition).
-            for (int i = 0; i < num_lines; ++i)
-              {
-                const char *temp_cstring = new_user_input.GetStringAtIndex(i);
-                std::string temp2 = "    ";
-                temp2.append(temp_cstring);
-                new_user_input.DeleteStringAtIndex (i);
-                new_user_input.InsertStringAtIndex (i, temp2.c_str());
-              }
-
-            // Insert the function definition line at the top of the new function.
-            new_user_input.InsertStringAtIndex (0, def_line.c_str());
-
-            ExportFunctionDefinitionToInterpreter (new_user_input);
-            callback_data.AppendString (last_function_call.c_str());
+            // Syntax error!
+            callback_data.Clear();
+            return false;
         }
     }
     else
     {
-        if (!last_function_call.empty())
-          callback_data.AppendString (last_function_call.c_str());
+        // If there was any code, it consisted entirely of function defs, without any calls to the functions.
+        // No actual exectuable code was therefore generated.  (Function calls would have looked like "loose" python,
+        // and would have been collected into the auto-generated function.)
+        return false;
     }
-
-    return callback_data.GetSize() > 0;
 }
 
 bool
@@ -881,8 +926,8 @@
         bool success = context->exe_ctx.target->GetDebugger().
                                                 GetCommandInterpreter().
                                                 GetScriptInterpreter()->ExecuteOneLineWithReturn (python_string,
-                                                                                                  ScriptInterpreter::eBool,
-                                                                                                  (void *) &temp_bool);
+                                                                                             ScriptInterpreter::eBool,
+                                                                                             (void *) &temp_bool);
         if (success)
           ret_value = temp_bool;
     }





More information about the lldb-commits mailing list