106c3fb27SDimitry Andric/* Typemap definitions, to allow SWIG to properly handle 'char**' data types.
206c3fb27SDimitry Andric
306c3fb27SDimitry AndricNOTE: If there's logic to free memory in a %typemap(freearg), it will also be
406c3fb27SDimitry Andricrun if you call SWIG_fail on an error path. Don't manually free() an argument
506c3fb27SDimitry AndricAND call SWIG_fail at the same time, because it will result in a double free.
606c3fb27SDimitry Andric
706c3fb27SDimitry Andric*/
8130d950cSDimitry Andric
9e8d8bef9SDimitry Andric%inline %{
10e8d8bef9SDimitry Andric
11e8d8bef9SDimitry Andric#include "../bindings/python/python-typemaps.h"
12e8d8bef9SDimitry Andric
13e8d8bef9SDimitry Andric%}
14e8d8bef9SDimitry Andric
15130d950cSDimitry Andric%typemap(in) char ** {
16130d950cSDimitry Andric  /* Check if is a list  */
17130d950cSDimitry Andric  if (PythonList::Check($input)) {
18130d950cSDimitry Andric    PythonList list(PyRefType::Borrowed, $input);
19130d950cSDimitry Andric    int size = list.GetSize();
20130d950cSDimitry Andric    int i = 0;
21130d950cSDimitry Andric    $1 = (char **)malloc((size + 1) * sizeof(char *));
22130d950cSDimitry Andric    for (i = 0; i < size; i++) {
23130d950cSDimitry Andric      PythonString py_str = list.GetItemAtIndex(i).AsType<PythonString>();
24130d950cSDimitry Andric      if (!py_str.IsAllocated()) {
25130d950cSDimitry Andric        PyErr_SetString(PyExc_TypeError, "list must contain strings");
26bdd1243dSDimitry Andric        SWIG_fail;
27130d950cSDimitry Andric      }
28130d950cSDimitry Andric
29130d950cSDimitry Andric      $1[i] = const_cast<char *>(py_str.GetString().data());
30130d950cSDimitry Andric    }
31130d950cSDimitry Andric    $1[i] = 0;
32130d950cSDimitry Andric  } else if ($input == Py_None) {
33130d950cSDimitry Andric    $1 = NULL;
34130d950cSDimitry Andric  } else {
35130d950cSDimitry Andric    PyErr_SetString(PyExc_TypeError, "not a list");
36bdd1243dSDimitry Andric    SWIG_fail;
37130d950cSDimitry Andric  }
38130d950cSDimitry Andric}
39130d950cSDimitry Andric
40130d950cSDimitry Andric%typemap(typecheck) char ** {
41130d950cSDimitry Andric  /* Check if is a list  */
42130d950cSDimitry Andric  $1 = 1;
43130d950cSDimitry Andric  if (PythonList::Check($input)) {
44130d950cSDimitry Andric    PythonList list(PyRefType::Borrowed, $input);
45130d950cSDimitry Andric    int size = list.GetSize();
46130d950cSDimitry Andric    int i = 0;
47130d950cSDimitry Andric    for (i = 0; i < size; i++) {
48130d950cSDimitry Andric      PythonString s = list.GetItemAtIndex(i).AsType<PythonString>();
490eae32dcSDimitry Andric      if (!s.IsAllocated()) {
500eae32dcSDimitry Andric        $1 = 0;
51130d950cSDimitry Andric      }
52130d950cSDimitry Andric    }
530eae32dcSDimitry Andric  } else {
54130d950cSDimitry Andric    $1 = (($input == Py_None) ? 1 : 0);
55130d950cSDimitry Andric  }
56130d950cSDimitry Andric}
57130d950cSDimitry Andric
58130d950cSDimitry Andric%typemap(freearg) char** {
59130d950cSDimitry Andric  free((char *) $1);
60130d950cSDimitry Andric}
61130d950cSDimitry Andric
6206c3fb27SDimitry Andric%typecheck(SWIG_TYPECHECK_POINTER) lldb::ScriptObjectPtr {
6306c3fb27SDimitry Andric  PythonObject obj(PyRefType::Borrowed, $input);
6406c3fb27SDimitry Andric  if (!obj.IsValid()) {
6506c3fb27SDimitry Andric    PyErr_Clear();
6606c3fb27SDimitry Andric    $1 = 0;
6706c3fb27SDimitry Andric  } else {
6806c3fb27SDimitry Andric    $1 = 1;
6906c3fb27SDimitry Andric  }
7006c3fb27SDimitry Andric}
7106c3fb27SDimitry Andric
7206c3fb27SDimitry Andric%typemap(in) lldb::ScriptObjectPtr {
7306c3fb27SDimitry Andric  if ($input == Py_None) {
7406c3fb27SDimitry Andric    $1 = nullptr;
7506c3fb27SDimitry Andric  } else {
7606c3fb27SDimitry Andric    PythonObject obj(PyRefType::Borrowed, $input);
7706c3fb27SDimitry Andric    if (!obj.IsValid()) {
7806c3fb27SDimitry Andric      PyErr_SetString(PyExc_TypeError, "Script object is not valid");
7906c3fb27SDimitry Andric      SWIG_fail;
8006c3fb27SDimitry Andric    }
8106c3fb27SDimitry Andric
8206c3fb27SDimitry Andric    auto lldb_module = PythonModule::Import("lldb");
8306c3fb27SDimitry Andric    if (!lldb_module) {
8406c3fb27SDimitry Andric      std::string err_msg = llvm::toString(lldb_module.takeError());
8506c3fb27SDimitry Andric      PyErr_SetString(PyExc_TypeError, err_msg.c_str());
8606c3fb27SDimitry Andric      SWIG_fail;
8706c3fb27SDimitry Andric    }
8806c3fb27SDimitry Andric
8906c3fb27SDimitry Andric    auto sb_structured_data_class = lldb_module.get().Get("SBStructuredData");
9006c3fb27SDimitry Andric    if (!sb_structured_data_class) {
9106c3fb27SDimitry Andric      std::string err_msg = llvm::toString(sb_structured_data_class.takeError());
9206c3fb27SDimitry Andric      PyErr_SetString(PyExc_TypeError, err_msg.c_str());
9306c3fb27SDimitry Andric      SWIG_fail;
9406c3fb27SDimitry Andric    }
9506c3fb27SDimitry Andric
9606c3fb27SDimitry Andric    if (obj.IsInstance(sb_structured_data_class.get())) {
9706c3fb27SDimitry Andric      $1 = obj.get();
9806c3fb27SDimitry Andric    } else {
9906c3fb27SDimitry Andric      auto type = obj.GetType();
10006c3fb27SDimitry Andric      if (!type) {
10106c3fb27SDimitry Andric        std::string err_msg = llvm::toString(type.takeError());
10206c3fb27SDimitry Andric        PyErr_SetString(PyExc_TypeError, err_msg.c_str());
10306c3fb27SDimitry Andric        SWIG_fail;
10406c3fb27SDimitry Andric      }
10506c3fb27SDimitry Andric
10606c3fb27SDimitry Andric      auto type_name = As<std::string>(type.get().GetAttribute("__name__"));
10706c3fb27SDimitry Andric      if (!type_name) {
10806c3fb27SDimitry Andric        std::string err_msg = llvm::toString(type_name.takeError());
10906c3fb27SDimitry Andric        PyErr_SetString(PyExc_TypeError, err_msg.c_str());
11006c3fb27SDimitry Andric        SWIG_fail;
11106c3fb27SDimitry Andric      }
11206c3fb27SDimitry Andric
113*cb14a3feSDimitry Andric      if (llvm::StringRef(type_name.get()).starts_with("SB")) {
11406c3fb27SDimitry Andric        std::string error_msg = "Input type is invalid: " + type_name.get();
11506c3fb27SDimitry Andric        PyErr_SetString(PyExc_TypeError, error_msg.c_str());
11606c3fb27SDimitry Andric        SWIG_fail;
11706c3fb27SDimitry Andric      } else {
11806c3fb27SDimitry Andric        $1 = obj.get();
11906c3fb27SDimitry Andric      }
12006c3fb27SDimitry Andric    }
12106c3fb27SDimitry Andric  }
12206c3fb27SDimitry Andric}
12306c3fb27SDimitry Andric
12406c3fb27SDimitry Andric%typemap(out) lldb::ScriptObjectPtr {
12506c3fb27SDimitry Andric  $result = (PyObject*) $1;
12606c3fb27SDimitry Andric  if (!$result)
12706c3fb27SDimitry Andric    $result = Py_None;
12806c3fb27SDimitry Andric  Py_INCREF($result);
12906c3fb27SDimitry Andric}
13006c3fb27SDimitry Andric
13106c3fb27SDimitry Andric%typemap(out) lldb::SBScriptObject {
13206c3fb27SDimitry Andric  $result = nullptr;
13306c3fb27SDimitry Andric  if (const void* impl = $1.GetPointer())
13406c3fb27SDimitry Andric    $result = (PyObject*) impl;
13506c3fb27SDimitry Andric  if (!$result) {
13606c3fb27SDimitry Andric    $result = Py_None;
13706c3fb27SDimitry Andric    Py_INCREF(Py_None);
13806c3fb27SDimitry Andric  } else {
13906c3fb27SDimitry Andric    Py_INCREF($result);
14006c3fb27SDimitry Andric  }
14106c3fb27SDimitry Andric}
14206c3fb27SDimitry Andric
143130d950cSDimitry Andric%typemap(out) char** {
144130d950cSDimitry Andric  int len;
145130d950cSDimitry Andric  int i;
146130d950cSDimitry Andric  len = 0;
1470eae32dcSDimitry Andric  while ($1[len])
1480eae32dcSDimitry Andric    len++;
149130d950cSDimitry Andric  PythonList list(len);
150130d950cSDimitry Andric  for (i = 0; i < len; i++)
151130d950cSDimitry Andric    list.SetItemAtIndex(i, PythonString($1[i]));
152130d950cSDimitry Andric  $result = list.release();
153130d950cSDimitry Andric}
154130d950cSDimitry Andric
155130d950cSDimitry Andric%typemap(in) lldb::tid_t {
1565ffd83dbSDimitry Andric  PythonObject obj = Retain<PythonObject>($input);
1575ffd83dbSDimitry Andric  lldb::tid_t value = unwrapOrSetPythonException(As<unsigned long long>(obj));
1585ffd83dbSDimitry Andric  if (PyErr_Occurred())
159bdd1243dSDimitry Andric    SWIG_fail;
1605ffd83dbSDimitry Andric  $1 = value;
161130d950cSDimitry Andric}
162130d950cSDimitry Andric
163130d950cSDimitry Andric%typemap(in) lldb::StateType {
1645ffd83dbSDimitry Andric  PythonObject obj = Retain<PythonObject>($input);
1655ffd83dbSDimitry Andric  unsigned long long state_type_value =
1665ffd83dbSDimitry Andric      unwrapOrSetPythonException(As<unsigned long long>(obj));
1675ffd83dbSDimitry Andric  if (PyErr_Occurred())
168bdd1243dSDimitry Andric    SWIG_fail;
169130d950cSDimitry Andric  if (state_type_value > lldb::StateType::kLastStateType) {
170130d950cSDimitry Andric    PyErr_SetString(PyExc_ValueError, "Not a valid StateType value");
171bdd1243dSDimitry Andric    SWIG_fail;
172130d950cSDimitry Andric  }
173130d950cSDimitry Andric  $1 = static_cast<lldb::StateType>(state_type_value);
174130d950cSDimitry Andric}
175130d950cSDimitry Andric
176130d950cSDimitry Andric/* Typemap definitions to allow SWIG to properly handle char buffer. */
177130d950cSDimitry Andric
178130d950cSDimitry Andric// typemap for a char buffer
179130d950cSDimitry Andric%typemap(in) (char *dst, size_t dst_len) {
18006c3fb27SDimitry Andric  if (!PyLong_Check($input)) {
181130d950cSDimitry Andric    PyErr_SetString(PyExc_ValueError, "Expecting an integer");
182bdd1243dSDimitry Andric    SWIG_fail;
183130d950cSDimitry Andric  }
18406c3fb27SDimitry Andric  $2 = PyLong_AsLong($input);
185130d950cSDimitry Andric  if ($2 <= 0) {
186130d950cSDimitry Andric    PyErr_SetString(PyExc_ValueError, "Positive integer expected");
187bdd1243dSDimitry Andric    SWIG_fail;
188130d950cSDimitry Andric  }
189130d950cSDimitry Andric  $1 = (char *)malloc($2);
190130d950cSDimitry Andric}
191130d950cSDimitry Andric// SBProcess::ReadCStringFromMemory() uses a void*, but needs to be treated
192130d950cSDimitry Andric// as char data instead of byte data.
193130d950cSDimitry Andric%typemap(in) (void *char_buf, size_t size) = (char *dst, size_t dst_len);
194130d950cSDimitry Andric
195130d950cSDimitry Andric// Return the char buffer.  Discarding any previous return result
196130d950cSDimitry Andric%typemap(argout) (char *dst, size_t dst_len) {
197130d950cSDimitry Andric  Py_XDECREF($result); /* Blow away any previous result */
198130d950cSDimitry Andric  if (result == 0) {
199130d950cSDimitry Andric    PythonString string("");
200130d950cSDimitry Andric    $result = string.release();
201130d950cSDimitry Andric    Py_INCREF($result);
202130d950cSDimitry Andric  } else {
203130d950cSDimitry Andric    llvm::StringRef ref(static_cast<const char *>($1), result);
204130d950cSDimitry Andric    PythonString string(ref);
205130d950cSDimitry Andric    $result = string.release();
206130d950cSDimitry Andric  }
207130d950cSDimitry Andric  free($1);
208130d950cSDimitry Andric}
209130d950cSDimitry Andric// SBProcess::ReadCStringFromMemory() uses a void*, but needs to be treated
210130d950cSDimitry Andric// as char data instead of byte data.
211130d950cSDimitry Andric%typemap(argout) (void *char_buf, size_t size) = (char *dst, size_t dst_len);
212130d950cSDimitry Andric
213130d950cSDimitry Andric
214130d950cSDimitry Andric// typemap for handling an snprintf-like API like SBThread::GetStopDescription.
215130d950cSDimitry Andric%typemap(in) (char *dst_or_null, size_t dst_len) {
21606c3fb27SDimitry Andric  if (!PyLong_Check($input)) {
217130d950cSDimitry Andric    PyErr_SetString(PyExc_ValueError, "Expecting an integer");
218bdd1243dSDimitry Andric    SWIG_fail;
219130d950cSDimitry Andric  }
22006c3fb27SDimitry Andric  $2 = PyLong_AsLong($input);
221130d950cSDimitry Andric  if ($2 <= 0) {
222130d950cSDimitry Andric    PyErr_SetString(PyExc_ValueError, "Positive integer expected");
223bdd1243dSDimitry Andric    SWIG_fail;
224130d950cSDimitry Andric  }
225130d950cSDimitry Andric  $1 = (char *)malloc($2);
226130d950cSDimitry Andric}
227130d950cSDimitry Andric%typemap(argout) (char *dst_or_null, size_t dst_len) {
228130d950cSDimitry Andric  Py_XDECREF($result); /* Blow away any previous result */
229130d950cSDimitry Andric  llvm::StringRef ref($1);
230130d950cSDimitry Andric  PythonString string(ref);
231130d950cSDimitry Andric  $result = string.release();
232130d950cSDimitry Andric  free($1);
233130d950cSDimitry Andric}
234130d950cSDimitry Andric
235130d950cSDimitry Andric
236130d950cSDimitry Andric// typemap for an outgoing buffer
237130d950cSDimitry Andric// See also SBEvent::SBEvent(uint32_t event, const char *cstr, uint32_t cstr_len).
238130d950cSDimitry Andric// Ditto for SBProcess::PutSTDIN(const char *src, size_t src_len).
239130d950cSDimitry Andric%typemap(in) (const char *cstr, uint32_t cstr_len),
240130d950cSDimitry Andric             (const char *src, size_t src_len) {
241130d950cSDimitry Andric  if (PythonString::Check($input)) {
242130d950cSDimitry Andric    PythonString str(PyRefType::Borrowed, $input);
243130d950cSDimitry Andric    $1 = (char *)str.GetString().data();
244130d950cSDimitry Andric    $2 = str.GetSize();
2450eae32dcSDimitry Andric  } else if (PythonByteArray::Check($input)) {
246130d950cSDimitry Andric    PythonByteArray bytearray(PyRefType::Borrowed, $input);
247130d950cSDimitry Andric    $1 = (char *)bytearray.GetBytes().data();
248130d950cSDimitry Andric    $2 = bytearray.GetSize();
2490eae32dcSDimitry Andric  } else if (PythonBytes::Check($input)) {
250130d950cSDimitry Andric    PythonBytes bytes(PyRefType::Borrowed, $input);
251130d950cSDimitry Andric    $1 = (char *)bytes.GetBytes().data();
252130d950cSDimitry Andric    $2 = bytes.GetSize();
2530eae32dcSDimitry Andric  } else {
254130d950cSDimitry Andric    PyErr_SetString(PyExc_ValueError, "Expecting a string");
255bdd1243dSDimitry Andric    SWIG_fail;
256130d950cSDimitry Andric  }
257130d950cSDimitry Andric}
258130d950cSDimitry Andric// For SBProcess::WriteMemory, SBTarget::GetInstructions and SBDebugger::DispatchInput.
259130d950cSDimitry Andric%typemap(in) (const void *buf, size_t size),
260130d950cSDimitry Andric             (const void *data, size_t data_len) {
261130d950cSDimitry Andric  if (PythonString::Check($input)) {
262130d950cSDimitry Andric    PythonString str(PyRefType::Borrowed, $input);
263130d950cSDimitry Andric    $1 = (void *)str.GetString().data();
264130d950cSDimitry Andric    $2 = str.GetSize();
2650eae32dcSDimitry Andric  } else if (PythonByteArray::Check($input)) {
266130d950cSDimitry Andric    PythonByteArray bytearray(PyRefType::Borrowed, $input);
267130d950cSDimitry Andric    $1 = (void *)bytearray.GetBytes().data();
268130d950cSDimitry Andric    $2 = bytearray.GetSize();
2690eae32dcSDimitry Andric  } else if (PythonBytes::Check($input)) {
270130d950cSDimitry Andric    PythonBytes bytes(PyRefType::Borrowed, $input);
271130d950cSDimitry Andric    $1 = (void *)bytes.GetBytes().data();
272130d950cSDimitry Andric    $2 = bytes.GetSize();
2730eae32dcSDimitry Andric  } else {
274130d950cSDimitry Andric    PyErr_SetString(PyExc_ValueError, "Expecting a buffer");
275bdd1243dSDimitry Andric    SWIG_fail;
276130d950cSDimitry Andric  }
277130d950cSDimitry Andric}
278130d950cSDimitry Andric
279130d950cSDimitry Andric// typemap for an incoming buffer
280130d950cSDimitry Andric// See also SBProcess::ReadMemory.
281130d950cSDimitry Andric%typemap(in) (void *buf, size_t size) {
28206c3fb27SDimitry Andric  if (PyLong_Check($input)) {
283130d950cSDimitry Andric    $2 = PyLong_AsLong($input);
284130d950cSDimitry Andric  } else {
285130d950cSDimitry Andric    PyErr_SetString(PyExc_ValueError, "Expecting an integer or long object");
286bdd1243dSDimitry Andric    SWIG_fail;
287130d950cSDimitry Andric  }
288130d950cSDimitry Andric  if ($2 <= 0) {
289130d950cSDimitry Andric    PyErr_SetString(PyExc_ValueError, "Positive integer expected");
290bdd1243dSDimitry Andric    SWIG_fail;
291130d950cSDimitry Andric  }
292130d950cSDimitry Andric  $1 = (void *)malloc($2);
293130d950cSDimitry Andric}
294130d950cSDimitry Andric
295130d950cSDimitry Andric// Return the buffer.  Discarding any previous return result
296130d950cSDimitry Andric// See also SBProcess::ReadMemory.
297130d950cSDimitry Andric%typemap(argout) (void *buf, size_t size) {
298130d950cSDimitry Andric  Py_XDECREF($result); /* Blow away any previous result */
299130d950cSDimitry Andric  if (result == 0) {
300130d950cSDimitry Andric    $result = Py_None;
301130d950cSDimitry Andric    Py_INCREF($result);
302130d950cSDimitry Andric  } else {
303130d950cSDimitry Andric    PythonBytes bytes(static_cast<const uint8_t *>($1), result);
304130d950cSDimitry Andric    $result = bytes.release();
305130d950cSDimitry Andric  }
306130d950cSDimitry Andric  free($1);
307130d950cSDimitry Andric}
308130d950cSDimitry Andric
309130d950cSDimitry Andric%{
310130d950cSDimitry Andricnamespace {
311130d950cSDimitry Andrictemplate <class T>
312130d950cSDimitry AndricT PyLongAsT(PyObject *obj) {
313130d950cSDimitry Andric  static_assert(true, "unsupported type");
314130d950cSDimitry Andric}
315130d950cSDimitry Andric
316130d950cSDimitry Andrictemplate <> uint64_t PyLongAsT<uint64_t>(PyObject *obj) {
317130d950cSDimitry Andric  return static_cast<uint64_t>(PyLong_AsUnsignedLongLong(obj));
318130d950cSDimitry Andric}
319130d950cSDimitry Andric
320130d950cSDimitry Andrictemplate <> uint32_t PyLongAsT<uint32_t>(PyObject *obj) {
321130d950cSDimitry Andric  return static_cast<uint32_t>(PyLong_AsUnsignedLong(obj));
322130d950cSDimitry Andric}
323130d950cSDimitry Andric
324130d950cSDimitry Andrictemplate <> int64_t PyLongAsT<int64_t>(PyObject *obj) {
325130d950cSDimitry Andric  return static_cast<int64_t>(PyLong_AsLongLong(obj));
326130d950cSDimitry Andric}
327130d950cSDimitry Andric
328130d950cSDimitry Andrictemplate <> int32_t PyLongAsT<int32_t>(PyObject *obj) {
329130d950cSDimitry Andric  return static_cast<int32_t>(PyLong_AsLong(obj));
330130d950cSDimitry Andric}
331130d950cSDimitry Andric
3320eae32dcSDimitry Andrictemplate <class T> bool SetNumberFromPyObject(T &number, PyObject *obj) {
33306c3fb27SDimitry Andric  if (PyLong_Check(obj))
334130d950cSDimitry Andric    number = PyLongAsT<T>(obj);
3350eae32dcSDimitry Andric  else
3360eae32dcSDimitry Andric    return false;
337130d950cSDimitry Andric
338130d950cSDimitry Andric  return true;
339130d950cSDimitry Andric}
340130d950cSDimitry Andric
3410eae32dcSDimitry Andrictemplate <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
342130d950cSDimitry Andric  if (PyFloat_Check(obj)) {
343130d950cSDimitry Andric    number = PyFloat_AsDouble(obj);
344130d950cSDimitry Andric    return true;
345130d950cSDimitry Andric  }
346130d950cSDimitry Andric
347130d950cSDimitry Andric  return false;
348130d950cSDimitry Andric}
349130d950cSDimitry Andric
350130d950cSDimitry Andric} // namespace
351130d950cSDimitry Andric%}
352130d950cSDimitry Andric
353130d950cSDimitry Andric// these typemaps allow Python users to pass list objects
354130d950cSDimitry Andric// and have them turn into C++ arrays (this is useful, for instance
355130d950cSDimitry Andric// when creating SBData objects from lists of numbers)
356130d950cSDimitry Andric%typemap(in) (uint64_t* array, size_t array_len),
357130d950cSDimitry Andric             (uint32_t* array, size_t array_len),
358130d950cSDimitry Andric             (int64_t* array, size_t array_len),
359130d950cSDimitry Andric             (int32_t* array, size_t array_len),
360130d950cSDimitry Andric             (double* array, size_t array_len) {
361130d950cSDimitry Andric  /* Check if is a list  */
362130d950cSDimitry Andric  if (PyList_Check($input)) {
363130d950cSDimitry Andric    int size = PyList_Size($input);
364130d950cSDimitry Andric    int i = 0;
365130d950cSDimitry Andric    $2 = size;
366130d950cSDimitry Andric    $1 = ($1_type)malloc(size * sizeof($*1_type));
367130d950cSDimitry Andric    for (i = 0; i < size; i++) {
368130d950cSDimitry Andric      PyObject *o = PyList_GetItem($input, i);
369130d950cSDimitry Andric      if (!SetNumberFromPyObject($1[i], o)) {
370130d950cSDimitry Andric        PyErr_SetString(PyExc_TypeError, "list must contain numbers");
371bdd1243dSDimitry Andric        SWIG_fail;
372130d950cSDimitry Andric      }
373130d950cSDimitry Andric
374130d950cSDimitry Andric      if (PyErr_Occurred()) {
375bdd1243dSDimitry Andric        SWIG_fail;
376130d950cSDimitry Andric      }
377130d950cSDimitry Andric    }
378130d950cSDimitry Andric  } else if ($input == Py_None) {
379130d950cSDimitry Andric    $1 = NULL;
380130d950cSDimitry Andric    $2 = 0;
381130d950cSDimitry Andric  } else {
382130d950cSDimitry Andric    PyErr_SetString(PyExc_TypeError, "not a list");
383bdd1243dSDimitry Andric    SWIG_fail;
384130d950cSDimitry Andric  }
385130d950cSDimitry Andric}
386130d950cSDimitry Andric
387130d950cSDimitry Andric%typemap(freearg) (uint64_t* array, size_t array_len),
388130d950cSDimitry Andric                  (uint32_t* array, size_t array_len),
389130d950cSDimitry Andric                  (int64_t* array, size_t array_len),
390130d950cSDimitry Andric                  (int32_t* array, size_t array_len),
391130d950cSDimitry Andric                  (double* array, size_t array_len) {
392130d950cSDimitry Andric  free($1);
393130d950cSDimitry Andric}
394130d950cSDimitry Andric
395130d950cSDimitry Andric// these typemaps wrap SBModule::GetVersion() from requiring a memory buffer
396130d950cSDimitry Andric// to the more Pythonic style where a list is returned and no previous allocation
397130d950cSDimitry Andric// is necessary - this will break if more than 50 versions are ever returned
398130d950cSDimitry Andric%typemap(typecheck) (uint32_t *versions, uint32_t num_versions) {
399130d950cSDimitry Andric  $1 = ($input == Py_None ? 1 : 0);
400130d950cSDimitry Andric}
401130d950cSDimitry Andric
402130d950cSDimitry Andric%typemap(in, numinputs=0) (uint32_t *versions) {
403130d950cSDimitry Andric  $1 = (uint32_t *)malloc(sizeof(uint32_t) * 50);
404130d950cSDimitry Andric}
405130d950cSDimitry Andric
406130d950cSDimitry Andric%typemap(in, numinputs=0) (uint32_t num_versions) {
407130d950cSDimitry Andric  $1 = 50;
408130d950cSDimitry Andric}
409130d950cSDimitry Andric
410130d950cSDimitry Andric%typemap(argout) (uint32_t *versions, uint32_t num_versions) {
411130d950cSDimitry Andric  uint32_t count = result;
412130d950cSDimitry Andric  if (count >= $2)
413130d950cSDimitry Andric    count = $2;
414130d950cSDimitry Andric  PyObject *list = PyList_New(count);
4150eae32dcSDimitry Andric  for (uint32_t j = 0; j < count; j++) {
41606c3fb27SDimitry Andric    PyObject *item = PyLong_FromLong($1[j]);
417130d950cSDimitry Andric    int ok = PyList_SetItem(list, j, item);
4180eae32dcSDimitry Andric    if (ok != 0) {
419130d950cSDimitry Andric      $result = Py_None;
420130d950cSDimitry Andric      break;
421130d950cSDimitry Andric    }
422130d950cSDimitry Andric  }
423130d950cSDimitry Andric  $result = list;
424130d950cSDimitry Andric}
425130d950cSDimitry Andric
426130d950cSDimitry Andric%typemap(freearg) (uint32_t *versions) {
427130d950cSDimitry Andric  free($1);
428130d950cSDimitry Andric}
429130d950cSDimitry Andric
430130d950cSDimitry Andric
431130d950cSDimitry Andric// For Log::LogOutputCallback
432130d950cSDimitry Andric%typemap(in) (lldb::LogOutputCallback log_callback, void *baton) {
4330eae32dcSDimitry Andric  if (!($input == Py_None ||
4340eae32dcSDimitry Andric        PyCallable_Check(reinterpret_cast<PyObject *>($input)))) {
435130d950cSDimitry Andric    PyErr_SetString(PyExc_TypeError, "Need a callable object or None!");
436bdd1243dSDimitry Andric    SWIG_fail;
437130d950cSDimitry Andric  }
438130d950cSDimitry Andric
439130d950cSDimitry Andric  // FIXME (filcab): We can't currently check if our callback is already
440130d950cSDimitry Andric  // LLDBSwigPythonCallPythonLogOutputCallback (to DECREF the previous
441130d950cSDimitry Andric  // baton) nor can we just remove all traces of a callback, if we want to
442130d950cSDimitry Andric  // revert to a file logging mechanism.
443130d950cSDimitry Andric
444130d950cSDimitry Andric  // Don't lose the callback reference
445130d950cSDimitry Andric  Py_INCREF($input);
446130d950cSDimitry Andric  $1 = LLDBSwigPythonCallPythonLogOutputCallback;
447130d950cSDimitry Andric  $2 = $input;
448130d950cSDimitry Andric}
449130d950cSDimitry Andric
450130d950cSDimitry Andric%typemap(typecheck) (lldb::LogOutputCallback log_callback, void *baton) {
451130d950cSDimitry Andric  $1 = $input == Py_None;
452130d950cSDimitry Andric  $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
453130d950cSDimitry Andric}
454130d950cSDimitry Andric
45506c3fb27SDimitry Andric// For lldb::SBDebuggerDestroyCallback
45606c3fb27SDimitry Andric%typemap(in) (lldb::SBDebuggerDestroyCallback destroy_callback, void *baton) {
45706c3fb27SDimitry Andric  if (!($input == Py_None ||
45806c3fb27SDimitry Andric        PyCallable_Check(reinterpret_cast<PyObject *>($input)))) {
45906c3fb27SDimitry Andric    PyErr_SetString(PyExc_TypeError, "Need a callable object or None!");
46006c3fb27SDimitry Andric    SWIG_fail;
46106c3fb27SDimitry Andric  }
46206c3fb27SDimitry Andric
46306c3fb27SDimitry Andric  // FIXME (filcab): We can't currently check if our callback is already
46406c3fb27SDimitry Andric  // LLDBSwigPythonCallPythonSBDebuggerTerminateCallback (to DECREF the previous
46506c3fb27SDimitry Andric  // baton) nor can we just remove all traces of a callback, if we want to
46606c3fb27SDimitry Andric  // revert to a file logging mechanism.
46706c3fb27SDimitry Andric
46806c3fb27SDimitry Andric  // Don't lose the callback reference
46906c3fb27SDimitry Andric  Py_INCREF($input);
47006c3fb27SDimitry Andric  $1 = LLDBSwigPythonCallPythonSBDebuggerTerminateCallback;
47106c3fb27SDimitry Andric  $2 = $input;
47206c3fb27SDimitry Andric}
47306c3fb27SDimitry Andric
47406c3fb27SDimitry Andric%typemap(typecheck) (lldb::SBDebuggerDestroyCallback destroy_callback, void *baton) {
47506c3fb27SDimitry Andric  $1 = $input == Py_None;
47606c3fb27SDimitry Andric  $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
47706c3fb27SDimitry Andric}
478130d950cSDimitry Andric
479130d950cSDimitry Andric%typemap(in) lldb::FileSP {
480130d950cSDimitry Andric  PythonFile py_file(PyRefType::Borrowed, $input);
481130d950cSDimitry Andric  if (!py_file) {
482130d950cSDimitry Andric    PyErr_SetString(PyExc_TypeError, "not a file");
483bdd1243dSDimitry Andric    SWIG_fail;
484130d950cSDimitry Andric  }
485130d950cSDimitry Andric  auto sp = unwrapOrSetPythonException(py_file.ConvertToFile());
486130d950cSDimitry Andric  if (!sp)
487bdd1243dSDimitry Andric    SWIG_fail;
488130d950cSDimitry Andric  $1 = sp;
489130d950cSDimitry Andric}
490130d950cSDimitry Andric
491130d950cSDimitry Andric%typemap(in) lldb::FileSP FORCE_IO_METHODS {
492130d950cSDimitry Andric  PythonFile py_file(PyRefType::Borrowed, $input);
493130d950cSDimitry Andric  if (!py_file) {
494130d950cSDimitry Andric    PyErr_SetString(PyExc_TypeError, "not a file");
495bdd1243dSDimitry Andric    SWIG_fail;
496130d950cSDimitry Andric  }
4970eae32dcSDimitry Andric  auto sp = unwrapOrSetPythonException(
4980eae32dcSDimitry Andric      py_file.ConvertToFileForcingUseOfScriptingIOMethods());
499130d950cSDimitry Andric  if (!sp)
500bdd1243dSDimitry Andric    SWIG_fail;
501130d950cSDimitry Andric  $1 = sp;
502130d950cSDimitry Andric}
503130d950cSDimitry Andric
504130d950cSDimitry Andric%typemap(in) lldb::FileSP BORROWED {
505130d950cSDimitry Andric  PythonFile py_file(PyRefType::Borrowed, $input);
506130d950cSDimitry Andric  if (!py_file) {
507130d950cSDimitry Andric    PyErr_SetString(PyExc_TypeError, "not a file");
508bdd1243dSDimitry Andric    SWIG_fail;
509130d950cSDimitry Andric  }
5100eae32dcSDimitry Andric  auto sp =
5110eae32dcSDimitry Andric      unwrapOrSetPythonException(py_file.ConvertToFile(/*borrowed=*/true));
512130d950cSDimitry Andric  if (!sp)
513bdd1243dSDimitry Andric    SWIG_fail;
514130d950cSDimitry Andric  $1 = sp;
515130d950cSDimitry Andric}
516130d950cSDimitry Andric
517130d950cSDimitry Andric%typemap(in) lldb::FileSP BORROWED_FORCE_IO_METHODS {
518130d950cSDimitry Andric  PythonFile py_file(PyRefType::Borrowed, $input);
519130d950cSDimitry Andric  if (!py_file) {
520130d950cSDimitry Andric    PyErr_SetString(PyExc_TypeError, "not a file");
521bdd1243dSDimitry Andric    SWIG_fail;
522130d950cSDimitry Andric  }
5230eae32dcSDimitry Andric  auto sp = unwrapOrSetPythonException(
5240eae32dcSDimitry Andric      py_file.ConvertToFileForcingUseOfScriptingIOMethods(/*borrowed=*/true));
525130d950cSDimitry Andric  if (!sp)
526bdd1243dSDimitry Andric    SWIG_fail;
527130d950cSDimitry Andric  $1 = sp;
528130d950cSDimitry Andric}
529130d950cSDimitry Andric
530130d950cSDimitry Andric%typecheck(SWIG_TYPECHECK_POINTER) lldb::FileSP {
531130d950cSDimitry Andric  if (PythonFile::Check($input)) {
532130d950cSDimitry Andric    $1 = 1;
533130d950cSDimitry Andric  } else {
534130d950cSDimitry Andric    PyErr_Clear();
535130d950cSDimitry Andric    $1 = 0;
536130d950cSDimitry Andric  }
537130d950cSDimitry Andric}
538130d950cSDimitry Andric
539130d950cSDimitry Andric%typemap(out) lldb::FileSP {
540130d950cSDimitry Andric  $result = nullptr;
541f3fd488fSDimitry Andric  const lldb::FileSP &sp = $1;
542130d950cSDimitry Andric  if (sp) {
543130d950cSDimitry Andric    PythonFile pyfile = unwrapOrSetPythonException(PythonFile::FromFile(*sp));
544130d950cSDimitry Andric    if (!pyfile.IsValid())
545bdd1243dSDimitry Andric      SWIG_fail;
546130d950cSDimitry Andric    $result = pyfile.release();
547130d950cSDimitry Andric  }
5480eae32dcSDimitry Andric  if (!$result) {
549130d950cSDimitry Andric    $result = Py_None;
550130d950cSDimitry Andric    Py_INCREF(Py_None);
551130d950cSDimitry Andric  }
552130d950cSDimitry Andric}
553130d950cSDimitry Andric
554130d950cSDimitry Andric%typemap(in) (const char* string, int len) {
5550eae32dcSDimitry Andric  if ($input == Py_None) {
556130d950cSDimitry Andric    $1 = NULL;
557130d950cSDimitry Andric    $2 = 0;
5580eae32dcSDimitry Andric  } else if (PythonString::Check($input)) {
559130d950cSDimitry Andric    PythonString py_str(PyRefType::Borrowed, $input);
560130d950cSDimitry Andric    llvm::StringRef str = py_str.GetString();
561130d950cSDimitry Andric    $1 = const_cast<char *>(str.data());
562130d950cSDimitry Andric    $2 = str.size();
563130d950cSDimitry Andric    // In Python 2, if $input is a PyUnicode object then this
564130d950cSDimitry Andric    // will trigger a Unicode -> String conversion, in which
565130d950cSDimitry Andric    // case the `PythonString` will now own the PyString.  Thus
566130d950cSDimitry Andric    // if it goes out of scope, the data will be deleted.  The
567130d950cSDimitry Andric    // only way to avoid this is to leak the Python object in
568130d950cSDimitry Andric    // that case.  Note that if there was no conversion, then
569130d950cSDimitry Andric    // releasing the string will not leak anything, since we
570130d950cSDimitry Andric    // created this as a borrowed reference.
571130d950cSDimitry Andric    py_str.release();
5720eae32dcSDimitry Andric  } else {
573130d950cSDimitry Andric    PyErr_SetString(PyExc_TypeError, "not a string-like object");
574bdd1243dSDimitry Andric    SWIG_fail;
575130d950cSDimitry Andric  }
576130d950cSDimitry Andric}
577130d950cSDimitry Andric
578130d950cSDimitry Andric// These two pybuffer macros are copied out of swig/Lib/python/pybuffer.i,
579130d950cSDimitry Andric// and fixed so they will not crash if PyObject_GetBuffer fails.
580130d950cSDimitry Andric// https://github.com/swig/swig/issues/1640
5815ffd83dbSDimitry Andric//
5825ffd83dbSDimitry Andric// I've also moved the call to PyBuffer_Release to the end of the SWIG wrapper,
5835ffd83dbSDimitry Andric// doing it right away is not legal according to the python buffer protocol.
584130d950cSDimitry Andric
585130d950cSDimitry Andric%define %pybuffer_mutable_binary(TYPEMAP, SIZE)
5865ffd83dbSDimitry Andric%typemap(in) (TYPEMAP, SIZE) (Py_buffer_RAII view) {
5870eae32dcSDimitry Andric  int res;
5880eae32dcSDimitry Andric  Py_ssize_t size = 0;
5890eae32dcSDimitry Andric  void *buf = 0;
5905ffd83dbSDimitry Andric  res = PyObject_GetBuffer($input, &view.buffer, PyBUF_WRITABLE);
591130d950cSDimitry Andric  if (res < 0) {
592130d950cSDimitry Andric    PyErr_Clear();
593130d950cSDimitry Andric    %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum);
594130d950cSDimitry Andric  }
5955ffd83dbSDimitry Andric  size = view.buffer.len;
5965ffd83dbSDimitry Andric  buf = view.buffer.buf;
597130d950cSDimitry Andric  $1 = ($1_ltype)buf;
598130d950cSDimitry Andric  $2 = ($2_ltype)(size / sizeof($*1_type));
599130d950cSDimitry Andric}
600130d950cSDimitry Andric%enddef
601130d950cSDimitry Andric
602130d950cSDimitry Andric%define %pybuffer_binary(TYPEMAP, SIZE)
6035ffd83dbSDimitry Andric%typemap(in) (TYPEMAP, SIZE) (Py_buffer_RAII view) {
6040eae32dcSDimitry Andric  int res;
6050eae32dcSDimitry Andric  Py_ssize_t size = 0;
6060eae32dcSDimitry Andric  const void *buf = 0;
6075ffd83dbSDimitry Andric  res = PyObject_GetBuffer($input, &view.buffer, PyBUF_CONTIG_RO);
608130d950cSDimitry Andric  if (res < 0) {
609130d950cSDimitry Andric    PyErr_Clear();
610130d950cSDimitry Andric    %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum);
611130d950cSDimitry Andric  }
6125ffd83dbSDimitry Andric  size = view.buffer.len;
6135ffd83dbSDimitry Andric  buf = view.buffer.buf;
614130d950cSDimitry Andric  $1 = ($1_ltype)buf;
615130d950cSDimitry Andric  $2 = ($2_ltype)(size / sizeof($*1_type));
616130d950cSDimitry Andric}
617130d950cSDimitry Andric%enddef
618130d950cSDimitry Andric
619130d950cSDimitry Andric%pybuffer_binary(const uint8_t *buf, size_t num_bytes);
620130d950cSDimitry Andric%pybuffer_mutable_binary(uint8_t *buf, size_t num_bytes);
62106c3fb27SDimitry Andric
62206c3fb27SDimitry Andric%typemap(in) (const char **symbol_name, uint32_t num_names) {
62306c3fb27SDimitry Andric  using namespace lldb_private;
62406c3fb27SDimitry Andric  /* Check if is a list  */
62506c3fb27SDimitry Andric  if (PythonList::Check($input)) {
62606c3fb27SDimitry Andric    PythonList list(PyRefType::Borrowed, $input);
62706c3fb27SDimitry Andric    $2 = list.GetSize();
62806c3fb27SDimitry Andric    int i = 0;
62906c3fb27SDimitry Andric    $1 = (char**)malloc(($2+1)*sizeof(char*));
63006c3fb27SDimitry Andric    for (i = 0; i < $2; i++) {
63106c3fb27SDimitry Andric      PythonString py_str = list.GetItemAtIndex(i).AsType<PythonString>();
63206c3fb27SDimitry Andric      if (!py_str.IsAllocated()) {
63306c3fb27SDimitry Andric        PyErr_SetString(PyExc_TypeError,"list must contain strings and blubby");
63406c3fb27SDimitry Andric        free($1);
63506c3fb27SDimitry Andric        return nullptr;
63606c3fb27SDimitry Andric      }
63706c3fb27SDimitry Andric
63806c3fb27SDimitry Andric      $1[i] = const_cast<char*>(py_str.GetString().data());
63906c3fb27SDimitry Andric    }
64006c3fb27SDimitry Andric    $1[i] = 0;
64106c3fb27SDimitry Andric  } else if ($input == Py_None) {
64206c3fb27SDimitry Andric    $1 =  NULL;
64306c3fb27SDimitry Andric  } else {
64406c3fb27SDimitry Andric    PyErr_SetString(PyExc_TypeError,"not a list");
64506c3fb27SDimitry Andric    return NULL;
64606c3fb27SDimitry Andric  }
64706c3fb27SDimitry Andric}
64806c3fb27SDimitry Andric
64906c3fb27SDimitry Andric// For lldb::SBPlatformLocateModuleCallback
65006c3fb27SDimitry Andric%typemap(in) (lldb::SBPlatformLocateModuleCallback callback,
65106c3fb27SDimitry Andric              void *callback_baton) {
65206c3fb27SDimitry Andric  if (!($input == Py_None ||
65306c3fb27SDimitry Andric        PyCallable_Check(reinterpret_cast<PyObject *>($input)))) {
65406c3fb27SDimitry Andric    PyErr_SetString(PyExc_TypeError, "Need a callable object or None!");
65506c3fb27SDimitry Andric    SWIG_fail;
65606c3fb27SDimitry Andric  }
65706c3fb27SDimitry Andric
65806c3fb27SDimitry Andric  if ($input == Py_None) {
65906c3fb27SDimitry Andric    $1 = nullptr;
66006c3fb27SDimitry Andric    $2 = nullptr;
66106c3fb27SDimitry Andric  } else {
66206c3fb27SDimitry Andric    PythonCallable callable = Retain<PythonCallable>($input);
66306c3fb27SDimitry Andric    if (!callable.IsValid()) {
66406c3fb27SDimitry Andric      PyErr_SetString(PyExc_TypeError, "Need a valid callable object");
66506c3fb27SDimitry Andric      SWIG_fail;
66606c3fb27SDimitry Andric    }
66706c3fb27SDimitry Andric
66806c3fb27SDimitry Andric    llvm::Expected<PythonCallable::ArgInfo> arg_info = callable.GetArgInfo();
66906c3fb27SDimitry Andric    if (!arg_info) {
67006c3fb27SDimitry Andric      PyErr_SetString(PyExc_TypeError,
67106c3fb27SDimitry Andric                      ("Could not get arguments: " +
67206c3fb27SDimitry Andric                          llvm::toString(arg_info.takeError())).c_str());
67306c3fb27SDimitry Andric      SWIG_fail;
67406c3fb27SDimitry Andric    }
67506c3fb27SDimitry Andric
67606c3fb27SDimitry Andric    if (arg_info.get().max_positional_args != 3) {
67706c3fb27SDimitry Andric      PyErr_SetString(PyExc_TypeError, "Expected 3 argument callable object");
67806c3fb27SDimitry Andric      SWIG_fail;
67906c3fb27SDimitry Andric    }
68006c3fb27SDimitry Andric
68106c3fb27SDimitry Andric    // NOTE: When this is called multiple times, this will leak the Python
68206c3fb27SDimitry Andric    // callable object as other callbacks, because this does not call Py_DECREF
68306c3fb27SDimitry Andric    // the object. But it should be almost zero impact since this method is
68406c3fb27SDimitry Andric    // expected to be called only once.
68506c3fb27SDimitry Andric
68606c3fb27SDimitry Andric    // Don't lose the callback reference
68706c3fb27SDimitry Andric    Py_INCREF($input);
68806c3fb27SDimitry Andric
68906c3fb27SDimitry Andric    $1 = LLDBSwigPythonCallLocateModuleCallback;
69006c3fb27SDimitry Andric    $2 = $input;
69106c3fb27SDimitry Andric  }
69206c3fb27SDimitry Andric}
69306c3fb27SDimitry Andric
69406c3fb27SDimitry Andric%typemap(typecheck) (lldb::SBPlatformLocateModuleCallback callback,
69506c3fb27SDimitry Andric                     void *callback_baton) {
69606c3fb27SDimitry Andric  $1 = $input == Py_None;
69706c3fb27SDimitry Andric  $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
69806c3fb27SDimitry Andric}
699