[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