1%include <typemaps.i>
2
3// FIXME: We need to port more typemaps from Python
4
5//===----------------------------------------------------------------------===//
6
7// In Lua 5.3 and beyond the VM supports integers, so we need to remap
8// SWIG's internal handling of integers.
9
10
11%define LLDB_NUMBER_TYPEMAP(TYPE)
12
13// Primitive integer mapping
14%typemap(in,checkfn="lua_isinteger") TYPE
15%{ $1 = ($type)lua_tointeger(L, $input); %}
16%typemap(in,checkfn="lua_isinteger") const TYPE&($basetype temp)
17%{ temp=($basetype)lua_tointeger(L,$input); $1=&temp;%}
18%typemap(out) TYPE
19%{ lua_pushinteger(L, (lua_Integer) $1); SWIG_arg++;%}
20%typemap(out) const TYPE&
21%{ lua_pushinteger(L, (lua_Integer) $1); SWIG_arg++;%}
22
23// Pointer and reference mapping
24%typemap(in,checkfn="lua_isinteger") TYPE *INPUT($*ltype temp), TYPE &INPUT($*ltype temp)
25%{ temp = ($*ltype)lua_tointeger(L,$input);
26   $1 = &temp; %}
27%typemap(in, numinputs=0) TYPE *OUTPUT ($*ltype temp)
28%{ $1 = &temp; %}
29%typemap(argout) TYPE *OUTPUT
30%{  lua_pushinteger(L, (lua_Integer) *$1); SWIG_arg++;%}
31%typemap(in) TYPE *INOUT = TYPE *INPUT;
32%typemap(argout) TYPE *INOUT = TYPE *OUTPUT;
33%typemap(in) TYPE &OUTPUT = TYPE *OUTPUT;
34%typemap(argout) TYPE &OUTPUT = TYPE *OUTPUT;
35%typemap(in) TYPE &INOUT = TYPE *INPUT;
36%typemap(argout) TYPE &INOUT = TYPE *OUTPUT;
37%typemap(in,checkfn="lua_isinteger") const TYPE *INPUT($*ltype temp)
38%{ temp = ($*ltype)lua_tointeger(L,$input);
39   $1 = &temp; %}
40
41%enddef // LLDB_NUMBER_TYPEMAP
42
43LLDB_NUMBER_TYPEMAP(unsigned char);
44LLDB_NUMBER_TYPEMAP(signed char);
45LLDB_NUMBER_TYPEMAP(short);
46LLDB_NUMBER_TYPEMAP(unsigned short);
47LLDB_NUMBER_TYPEMAP(signed short);
48LLDB_NUMBER_TYPEMAP(int);
49LLDB_NUMBER_TYPEMAP(unsigned int);
50LLDB_NUMBER_TYPEMAP(signed int);
51LLDB_NUMBER_TYPEMAP(long);
52LLDB_NUMBER_TYPEMAP(unsigned long);
53LLDB_NUMBER_TYPEMAP(signed long);
54LLDB_NUMBER_TYPEMAP(long long);
55LLDB_NUMBER_TYPEMAP(unsigned long long);
56LLDB_NUMBER_TYPEMAP(signed long long);
57LLDB_NUMBER_TYPEMAP(enum SWIGTYPE);
58
59%apply unsigned long { size_t };
60%apply const unsigned long & { const size_t & };
61%apply long { ssize_t };
62%apply const long & { const ssize_t & };
63
64//===----------------------------------------------------------------------===//
65
66// FIXME:
67//  Ideally all the typemaps should be revisited in a future SB API revision.
68//  Typemaps, usually, modifies the function signatures and might spawn
69//  different LLDB APIs across languages (C++, Python, Lua...).
70//  Historically, typemaps have been used to replace SWIG's deficiencies,
71//  but SWIG itself evolved and some API design choices are now redundant.
72
73//===----------------------------------------------------------------------===//
74
75// Typemap definitions to allow SWIG to properly handle char buffer.
76
77// typemap for a char buffer
78%typemap(in) (char *dst, size_t dst_len) {
79  $2 = luaL_checkinteger(L, $input);
80  if ($2 <= 0) {
81    return luaL_error(L, "Positive integer expected");
82  }
83  $1 = (char *)malloc($2);
84}
85
86// SBProcess::ReadCStringFromMemory() uses a void*, but needs to be treated
87// as char data instead of byte data.
88%typemap(in) (void *char_buf, size_t size) = (char *dst, size_t dst_len);
89
90// Also SBProcess::ReadMemory.
91%typemap(in) (void *buf, size_t size) = (char *dst, size_t dst_len);
92
93// Return the char buffer.  Discarding any previous return result
94%typemap(argout) (char *dst, size_t dst_len) {
95  lua_pop(L, 1); // Blow away the previous result
96  if ($result == 0) {
97    lua_pushliteral(L, "");
98  } else {
99    lua_pushlstring(L, (const char *)$1, $result);
100  }
101  free($1);
102  // SWIG_arg was already incremented
103}
104
105// SBProcess::ReadCStringFromMemory() uses a void*, but needs to be treated
106// as char data instead of byte data.
107%typemap(argout) (void *char_buf, size_t size) = (char *dst, size_t dst_len);
108
109// Also SBProcess::ReadMemory.
110%typemap(argout) (void *buf, size_t size) = (char *dst, size_t dst_len);
111
112//===----------------------------------------------------------------------===//
113
114// Typemap for handling a snprintf-like API like SBThread::GetStopDescription.
115
116%typemap(in) (char *dst_or_null, size_t dst_len) {
117  $2 = luaL_checkinteger(L, $input);
118  if ($2 <= 0) {
119    return luaL_error(L, "Positive integer expected");
120  }
121  $1 = (char *)malloc($2);
122}
123
124%typemap(argout) (char *dst_or_null, size_t dst_len) {
125  lua_pop(L, 1); // Blow away the previous result
126  lua_pushlstring(L, (const char *)$1, $result);
127  free($1);
128  // SWIG_arg was already incremented
129}
130
131//===----------------------------------------------------------------------===//
132
133// Typemap for handling SBModule::GetVersion
134
135%typemap(in) (uint32_t *versions, uint32_t num_versions) {
136  $2 = 99;
137  $1 = (uint32_t *)malloc(sizeof(uint32_t) * $2);
138}
139
140%typemap(argout) (uint32_t *versions, uint32_t num_versions) {
141  uint32_t count = result;
142  if (count >= $2)
143    count = $2;
144  lua_newtable(L);
145  int i = 0;
146  while (i++ < count) {
147    lua_pushinteger(L, $1[i - 1]);
148    lua_seti(L, -2, i);
149  }
150  SWIG_arg++;
151  free($1);
152}
153
154//===----------------------------------------------------------------------===//
155
156// Typemap for handling SBDebugger::SetLoggingCallback
157
158%typemap(in) (lldb::LogOutputCallback log_callback, void *baton) {
159  $1 = LLDBSwigLuaCallLuaLogOutputCallback;
160  $2 = (void *)L;
161
162  luaL_checktype(L, 2, LUA_TFUNCTION);
163  lua_settop(L, 2);
164
165  lua_pushlightuserdata(L, (void *)&LLDBSwigLuaCallLuaLogOutputCallback);
166  lua_insert(L, 2);
167  lua_settable(L, LUA_REGISTRYINDEX);
168}
169
170//===----------------------------------------------------------------------===//
171
172// Typemap for handling SBEvent::SBEvent(uint32_t event, const char *cstr, uint32_t cstr_len)
173
174%typemap(in) (const char *cstr, uint32_t cstr_len) {
175  $1 = (char *)luaL_checklstring(L, $input, (size_t *)&$2);
176}
177
178// Typemap for handling SBProcess::PutSTDIN
179
180%typemap(in) (const char *src, size_t src_len) {
181  $1 = (char *)luaL_checklstring(L, $input, &$2);
182}
183
184// Typemap for handling SBProcess::WriteMemory, SBTarget::GetInstructions...
185
186%typemap(in) (const void *buf, size_t size),
187             (const void *data, size_t data_len) {
188  $1 = (void *)luaL_checklstring(L, $input, &$2);
189}
190
191//===----------------------------------------------------------------------===//
192
193// Typemap for handling char ** in SBTarget::LaunchSimple, SBTarget::Launch...
194
195// It should accept a Lua table of strings, for stuff like "argv" and "envp".
196
197%typemap(in) char ** {
198  if (lua_istable(L, $input)) {
199    size_t size = lua_rawlen(L, $input);
200    $1 = (char **)malloc((size + 1) * sizeof(char *));
201    int i = 0, j = 0;
202    while (i++ < size) {
203      lua_rawgeti(L, $input, i);
204      if (!lua_isstring(L, -1)) {
205        // if current element cannot be converted to string, raise an error
206        lua_pop(L, 1);
207        return luaL_error(L, "List should only contain strings");
208      }
209      $1[j++] = (char *)lua_tostring(L, -1);
210      lua_pop(L, 1);
211    }
212    $1[j] = 0;
213  } else if (lua_isnil(L, $input)) {
214    // "nil" is also acceptable, equivalent as an empty table
215    $1 = NULL;
216  } else {
217    return luaL_error(L, "A list of strings expected");
218  }
219}
220
221%typemap(freearg) char ** {
222  free((char *) $1);
223}
224
225%typecheck(SWIG_TYPECHECK_STRING_ARRAY) char ** {
226  $1 = (lua_istable(L, $input) || lua_isnil(L, $input));
227}
228
229//===----------------------------------------------------------------------===//
230
231// Typemap for file handles (e.g. used in SBDebugger::SetOutputFile)
232
233%typemap(in) lldb::FileSP {
234  luaL_Stream *p = (luaL_Stream *)luaL_checkudata(L, $input, LUA_FILEHANDLE);
235  lldb::FileSP file_sp;
236  file_sp = std::make_shared<lldb_private::NativeFile>(p->f, false);
237  if (!file_sp->IsValid())
238    return luaL_error(L, "Invalid file");
239  $1 = file_sp;
240}
241
242%typecheck(SWIG_TYPECHECK_POINTER) lldb::FileSP {
243  $1 = (lua_isuserdata(L, $input)) &&
244       (luaL_testudata(L, $input, LUA_FILEHANDLE) != nullptr);
245}
246
247// Typemap for file handles (e.g. used in SBDebugger::GetOutputFileHandle)
248
249%typemap(out) lldb::FileSP {
250  lldb::FileSP sp = $1;
251  if (sp && sp->IsValid()) {
252    luaL_Stream *p = (luaL_Stream *)lua_newuserdata(L, sizeof(luaL_Stream));
253    p->closef = &LLDBSwigLuaCloseFileHandle;
254    p->f = sp->GetStream();
255    luaL_setmetatable(L, LUA_FILEHANDLE);
256    SWIG_arg++;
257  }
258}
259
260//===----------------------------------------------------------------------===//
261
262// Typemap for SBData::CreateDataFromUInt64Array, SBData::SetDataFromUInt64Array ...
263
264%typemap(in) (uint64_t* array, size_t array_len),
265             (uint32_t* array, size_t array_len),
266             (int64_t* array, size_t array_len),
267             (int32_t* array, size_t array_len),
268             (double* array, size_t array_len) {
269  if (lua_istable(L, $input)) {
270    // It should accept a table of numbers.
271    $2 = lua_rawlen(L, $input);
272    $1 = ($1_ltype)malloc(($2) * sizeof($*1_type));
273    int i = 0, j = 0;
274    while (i++ < $2) {
275      lua_rawgeti(L, $input, i);
276      if (!lua_isnumber(L, -1)) {
277        // if current element cannot be converted to number, raise an error
278        lua_pop(L, 1);
279        return luaL_error(L, "List should only contain numbers");
280      }
281      $1[j++] = ($*1_ltype) lua_tonumber(L, -1);
282      lua_pop(L, 1);
283    }
284  } else if (lua_isnil(L, $input)) {
285    // "nil" is also acceptable, equivalent as an empty table
286    $1 = NULL;
287    $2 = 0;
288  } else {
289    // else raise an error
290    return luaL_error(L, "A list of numbers expected.");
291  }
292}
293
294%typemap(freearg) (uint64_t* array, size_t array_len),
295             (uint32_t* array, size_t array_len),
296             (int64_t* array, size_t array_len),
297             (int32_t* array, size_t array_len),
298             (double* array, size_t array_len) {
299  free($1);
300}
301
302//===----------------------------------------------------------------------===//
303
304// Typemap for SBCommandReturnObject::PutCString
305
306%typemap(in) (const char *string, int len) {
307  if (lua_isnil(L, $input)) {
308    $1 = NULL;
309    $2 = 0;
310  } else {
311    $1 = (char *)luaL_checklstring(L, $input, (size_t *)&$2);
312  }
313}
314
315//===----------------------------------------------------------------------===//
316