diff options
| author | Enrico Granata <granata.enrico@gmail.com> | 2011-07-15 02:26:42 +0000 |
|---|---|---|
| committer | Enrico Granata <granata.enrico@gmail.com> | 2011-07-15 02:26:42 +0000 |
| commit | f2bbf717f72f7f01b83b1b41b0fd014c9471c8aa (patch) | |
| tree | bcbf57281baa4c9e0fe1c4c440087ff2e6c2528c /lldb/source/Interpreter/ScriptInterpreterPython.cpp | |
| parent | a83b37a9db2880091f4f8e7683c30ca142678fff (diff) | |
| download | bcm5719-llvm-f2bbf717f72f7f01b83b1b41b0fd014c9471c8aa.tar.gz bcm5719-llvm-f2bbf717f72f7f01b83b1b41b0fd014c9471c8aa.zip | |
Python summary strings:
- you can use a Python script to write a summary string for data-types, in one of
three ways:
-P option and typing the script a line at a time
-s option and passing a one-line Python script
-F option and passing the name of a Python function
these options all work for the "type summary add" command
your Python code (if provided through -P or -s) is wrapped in a function
that accepts two parameters: valobj (a ValueObject) and dict (an LLDB
internal dictionary object). if you use -F and give a function name,
you're expected to define the function on your own and with the right
prototype. your function, however defined, must return a Python string
- test case for the Python summary feature
- a few quirks:
Python summaries cannot have names, and cannot use regex as type names
both issues will be fixed ASAP
major redesign of type summary code:
- type summary working with strings and type summary working with Python code
are two classes, with a common base class SummaryFormat
- SummaryFormat classes now are able to actively format objects rather than
just aggregating data
- cleaner code to print descriptions for summaries
the public API now exports a method to easily navigate a ValueObject hierarchy
New InputReaderEZ and PriorityPointerPair classes
Several minor fixes and improvements
llvm-svn: 135238
Diffstat (limited to 'lldb/source/Interpreter/ScriptInterpreterPython.cpp')
| -rw-r--r-- | lldb/source/Interpreter/ScriptInterpreterPython.cpp | 175 |
1 files changed, 173 insertions, 2 deletions
diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index 610c019cb33..57a5929fc58 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -34,6 +34,7 @@ using namespace lldb_private; static ScriptInterpreter::SWIGInitCallback g_swig_init_callback = NULL; static ScriptInterpreter::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = NULL; +static ScriptInterpreter::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = NULL; static int @@ -1140,6 +1141,117 @@ ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &func return ExecuteMultipleLines (function_def_string.c_str()); } +// TODO move both GenerateTypeScriptFunction and GenerateBreakpointCommandCallbackData to actually +// use this code to generate their functions +bool +ScriptInterpreterPython::GenerateFunction(std::string& signature, StringList &input, StringList &output) +{ + int num_lines = input.GetSize (); + if (num_lines == 0) + return false; + StreamString sstr; + StringList auto_generated_function; + auto_generated_function.AppendString (signature.c_str()); + auto_generated_function.AppendString (" global_dict = globals()"); // Grab the global dictionary + auto_generated_function.AppendString (" new_keys = dict.keys()"); // Make a list of keys in the session dict + auto_generated_function.AppendString (" old_keys = global_dict.keys()"); // Save list of keys in global dict + auto_generated_function.AppendString (" global_dict.update (dict)"); // Add the session dictionary to the + // global dictionary. + + // Wrap everything up inside the function, increasing the indentation. + + for (int i = 0; i < num_lines; ++i) + { + sstr.Clear (); + sstr.Printf (" %s", input.GetStringAtIndex (i)); + auto_generated_function.AppendString (sstr.GetData()); + } + auto_generated_function.AppendString (" for key in new_keys:"); // Iterate over all the keys from session dict + auto_generated_function.AppendString (" dict[key] = global_dict[key]"); // Update session dict values + auto_generated_function.AppendString (" if key not in old_keys:"); // If key was not originally in global dict + auto_generated_function.AppendString (" del global_dict[key]"); // ...then remove key/value from global dict + + // Verify that the results are valid Python. + + if (!ExportFunctionDefinitionToInterpreter (auto_generated_function)) + return false; + + return true; + +} + +// this implementation is identical to GenerateBreakpointCommandCallbackData (apart from the name +// given to generated functions, of course) +bool +ScriptInterpreterPython::GenerateTypeScriptFunction (StringList &user_input, StringList &output) +{ + static int num_created_functions = 0; + user_input.RemoveBlankLines (); + int num_lines = user_input.GetSize (); + StreamString sstr; + + // Check to see if we have any data; if not, just return. + if (user_input.GetSize() == 0) + return false; + + // Take what the user wrote, wrap it all up inside one big auto-generated Python function, passing in the + // ValueObject as parameter to the function. + + sstr.Printf ("lldb_autogen_python_type_print_func_%d", num_created_functions); + ++num_created_functions; + std::string auto_generated_function_name = sstr.GetData(); + + sstr.Clear(); + StringList auto_generated_function; + + // Create the function name & definition string. + + sstr.Printf ("def %s (valobj, dict):", auto_generated_function_name.c_str()); + auto_generated_function.AppendString (sstr.GetData()); + + // Pre-pend code for setting up the session dictionary. + + auto_generated_function.AppendString (" global_dict = globals()"); // Grab the global dictionary + auto_generated_function.AppendString (" new_keys = dict.keys()"); // Make a list of keys in the session dict + auto_generated_function.AppendString (" old_keys = global_dict.keys()"); // Save list of keys in global dict + auto_generated_function.AppendString (" global_dict.update (dict)"); // Add the session dictionary to the + // global dictionary. + + // Wrap everything up inside the function, increasing the indentation. + + for (int i = 0; i < num_lines; ++i) + { + sstr.Clear (); + sstr.Printf (" %s", user_input.GetStringAtIndex (i)); + auto_generated_function.AppendString (sstr.GetData()); + } + + // Append code to clean up the global dictionary and update the session dictionary (all updates in the function + // got written to the values in the global dictionary, not the session dictionary). + + auto_generated_function.AppendString (" for key in new_keys:"); // Iterate over all the keys from session dict + auto_generated_function.AppendString (" dict[key] = global_dict[key]"); // Update session dict values + auto_generated_function.AppendString (" if key not in old_keys:"); // If key was not originally in global dict + auto_generated_function.AppendString (" del global_dict[key]"); // ...then remove key/value from global dict + + // Verify that the results are valid Python. + + if (!ExportFunctionDefinitionToInterpreter (auto_generated_function)) + return false; + + // Store the name of the auto-generated function to be called. + + output.AppendString (auto_generated_function_name.c_str()); + return true; +} + +bool +ScriptInterpreterPython::GenerateTypeScriptFunction (const char* oneliner, StringList &output) +{ + StringList input(oneliner); + return GenerateTypeScriptFunction(input, output); +} + bool ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, StringList &callback_data) { @@ -1206,6 +1318,63 @@ ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user return true; } +std::string +ScriptInterpreterPython::CallPythonScriptFunction (const char *python_function_name, + lldb::ValueObjectSP valobj) +{ + + if (!python_function_name || !(*python_function_name)) + return "<no function>"; + + if (!valobj.get()) + return "<no object>"; + + Target *target = valobj->GetUpdatePoint().GetTarget(); + + if (!target) + return "<no target>"; + + Debugger &debugger = target->GetDebugger(); + ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); + ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter; + + if (!script_interpreter) + return "<no python>"; + + std::string ret_val; + + if (python_function_name + && *python_function_name) + { + FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); + if (CurrentThreadHasPythonLock()) + { + python_interpreter->EnterSession (); + ret_val = g_swig_typescript_callback (python_function_name, + python_interpreter->m_dictionary_name.c_str(), + valobj); + python_interpreter->LeaveSession (); + } + else + { + while (!GetPythonLock (1)) + fprintf (tmp_fh, + "Python interpreter locked on another thread; waiting to acquire lock...\n"); + python_interpreter->EnterSession (); + ret_val = g_swig_typescript_callback (python_function_name, + python_interpreter->m_dictionary_name.c_str(), + valobj); + python_interpreter->LeaveSession (); + ReleasePythonLock (); + } + } + else + return "<no function name>"; + + return ret_val; + +} + bool ScriptInterpreterPython::BreakpointCallbackFunction ( @@ -1399,10 +1568,12 @@ ScriptInterpreterPython::RunEmbeddedPythonInterpreter (lldb::thread_arg_t baton) void ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_init_callback, - SWIGBreakpointCallbackFunction python_swig_breakpoint_callback) + SWIGBreakpointCallbackFunction python_swig_breakpoint_callback, + SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback) { g_swig_init_callback = python_swig_init_callback; - g_swig_breakpoint_callback = python_swig_breakpoint_callback; + g_swig_breakpoint_callback = python_swig_breakpoint_callback; + g_swig_typescript_callback = python_swig_typescript_callback; } void |

