aboutsummaryrefslogtreecommitdiff
path: root/ldblib.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-05-15 16:27:33 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-05-15 16:27:33 -0300
commit6a5d87771fa28c8337c5e10f4a0c4364dbeb37e9 (patch)
tree1aa6d6dd52e68d6adb9c78660095191ce6e9b808 /ldblib.c
parent15e8405731c18f96e926e66dbd692fcefbb724ab (diff)
downloadlua-6a5d87771fa28c8337c5e10f4a0c4364dbeb37e9.tar.gz
lua-6a5d87771fa28c8337c5e10f4a0c4364dbeb37e9.tar.bz2
lua-6a5d87771fa28c8337c5e10f4a0c4364dbeb37e9.zip
added lots of new comments + small changes in code
Diffstat (limited to 'ldblib.c')
-rw-r--r--ldblib.c155
1 files changed, 94 insertions, 61 deletions
diff --git a/ldblib.c b/ldblib.c
index 2e0a866b..7a9f3fbb 100644
--- a/ldblib.c
+++ b/ldblib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldblib.c,v 1.137 2014/03/12 20:57:40 roberto Exp roberto $ 2** $Id: ldblib.c,v 1.138 2014/04/30 18:59:15 roberto Exp roberto $
3** Interface from Lua to its debug API 3** Interface from Lua to its debug API
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -28,7 +28,7 @@ static int db_Csize (lua_State *L) {
28 } sizes[] = { 28 } sizes[] = {
29 {'I', sizeof(lua_Integer)}, 29 {'I', sizeof(lua_Integer)},
30 {'F', sizeof(lua_Number)}, 30 {'F', sizeof(lua_Number)},
31 {'b', CHAR_BIT}, 31 {'b', CHAR_BIT}, /* here is number of bits (not bytes) */
32 {'h', sizeof(short)}, 32 {'h', sizeof(short)},
33 {'i', sizeof(int)}, 33 {'i', sizeof(int)},
34 {'l', sizeof(long)}, 34 {'l', sizeof(long)},
@@ -91,24 +91,12 @@ static int db_setuservalue (lua_State *L) {
91} 91}
92 92
93 93
94static void settabss (lua_State *L, const char *i, const char *v) { 94/*
95 lua_pushstring(L, v); 95** Auxiliary function used by several library functions: check for
96 lua_setfield(L, -2, i); 96** an optional thread as function's first argument and set 'arg' with
97} 97** 1 if this argument is present (so that functions can skip it to
98 98** access their other arguments)
99 99*/
100static void settabsi (lua_State *L, const char *i, int v) {
101 lua_pushinteger(L, v);
102 lua_setfield(L, -2, i);
103}
104
105
106static void settabsb (lua_State *L, const char *i, int v) {
107 lua_pushboolean(L, v);
108 lua_setfield(L, -2, i);
109}
110
111
112static lua_State *getthread (lua_State *L, int *arg) { 100static lua_State *getthread (lua_State *L, int *arg) {
113 if (lua_isthread(L, 1)) { 101 if (lua_isthread(L, 1)) {
114 *arg = 1; 102 *arg = 1;
@@ -116,44 +104,70 @@ static lua_State *getthread (lua_State *L, int *arg) {
116 } 104 }
117 else { 105 else {
118 *arg = 0; 106 *arg = 0;
119 return L; 107 return L; /* function will operate over current thread */
120 } 108 }
121} 109}
122 110
123 111
112/*
113** Variations of 'lua_settable', used by 'db_getinfo' to put results
114** from 'lua_getinfo' into result table. Key is always a string;
115** value can be a string, an int, or a boolean.
116*/
117static void settabss (lua_State *L, const char *k, const char *v) {
118 lua_pushstring(L, v);
119 lua_setfield(L, -2, k);
120}
121
122static void settabsi (lua_State *L, const char *k, int v) {
123 lua_pushinteger(L, v);
124 lua_setfield(L, -2, k);
125}
126
127static void settabsb (lua_State *L, const char *k, int v) {
128 lua_pushboolean(L, v);
129 lua_setfield(L, -2, k);
130}
131
132
133/*
134** In function 'db_getinfo', the call to 'lua_getinfo' may push
135** results on the stack; later it creates the result table to put
136** these objects. Function 'treatstackoption' puts the result from
137** 'lua_getinfo' on top of the result table so that it can call
138** 'lua_setfield'.
139*/
124static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { 140static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
125 if (L == L1) { 141 if (L == L1)
126 lua_pushvalue(L, -2); 142 lua_rotate(L, -2, 1); /* exchange object and table */
127 lua_remove(L, -3);
128 }
129 else 143 else
130 lua_xmove(L1, L, 1); 144 lua_xmove(L1, L, 1); /* move object to the "main" stack */
131 lua_setfield(L, -2, fname); 145 lua_setfield(L, -2, fname); /* put object into table */
132} 146}
133 147
134 148
149/*
150** Calls 'lua_getinfo' and collects all results in a new table.
151*/
135static int db_getinfo (lua_State *L) { 152static int db_getinfo (lua_State *L) {
136 lua_Debug ar; 153 lua_Debug ar;
137 int arg; 154 int arg;
138 lua_State *L1 = getthread(L, &arg); 155 lua_State *L1 = getthread(L, &arg);
139 const char *options = luaL_optstring(L, arg+2, "flnStu"); 156 const char *options = luaL_optstring(L, arg+2, "flnStu");
140 if (lua_isnumber(L, arg+1)) { 157 if (lua_isfunction(L, arg + 1)) { /* info about a function? */
141 if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) { 158 options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */
159 lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */
160 lua_xmove(L, L1, 1);
161 }
162 else { /* stack level */
163 if (!lua_getstack(L1, luaL_checkint(L, arg + 1), &ar)) {
142 lua_pushnil(L); /* level out of range */ 164 lua_pushnil(L); /* level out of range */
143 return 1; 165 return 1;
144 } 166 }
145 } 167 }
146 else if (lua_isfunction(L, arg+1)) {
147 lua_pushfstring(L, ">%s", options);
148 options = lua_tostring(L, -1);
149 lua_pushvalue(L, arg+1);
150 lua_xmove(L, L1, 1);
151 }
152 else
153 return luaL_argerror(L, arg+1, "function or level expected");
154 if (!lua_getinfo(L1, options, &ar)) 168 if (!lua_getinfo(L1, options, &ar))
155 return luaL_argerror(L, arg+2, "invalid option"); 169 return luaL_argerror(L, arg+2, "invalid option");
156 lua_createtable(L, 0, 2); 170 lua_newtable(L); /* table to collect results */
157 if (strchr(options, 'S')) { 171 if (strchr(options, 'S')) {
158 settabss(L, "source", ar.source); 172 settabss(L, "source", ar.source);
159 settabss(L, "short_src", ar.short_src); 173 settabss(L, "short_src", ar.short_src);
@@ -191,16 +205,16 @@ static int db_getlocal (lua_State *L) {
191 if (lua_isfunction(L, arg + 1)) { /* function argument? */ 205 if (lua_isfunction(L, arg + 1)) { /* function argument? */
192 lua_pushvalue(L, arg + 1); /* push function */ 206 lua_pushvalue(L, arg + 1); /* push function */
193 lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */ 207 lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */
194 return 1; 208 return 1; /* return only name (there is no value) */
195 } 209 }
196 else { /* stack-level argument */ 210 else { /* stack-level argument */
197 if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ 211 if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
198 return luaL_argerror(L, arg+1, "level out of range"); 212 return luaL_argerror(L, arg+1, "level out of range");
199 name = lua_getlocal(L1, &ar, nvar); 213 name = lua_getlocal(L1, &ar, nvar);
200 if (name) { 214 if (name) {
201 lua_xmove(L1, L, 1); /* push local value */ 215 lua_xmove(L1, L, 1); /* move local value */
202 lua_pushstring(L, name); /* push name */ 216 lua_pushstring(L, name); /* push name */
203 lua_pushvalue(L, -2); /* re-order */ 217 lua_rotate(L, -2, 1); /* re-order */
204 return 2; 218 return 2;
205 } 219 }
206 else { 220 else {
@@ -225,14 +239,17 @@ static int db_setlocal (lua_State *L) {
225} 239}
226 240
227 241
242/*
243** get (if 'get' is true) or set an upvalue from a closure
244*/
228static int auxupvalue (lua_State *L, int get) { 245static int auxupvalue (lua_State *L, int get) {
229 const char *name; 246 const char *name;
230 int n = luaL_checkint(L, 2); 247 int n = luaL_checkint(L, 2); /* upvalue index */
231 luaL_checktype(L, 1, LUA_TFUNCTION); 248 luaL_checktype(L, 1, LUA_TFUNCTION); /* closure */
232 name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); 249 name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
233 if (name == NULL) return 0; 250 if (name == NULL) return 0;
234 lua_pushstring(L, name); 251 lua_pushstring(L, name);
235 lua_insert(L, -(get+1)); 252 lua_insert(L, -(get+1)); /* no-op if get is false */
236 return get + 1; 253 return get + 1;
237} 254}
238 255
@@ -248,13 +265,15 @@ static int db_setupvalue (lua_State *L) {
248} 265}
249 266
250 267
268/*
269** Check whether a given upvalue from a given closure exists and
270** returns its index
271*/
251static int checkupval (lua_State *L, int argf, int argnup) { 272static int checkupval (lua_State *L, int argf, int argnup) {
252 lua_Debug ar; 273 int nup = luaL_checkint(L, argnup); /* upvalue index */
253 int nup = luaL_checkint(L, argnup); 274 luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */
254 luaL_checktype(L, argf, LUA_TFUNCTION); 275 luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup,
255 lua_pushvalue(L, argf); 276 "invalid upvalue index");
256 lua_getinfo(L, ">u", &ar);
257 luaL_argcheck(L, 1 <= nup && nup <= ar.nups, argnup, "invalid upvalue index");
258 return nup; 277 return nup;
259} 278}
260 279
@@ -276,25 +295,36 @@ static int db_upvaluejoin (lua_State *L) {
276} 295}
277 296
278 297
298/*
299** The hook table (at registry[HOOKKEY]) maps threads to their current
300** hook function
301*/
279#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY) 302#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)
280 303
281 304
305/*
306** Call hook function registered at hook table for the current
307** thread (if there is one)
308*/
282static void hookf (lua_State *L, lua_Debug *ar) { 309static void hookf (lua_State *L, lua_Debug *ar) {
283 static const char *const hooknames[] = 310 static const char *const hooknames[] =
284 {"call", "return", "line", "count", "tail call"}; 311 {"call", "return", "line", "count", "tail call"};
285 gethooktable(L); 312 gethooktable(L);
286 lua_pushthread(L); 313 lua_pushthread(L);
287 if (lua_rawget(L, -2) == LUA_TFUNCTION) { 314 if (lua_rawget(L, -2) == LUA_TFUNCTION) { /* is there a hook function? */
288 lua_pushstring(L, hooknames[(int)ar->event]); 315 lua_pushstring(L, hooknames[(int)ar->event]); /* push event name */
289 if (ar->currentline >= 0) 316 if (ar->currentline >= 0)
290 lua_pushinteger(L, ar->currentline); 317 lua_pushinteger(L, ar->currentline); /* push current line */
291 else lua_pushnil(L); 318 else lua_pushnil(L);
292 lua_assert(lua_getinfo(L, "lS", ar)); 319 lua_assert(lua_getinfo(L, "lS", ar));
293 lua_call(L, 2, 0); 320 lua_call(L, 2, 0); /* call hook function */
294 } 321 }
295} 322}
296 323
297 324
325/*
326** Convert a string mask (for 'sethook') into a bit mask
327*/
298static int makemask (const char *smask, int count) { 328static int makemask (const char *smask, int count) {
299 int mask = 0; 329 int mask = 0;
300 if (strchr(smask, 'c')) mask |= LUA_MASKCALL; 330 if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
@@ -305,6 +335,9 @@ static int makemask (const char *smask, int count) {
305} 335}
306 336
307 337
338/*
339** Convert a bit mask (for 'gethook') into a string mask
340*/
308static char *unmakemask (int mask, char *smask) { 341static char *unmakemask (int mask, char *smask) {
309 int i = 0; 342 int i = 0;
310 if (mask & LUA_MASKCALL) smask[i++] = 'c'; 343 if (mask & LUA_MASKCALL) smask[i++] = 'c';
@@ -319,7 +352,7 @@ static int db_sethook (lua_State *L) {
319 int arg, mask, count; 352 int arg, mask, count;
320 lua_Hook func; 353 lua_Hook func;
321 lua_State *L1 = getthread(L, &arg); 354 lua_State *L1 = getthread(L, &arg);
322 if (lua_isnoneornil(L, arg+1)) { 355 if (lua_isnoneornil(L, arg+1)) { /* no hook? */
323 lua_settop(L, arg+1); 356 lua_settop(L, arg+1);
324 func = NULL; mask = 0; count = 0; /* turn off hooks */ 357 func = NULL; mask = 0; count = 0; /* turn off hooks */
325 } 358 }
@@ -335,9 +368,9 @@ static int db_sethook (lua_State *L) {
335 lua_pushvalue(L, -1); 368 lua_pushvalue(L, -1);
336 lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */ 369 lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */
337 } 370 }
338 lua_pushthread(L1); lua_xmove(L1, L, 1); 371 lua_pushthread(L1); lua_xmove(L1, L, 1); /* key */
339 lua_pushvalue(L, arg+1); 372 lua_pushvalue(L, arg+1); /* value */
340 lua_rawset(L, -3); /* set new hook */ 373 lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */
341 lua_sethook(L1, func, mask, count); /* set hooks */ 374 lua_sethook(L1, func, mask, count); /* set hooks */
342 return 0; 375 return 0;
343} 376}
@@ -354,11 +387,11 @@ static int db_gethook (lua_State *L) {
354 else { 387 else {
355 gethooktable(L); 388 gethooktable(L);
356 lua_pushthread(L1); lua_xmove(L1, L, 1); 389 lua_pushthread(L1); lua_xmove(L1, L, 1);
357 lua_rawget(L, -2); /* get hook */ 390 lua_rawget(L, -2); /* 1st result = hooktable[L1] */
358 lua_remove(L, -2); /* remove hook table */ 391 lua_remove(L, -2); /* remove hook table */
359 } 392 }
360 lua_pushstring(L, unmakemask(mask, buff)); 393 lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */
361 lua_pushinteger(L, lua_gethookcount(L1)); 394 lua_pushinteger(L, lua_gethookcount(L1)); /* 3rd result = count */
362 return 3; 395 return 3;
363} 396}
364 397