Mercurial > vba-clojure
diff src/lua/ldblib.c @ 11:27763b933818
raise lua sources up one level
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 11:07:39 -0600 |
parents | src/lua/src/ldblib.c@f9f4f1b99eed |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/lua/ldblib.c Sat Mar 03 11:07:39 2012 -0600 1.3 @@ -0,0 +1,397 @@ 1.4 +/* 1.5 +** $Id: ldblib.c,v 1.104.1.3 2008/01/21 13:11:21 roberto Exp $ 1.6 +** Interface from Lua to its debug API 1.7 +** See Copyright Notice in lua.h 1.8 +*/ 1.9 + 1.10 + 1.11 +#include <stdio.h> 1.12 +#include <stdlib.h> 1.13 +#include <string.h> 1.14 + 1.15 +#define ldblib_c 1.16 +#define LUA_LIB 1.17 + 1.18 +#include "lua.h" 1.19 + 1.20 +#include "lauxlib.h" 1.21 +#include "lualib.h" 1.22 + 1.23 + 1.24 + 1.25 +static int db_getregistry (lua_State *L) { 1.26 + lua_pushvalue(L, LUA_REGISTRYINDEX); 1.27 + return 1; 1.28 +} 1.29 + 1.30 + 1.31 +static int db_getmetatable (lua_State *L) { 1.32 + luaL_checkany(L, 1); 1.33 + if (!lua_getmetatable(L, 1)) { 1.34 + lua_pushnil(L); /* no metatable */ 1.35 + } 1.36 + return 1; 1.37 +} 1.38 + 1.39 + 1.40 +static int db_setmetatable (lua_State *L) { 1.41 + int t = lua_type(L, 2); 1.42 + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, 1.43 + "nil or table expected"); 1.44 + lua_settop(L, 2); 1.45 + lua_pushboolean(L, lua_setmetatable(L, 1)); 1.46 + return 1; 1.47 +} 1.48 + 1.49 + 1.50 +static int db_getfenv (lua_State *L) { 1.51 + lua_getfenv(L, 1); 1.52 + return 1; 1.53 +} 1.54 + 1.55 + 1.56 +static int db_setfenv (lua_State *L) { 1.57 + luaL_checktype(L, 2, LUA_TTABLE); 1.58 + lua_settop(L, 2); 1.59 + if (lua_setfenv(L, 1) == 0) 1.60 + luaL_error(L, LUA_QL("setfenv") 1.61 + " cannot change environment of given object"); 1.62 + return 1; 1.63 +} 1.64 + 1.65 + 1.66 +static void settabss (lua_State *L, const char *i, const char *v) { 1.67 + lua_pushstring(L, v); 1.68 + lua_setfield(L, -2, i); 1.69 +} 1.70 + 1.71 + 1.72 +static void settabsi (lua_State *L, const char *i, int v) { 1.73 + lua_pushinteger(L, v); 1.74 + lua_setfield(L, -2, i); 1.75 +} 1.76 + 1.77 + 1.78 +static lua_State *getthread (lua_State *L, int *arg) { 1.79 + if (lua_isthread(L, 1)) { 1.80 + *arg = 1; 1.81 + return lua_tothread(L, 1); 1.82 + } 1.83 + else { 1.84 + *arg = 0; 1.85 + return L; 1.86 + } 1.87 +} 1.88 + 1.89 + 1.90 +static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { 1.91 + if (L == L1) { 1.92 + lua_pushvalue(L, -2); 1.93 + lua_remove(L, -3); 1.94 + } 1.95 + else 1.96 + lua_xmove(L1, L, 1); 1.97 + lua_setfield(L, -2, fname); 1.98 +} 1.99 + 1.100 + 1.101 +static int db_getinfo (lua_State *L) { 1.102 + lua_Debug ar; 1.103 + int arg; 1.104 + lua_State *L1 = getthread(L, &arg); 1.105 + const char *options = luaL_optstring(L, arg+2, "flnSu"); 1.106 + if (lua_isnumber(L, arg+1)) { 1.107 + if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) { 1.108 + lua_pushnil(L); /* level out of range */ 1.109 + return 1; 1.110 + } 1.111 + } 1.112 + else if (lua_isfunction(L, arg+1)) { 1.113 + lua_pushfstring(L, ">%s", options); 1.114 + options = lua_tostring(L, -1); 1.115 + lua_pushvalue(L, arg+1); 1.116 + lua_xmove(L, L1, 1); 1.117 + } 1.118 + else 1.119 + return luaL_argerror(L, arg+1, "function or level expected"); 1.120 + if (!lua_getinfo(L1, options, &ar)) 1.121 + return luaL_argerror(L, arg+2, "invalid option"); 1.122 + lua_createtable(L, 0, 2); 1.123 + if (strchr(options, 'S')) { 1.124 + settabss(L, "source", ar.source); 1.125 + settabss(L, "short_src", ar.short_src); 1.126 + settabsi(L, "linedefined", ar.linedefined); 1.127 + settabsi(L, "lastlinedefined", ar.lastlinedefined); 1.128 + settabss(L, "what", ar.what); 1.129 + } 1.130 + if (strchr(options, 'l')) 1.131 + settabsi(L, "currentline", ar.currentline); 1.132 + if (strchr(options, 'u')) 1.133 + settabsi(L, "nups", ar.nups); 1.134 + if (strchr(options, 'n')) { 1.135 + settabss(L, "name", ar.name); 1.136 + settabss(L, "namewhat", ar.namewhat); 1.137 + } 1.138 + if (strchr(options, 'L')) 1.139 + treatstackoption(L, L1, "activelines"); 1.140 + if (strchr(options, 'f')) 1.141 + treatstackoption(L, L1, "func"); 1.142 + return 1; /* return table */ 1.143 +} 1.144 + 1.145 + 1.146 +static int db_getlocal (lua_State *L) { 1.147 + int arg; 1.148 + lua_State *L1 = getthread(L, &arg); 1.149 + lua_Debug ar; 1.150 + const char *name; 1.151 + if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ 1.152 + return luaL_argerror(L, arg+1, "level out of range"); 1.153 + name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2)); 1.154 + if (name) { 1.155 + lua_xmove(L1, L, 1); 1.156 + lua_pushstring(L, name); 1.157 + lua_pushvalue(L, -2); 1.158 + return 2; 1.159 + } 1.160 + else { 1.161 + lua_pushnil(L); 1.162 + return 1; 1.163 + } 1.164 +} 1.165 + 1.166 + 1.167 +static int db_setlocal (lua_State *L) { 1.168 + int arg; 1.169 + lua_State *L1 = getthread(L, &arg); 1.170 + lua_Debug ar; 1.171 + if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ 1.172 + return luaL_argerror(L, arg+1, "level out of range"); 1.173 + luaL_checkany(L, arg+3); 1.174 + lua_settop(L, arg+3); 1.175 + lua_xmove(L, L1, 1); 1.176 + lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2))); 1.177 + return 1; 1.178 +} 1.179 + 1.180 + 1.181 +static int auxupvalue (lua_State *L, int get) { 1.182 + const char *name; 1.183 + int n = luaL_checkint(L, 2); 1.184 + luaL_checktype(L, 1, LUA_TFUNCTION); 1.185 + if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */ 1.186 + name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); 1.187 + if (name == NULL) return 0; 1.188 + lua_pushstring(L, name); 1.189 + lua_insert(L, -(get+1)); 1.190 + return get + 1; 1.191 +} 1.192 + 1.193 + 1.194 +static int db_getupvalue (lua_State *L) { 1.195 + return auxupvalue(L, 1); 1.196 +} 1.197 + 1.198 + 1.199 +static int db_setupvalue (lua_State *L) { 1.200 + luaL_checkany(L, 3); 1.201 + return auxupvalue(L, 0); 1.202 +} 1.203 + 1.204 + 1.205 + 1.206 +static const char KEY_HOOK = 'h'; 1.207 + 1.208 + 1.209 +static void hookf (lua_State *L, lua_Debug *ar) { 1.210 + static const char *const hooknames[] = 1.211 + {"call", "return", "line", "count", "tail return"}; 1.212 + lua_pushlightuserdata(L, (void *)&KEY_HOOK); 1.213 + lua_rawget(L, LUA_REGISTRYINDEX); 1.214 + lua_pushlightuserdata(L, L); 1.215 + lua_rawget(L, -2); 1.216 + if (lua_isfunction(L, -1)) { 1.217 + lua_pushstring(L, hooknames[(int)ar->event]); 1.218 + if (ar->currentline >= 0) 1.219 + lua_pushinteger(L, ar->currentline); 1.220 + else lua_pushnil(L); 1.221 + lua_assert(lua_getinfo(L, "lS", ar)); 1.222 + lua_call(L, 2, 0); 1.223 + } 1.224 +} 1.225 + 1.226 + 1.227 +static int makemask (const char *smask, int count) { 1.228 + int mask = 0; 1.229 + if (strchr(smask, 'c')) mask |= LUA_MASKCALL; 1.230 + if (strchr(smask, 'r')) mask |= LUA_MASKRET; 1.231 + if (strchr(smask, 'l')) mask |= LUA_MASKLINE; 1.232 + if (count > 0) mask |= LUA_MASKCOUNT; 1.233 + return mask; 1.234 +} 1.235 + 1.236 + 1.237 +static char *unmakemask (int mask, char *smask) { 1.238 + int i = 0; 1.239 + if (mask & LUA_MASKCALL) smask[i++] = 'c'; 1.240 + if (mask & LUA_MASKRET) smask[i++] = 'r'; 1.241 + if (mask & LUA_MASKLINE) smask[i++] = 'l'; 1.242 + smask[i] = '\0'; 1.243 + return smask; 1.244 +} 1.245 + 1.246 + 1.247 +static void gethooktable (lua_State *L) { 1.248 + lua_pushlightuserdata(L, (void *)&KEY_HOOK); 1.249 + lua_rawget(L, LUA_REGISTRYINDEX); 1.250 + if (!lua_istable(L, -1)) { 1.251 + lua_pop(L, 1); 1.252 + lua_createtable(L, 0, 1); 1.253 + lua_pushlightuserdata(L, (void *)&KEY_HOOK); 1.254 + lua_pushvalue(L, -2); 1.255 + lua_rawset(L, LUA_REGISTRYINDEX); 1.256 + } 1.257 +} 1.258 + 1.259 + 1.260 +static int db_sethook (lua_State *L) { 1.261 + int arg, mask, count; 1.262 + lua_Hook func; 1.263 + lua_State *L1 = getthread(L, &arg); 1.264 + if (lua_isnoneornil(L, arg+1)) { 1.265 + lua_settop(L, arg+1); 1.266 + func = NULL; mask = 0; count = 0; /* turn off hooks */ 1.267 + } 1.268 + else { 1.269 + const char *smask = luaL_checkstring(L, arg+2); 1.270 + luaL_checktype(L, arg+1, LUA_TFUNCTION); 1.271 + count = luaL_optint(L, arg+3, 0); 1.272 + func = hookf; mask = makemask(smask, count); 1.273 + } 1.274 + gethooktable(L); 1.275 + lua_pushlightuserdata(L, L1); 1.276 + lua_pushvalue(L, arg+1); 1.277 + lua_rawset(L, -3); /* set new hook */ 1.278 + lua_pop(L, 1); /* remove hook table */ 1.279 + lua_sethook(L1, func, mask, count); /* set hooks */ 1.280 + return 0; 1.281 +} 1.282 + 1.283 + 1.284 +static int db_gethook (lua_State *L) { 1.285 + int arg; 1.286 + lua_State *L1 = getthread(L, &arg); 1.287 + char buff[5]; 1.288 + int mask = lua_gethookmask(L1); 1.289 + lua_Hook hook = lua_gethook(L1); 1.290 + if (hook != NULL && hook != hookf) /* external hook? */ 1.291 + lua_pushliteral(L, "external hook"); 1.292 + else { 1.293 + gethooktable(L); 1.294 + lua_pushlightuserdata(L, L1); 1.295 + lua_rawget(L, -2); /* get hook */ 1.296 + lua_remove(L, -2); /* remove hook table */ 1.297 + } 1.298 + lua_pushstring(L, unmakemask(mask, buff)); 1.299 + lua_pushinteger(L, lua_gethookcount(L1)); 1.300 + return 3; 1.301 +} 1.302 + 1.303 + 1.304 +static int db_debug (lua_State *L) { 1.305 + for (;;) { 1.306 + char buffer[250]; 1.307 + fputs("lua_debug> ", stderr); 1.308 + if (fgets(buffer, sizeof(buffer), stdin) == 0 || 1.309 + strcmp(buffer, "cont\n") == 0) 1.310 + return 0; 1.311 + if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || 1.312 + lua_pcall(L, 0, 0, 0)) { 1.313 + fputs(lua_tostring(L, -1), stderr); 1.314 + fputs("\n", stderr); 1.315 + } 1.316 + lua_settop(L, 0); /* remove eventual returns */ 1.317 + } 1.318 +} 1.319 + 1.320 + 1.321 +#define LEVELS1 12 /* size of the first part of the stack */ 1.322 +#define LEVELS2 10 /* size of the second part of the stack */ 1.323 + 1.324 +static int db_errorfb (lua_State *L) { 1.325 + int level; 1.326 + int firstpart = 1; /* still before eventual `...' */ 1.327 + int arg; 1.328 + lua_State *L1 = getthread(L, &arg); 1.329 + lua_Debug ar; 1.330 + if (lua_isnumber(L, arg+2)) { 1.331 + level = (int)lua_tointeger(L, arg+2); 1.332 + lua_pop(L, 1); 1.333 + } 1.334 + else 1.335 + level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ 1.336 + if (lua_gettop(L) == arg) 1.337 + lua_pushliteral(L, ""); 1.338 + else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */ 1.339 + else lua_pushliteral(L, "\n"); 1.340 + lua_pushliteral(L, "stack traceback:"); 1.341 + while (lua_getstack(L1, level++, &ar)) { 1.342 + if (level > LEVELS1 && firstpart) { 1.343 + /* no more than `LEVELS2' more levels? */ 1.344 + if (!lua_getstack(L1, level+LEVELS2, &ar)) 1.345 + level--; /* keep going */ 1.346 + else { 1.347 + lua_pushliteral(L, "\n\t..."); /* too many levels */ 1.348 + while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */ 1.349 + level++; 1.350 + } 1.351 + firstpart = 0; 1.352 + continue; 1.353 + } 1.354 + lua_pushliteral(L, "\n\t"); 1.355 + lua_getinfo(L1, "Snl", &ar); 1.356 + lua_pushfstring(L, "%s:", ar.short_src); 1.357 + if (ar.currentline > 0) 1.358 + lua_pushfstring(L, "%d:", ar.currentline); 1.359 + if (*ar.namewhat != '\0') /* is there a name? */ 1.360 + lua_pushfstring(L, " in function " LUA_QS, ar.name); 1.361 + else { 1.362 + if (*ar.what == 'm') /* main? */ 1.363 + lua_pushfstring(L, " in main chunk"); 1.364 + else if (*ar.what == 'C' || *ar.what == 't') 1.365 + lua_pushliteral(L, " ?"); /* C function or tail call */ 1.366 + else 1.367 + lua_pushfstring(L, " in function <%s:%d>", 1.368 + ar.short_src, ar.linedefined); 1.369 + } 1.370 + lua_concat(L, lua_gettop(L) - arg); 1.371 + } 1.372 + lua_concat(L, lua_gettop(L) - arg); 1.373 + return 1; 1.374 +} 1.375 + 1.376 + 1.377 +static const luaL_Reg dblib[] = { 1.378 + {"debug", db_debug}, 1.379 + {"getfenv", db_getfenv}, 1.380 + {"gethook", db_gethook}, 1.381 + {"getinfo", db_getinfo}, 1.382 + {"getlocal", db_getlocal}, 1.383 + {"getregistry", db_getregistry}, 1.384 + {"getmetatable", db_getmetatable}, 1.385 + {"getupvalue", db_getupvalue}, 1.386 + {"setfenv", db_setfenv}, 1.387 + {"sethook", db_sethook}, 1.388 + {"setlocal", db_setlocal}, 1.389 + {"setmetatable", db_setmetatable}, 1.390 + {"setupvalue", db_setupvalue}, 1.391 + {"traceback", db_errorfb}, 1.392 + {NULL, NULL} 1.393 +}; 1.394 + 1.395 + 1.396 +LUALIB_API int luaopen_debug (lua_State *L) { 1.397 + luaL_register(L, LUA_DBLIBNAME, dblib); 1.398 + return 1; 1.399 +} 1.400 +