1 /*
2 ** $Id: ldblib.c,v 1.1 2002/02/14 10:46:59 jcatki Exp $
3 ** Interface from Lua to its debug API
4 ** See Copyright Notice in lua.h
5 */
6 
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include "lua.h"
13 
14 #include "lauxlib.h"
15 #include "luadebug.h"
16 #include "lualib.h"
17 
18 
19 
settabss(lua_State * L,const char * i,const char * v)20 static void settabss (lua_State *L, const char *i, const char *v) {
21   lua_pushstring(L, i);
22   lua_pushstring(L, v);
23   lua_settable(L, -3);
24 }
25 
26 
settabsi(lua_State * L,const char * i,int v)27 static void settabsi (lua_State *L, const char *i, int v) {
28   lua_pushstring(L, i);
29   lua_pushnumber(L, v);
30   lua_settable(L, -3);
31 }
32 
33 
getinfo(lua_State * L)34 static int getinfo (lua_State *L) {
35   lua_Debug ar;
36   const char *options = luaL_opt_string(L, 2, "flnSu");
37   char buff[20];
38   if (lua_isnumber(L, 1)) {
39     if (!lua_getstack(L, (int)lua_tonumber(L, 1), &ar)) {
40       lua_pushnil(L);  /* level out of range */
41       return 1;
42     }
43   }
44   else if (lua_isfunction(L, 1)) {
45     lua_pushvalue(L, 1);
46     sprintf(buff, ">%.10s", options);
47     options = buff;
48   }
49   else
50     luaL_argerror(L, 1, "function or level expected");
51   if (!lua_getinfo(L, options, &ar))
52     luaL_argerror(L, 2, "invalid option");
53   lua_newtable(L);
54   for (; *options; options++) {
55     switch (*options) {
56       case 'S':
57         settabss(L, "source", ar.source);
58         if (ar.source)
59           settabss(L, "short_src", ar.short_src);
60         settabsi(L, "linedefined", ar.linedefined);
61         settabss(L, "what", ar.what);
62         break;
63       case 'l':
64         settabsi(L, "currentline", ar.currentline);
65         break;
66       case 'u':
67         settabsi(L, "nups", ar.nups);
68         break;
69       case 'n':
70         settabss(L, "name", ar.name);
71         settabss(L, "namewhat", ar.namewhat);
72         break;
73       case 'f':
74         lua_pushstring(L, "func");
75         lua_pushvalue(L, -3);
76         lua_settable(L, -3);
77         break;
78     }
79   }
80   return 1;  /* return table */
81 }
82 
83 
getlocal(lua_State * L)84 static int getlocal (lua_State *L) {
85   lua_Debug ar;
86   const char *name;
87   if (!lua_getstack(L, luaL_check_int(L, 1), &ar))  /* level out of range? */
88     luaL_argerror(L, 1, "level out of range");
89   name = lua_getlocal(L, &ar, luaL_check_int(L, 2));
90   if (name) {
91     lua_pushstring(L, name);
92     lua_pushvalue(L, -2);
93     return 2;
94   }
95   else {
96     lua_pushnil(L);
97     return 1;
98   }
99 }
100 
101 
setlocal(lua_State * L)102 static int setlocal (lua_State *L) {
103   lua_Debug ar;
104   if (!lua_getstack(L, luaL_check_int(L, 1), &ar))  /* level out of range? */
105     luaL_argerror(L, 1, "level out of range");
106   luaL_checkany(L, 3);
107   lua_pushstring(L, lua_setlocal(L, &ar, luaL_check_int(L, 2)));
108   return 1;
109 }
110 
111 
112 
113 /* dummy variables (to define unique addresses) */
114 static char key1, key2;
115 #define KEY_CALLHOOK	(&key1)
116 #define KEY_LINEHOOK	(&key2)
117 
118 
hookf(lua_State * L,void * key)119 static void hookf (lua_State *L, void *key) {
120   lua_getregistry(L);
121   lua_pushuserdata(L, key);
122   lua_gettable(L, -2);
123   if (lua_isfunction(L, -1)) {
124     lua_pushvalue(L, 1);
125     lua_rawcall(L, 1, 0);
126   }
127   else
128     lua_pop(L, 1);  /* pop result from gettable */
129   lua_pop(L, 1);  /* pop table */
130 }
131 
132 
callf(lua_State * L,lua_Debug * ar)133 static void callf (lua_State *L, lua_Debug *ar) {
134   lua_pushstring(L, ar->event);
135   hookf(L, KEY_CALLHOOK);
136 }
137 
138 
linef(lua_State * L,lua_Debug * ar)139 static void linef (lua_State *L, lua_Debug *ar) {
140   lua_pushnumber(L, ar->currentline);
141   hookf(L, KEY_LINEHOOK);
142 }
143 
144 
sethook(lua_State * L,void * key,lua_Hook hook,lua_Hook (* sethookf)(lua_State * L,lua_Hook h))145 static void sethook (lua_State *L, void *key, lua_Hook hook,
146                      lua_Hook (*sethookf)(lua_State * L, lua_Hook h)) {
147   lua_settop(L, 1);
148   if (lua_isnil(L, 1))
149     (*sethookf)(L, NULL);
150   else if (lua_isfunction(L, 1))
151     (*sethookf)(L, hook);
152   else
153     luaL_argerror(L, 1, "function expected");
154   lua_getregistry(L);
155   lua_pushuserdata(L, key);
156   lua_pushvalue(L, -1);  /* dup key */
157   lua_gettable(L, -3);   /* get old value */
158   lua_pushvalue(L, -2);  /* key (again) */
159   lua_pushvalue(L, 1);
160   lua_settable(L, -5);  /* set new value */
161 }
162 
163 
setcallhook(lua_State * L)164 static int setcallhook (lua_State *L) {
165   sethook(L, KEY_CALLHOOK, callf, lua_setcallhook);
166   return 1;
167 }
168 
169 
setlinehook(lua_State * L)170 static int setlinehook (lua_State *L) {
171   sethook(L, KEY_LINEHOOK, linef, lua_setlinehook);
172   return 1;
173 }
174 
175 
176 static const struct luaL_reg dblib[] = {
177   {"getlocal", getlocal},
178   {"getinfo", getinfo},
179   {"setcallhook", setcallhook},
180   {"setlinehook", setlinehook},
181   {"setlocal", setlocal}
182 };
183 
184 
lua_dblibopen(lua_State * L)185 LUALIB_API void lua_dblibopen (lua_State *L) {
186   luaL_openl(L, dblib);
187 }
188 
189