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