Added a typemap and wrappers for SBInputReader callbacks

Now it's possible to use SBInputReader callbacks in Python.

We leak the callback object, unfortunately. A __del__ method can be added
to SBInputReader, but we have no way to check the callback function that
is on the reader. So we can't call Py_DECREF on it when we have our
PythonCallback function. One way to do it is to assume that reified
SBInputReaders always have a Python callback (and always call Py_DECREF).
Another one is to add methods or properties to SBInputReader (or make the
m_callback_function property public).



git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@162356 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/scripts/Python/python-extensions.swig b/scripts/Python/python-extensions.swig
index cd8f1cf..24f06a1 100644
--- a/scripts/Python/python-extensions.swig
+++ b/scripts/Python/python-extensions.swig
@@ -25,7 +25,6 @@
                     return PyString_FromStringAndSize (desc, desc_len);
                 else
                     return PyString_FromString("");
-
         }
 }
 %extend lldb::SBBreakpoint {
@@ -485,6 +484,16 @@
         }
 }
 
+// %extend lldb::SBInputReader {
+//         // FIXME: m_callback_function is private and we have no other
+//         // way to access it.
+//         PyObject *lldb::SBInputReader::__del__ (){
+//             // Only call Py_XDECREF if we have a Python object (or NULL)
+//             if (LLDBSwigPythonCallSBInputReaderCallback == $self->m_callback_function)
+//                 Py_XDECREF($self->m_callback_baton);
+//         }
+// }
+
 %pythoncode %{
 
 class declaration(object):
diff --git a/scripts/Python/python-typemaps.swig b/scripts/Python/python-typemaps.swig
index c269795..e212d3f 100644
--- a/scripts/Python/python-typemaps.swig
+++ b/scripts/Python/python-typemaps.swig
@@ -350,6 +350,27 @@
     free($1);
 }
 
+// For lldb::SBInputReader::Callback
+%typemap(in) (lldb::SBInputReader::Callback callback, void *callback_baton) {
+  if (!PyCallable_Check(reinterpret_cast<PyObject*>($input))) {
+    PyErr_SetString(PyExc_TypeError, "Need a callable object!");
+    return NULL;
+  }
+
+  // Don't lose the callback reference
+  Py_INCREF($input);
+  $1 = LLDBSwigPythonCallSBInputReaderCallback;
+  $2 = $input;
+}
+
+%typemap(typecheck) (lldb::SBInputReader::Callback callback, void *baton) {
+  if (!PyCallable_Check(reinterpret_cast<PyObject*>($input))) {
+    $1 = 0;
+  } else {
+    $1 = 1;
+  }
+}
+
 %typemap(in) FILE * {
    if ($input == Py_None)
       $1 = NULL;
diff --git a/scripts/Python/python-wrapper.swig b/scripts/Python/python-wrapper.swig
index 73bad8d..9b48f3b 100644
--- a/scripts/Python/python-wrapper.swig
+++ b/scripts/Python/python-wrapper.swig
@@ -823,5 +823,61 @@
     }
     return retval;
 }
+%}
 
+
+%runtime %{
+// Forward declaration to be inserted at the start of LLDBWrapPython.h
+// I used runtime as a hack to make SWIG place it where it's needed.
+// This is needed to use LLDBSwigPythonCallSBInputReaderCallback in the
+// typemaps and in the extensions (SBInputReader.__del__()).
+#include "SBInputReader.h"
+
+size_t
+LLDBSwigPythonCallSBInputReaderCallback(void *baton,
+                                        lldb::SBInputReader *reader,
+                                        lldb::InputReaderAction notification,
+                                        const char*bytes,
+                                        size_t bytes_len);
+%}
+
+%wrapper %{
+// For the InputReader Callback functions
+SWIGEXPORT size_t
+LLDBSwigPythonCallSBInputReaderCallback(void *baton,
+                                        lldb::SBInputReader *reader,
+                                        lldb::InputReaderAction notification,
+                                        const char*bytes,
+                                        size_t bytes_len) {
+    SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+
+    PyObject *py_InputReader = SWIG_NewPointerObj(reader, SWIGTYPE_p_lldb__SBInputReader, false);
+    PyObject *py_Notification = PyInt_FromLong(notification);
+    PyObject *py_Bytes = PyBytes_FromStringAndSize(bytes, bytes_len);
+
+    PyObject *tuple = PyTuple_Pack(3, py_InputReader, py_Notification, py_Bytes);
+    PyObject *res = PyObject_Call(reinterpret_cast<PyObject*>(baton), tuple, NULL);
+    Py_DECREF(tuple);
+    Py_DECREF(py_InputReader);
+    Py_DECREF(py_Notification);
+    Py_DECREF(py_Bytes);
+
+    if (res == NULL) {
+      PyObject *exc = PyErr_Occurred();
+      if (exc) {
+        ::puts("\nErroring out at LLDBSwigPythonCallSBInputReaderCallback");
+        PyErr_Print();
+      }
+      return 0;
+    }
+
+    size_t result = 0;
+    // If the callback misbehaves and returns Py_None, assume it returned 0
+    if (res != Py_None)
+      result = static_cast<size_t>(PyInt_AsSsize_t(res));
+
+    Py_DECREF(res);
+    SWIG_PYTHON_THREAD_END_BLOCK;
+    return result;
+}
 %}