diff options
Diffstat (limited to 'ldebug.c')
-rw-r--r-- | ldebug.c | 213 |
1 files changed, 131 insertions, 82 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldebug.c,v 1.3 1999/12/29 16:31:15 roberto Exp roberto $ | 2 | ** $Id: ldebug.c,v 1.4 1999/12/30 18:28:40 roberto Exp roberto $ |
3 | ** Debug Interface | 3 | ** Debug Interface |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -10,6 +10,7 @@ | |||
10 | #include "lapi.h" | 10 | #include "lapi.h" |
11 | #include "lauxlib.h" | 11 | #include "lauxlib.h" |
12 | #include "ldebug.h" | 12 | #include "ldebug.h" |
13 | #include "ldo.h" | ||
13 | #include "lfunc.h" | 14 | #include "lfunc.h" |
14 | #include "lobject.h" | 15 | #include "lobject.h" |
15 | #include "lstate.h" | 16 | #include "lstate.h" |
@@ -19,22 +20,38 @@ | |||
19 | #include "luadebug.h" | 20 | #include "luadebug.h" |
20 | 21 | ||
21 | 22 | ||
22 | static int hasdebuginfo (lua_State *L, lua_Function f) { | 23 | static const lua_Type normtype[] = { /* ORDER LUA_T */ |
23 | return (f+1 < L->top && (f+1)->ttype == LUA_T_LINE); | 24 | LUA_T_USERDATA, LUA_T_NUMBER, LUA_T_STRING, LUA_T_ARRAY, |
25 | LUA_T_LPROTO, LUA_T_CPROTO, LUA_T_NIL, | ||
26 | LUA_T_LCLOSURE, LUA_T_CCLOSURE, | ||
27 | LUA_T_LCLOSURE, LUA_T_CCLOSURE, /* LUA_T_LCLMARK, LUA_T_CCLMARK */ | ||
28 | LUA_T_LPROTO, LUA_T_CPROTO /* LUA_T_LMARK, LUA_T_CMARK */ | ||
29 | }; | ||
30 | |||
31 | |||
32 | static void setnormalized (TObject *d, const TObject *s) { | ||
33 | d->value = s->value; | ||
34 | d->ttype = normtype[-ttype(s)]; | ||
24 | } | 35 | } |
25 | 36 | ||
26 | 37 | ||
27 | lua_LHFunction lua_setlinehook (lua_State *L, lua_LHFunction func) { | 38 | |
28 | lua_LHFunction old = L->linehook; | 39 | static int hasdebuginfo (lua_State *L, StkId f) { |
29 | L->linehook = func; | 40 | return (f+1 < L->top && (f+1)->ttype == LUA_T_LINE); |
30 | return old; | ||
31 | } | 41 | } |
32 | 42 | ||
33 | 43 | ||
34 | lua_CHFunction lua_setcallhook (lua_State *L, lua_CHFunction func) { | 44 | lua_Dbghook lua_setcallhook (lua_State *L, lua_Dbghook func) { |
35 | lua_CHFunction old = L->callhook; | 45 | lua_Dbghook oldhook = L->callhook; |
36 | L->callhook = func; | 46 | L->callhook = func; |
37 | return old; | 47 | return oldhook; |
48 | } | ||
49 | |||
50 | |||
51 | lua_Dbghook lua_setlinehook (lua_State *L, lua_Dbghook func) { | ||
52 | lua_Dbghook oldhook = L->linehook; | ||
53 | L->linehook = func; | ||
54 | return oldhook; | ||
38 | } | 55 | } |
39 | 56 | ||
40 | 57 | ||
@@ -45,7 +62,7 @@ int lua_setdebug (lua_State *L, int debug) { | |||
45 | } | 62 | } |
46 | 63 | ||
47 | 64 | ||
48 | static lua_Function aux_stackedfunction (lua_State *L, int level, StkId top) { | 65 | static StkId aux_stackedfunction (lua_State *L, int level, StkId top) { |
49 | int i; | 66 | int i; |
50 | for (i = (top-1)-L->stack; i>=0; i--) { | 67 | for (i = (top-1)-L->stack; i>=0; i--) { |
51 | if (is_T_MARK(L->stack[i].ttype)) { | 68 | if (is_T_MARK(L->stack[i].ttype)) { |
@@ -54,18 +71,23 @@ static lua_Function aux_stackedfunction (lua_State *L, int level, StkId top) { | |||
54 | level--; | 71 | level--; |
55 | } | 72 | } |
56 | } | 73 | } |
57 | return LUA_NOOBJECT; | 74 | return NULL; |
58 | } | 75 | } |
59 | 76 | ||
60 | 77 | ||
61 | lua_Function lua_stackedfunction (lua_State *L, int level) { | 78 | int lua_getstack (lua_State *L, int level, lua_Dbgactreg *ar) { |
62 | return aux_stackedfunction(L, level, L->top); | 79 | StkId f = aux_stackedfunction(L, level, L->top); |
80 | if (f == NULL) return 0; /* there is no such level */ | ||
81 | else { | ||
82 | ar->_func = f; | ||
83 | return 1; | ||
84 | } | ||
63 | } | 85 | } |
64 | 86 | ||
65 | 87 | ||
66 | static const char *luaG_getname (lua_State *L, const char **name, StkId top) { | 88 | static const char *luaG_getname (lua_State *L, const char **name, StkId top) { |
67 | lua_Function f = aux_stackedfunction(L, 0, top); | 89 | StkId f = aux_stackedfunction(L, 0, top); |
68 | if (f == LUA_NOOBJECT || !hasdebuginfo(L, f) || ttype(f+2) == LUA_T_NIL) | 90 | if (f == NULL || !hasdebuginfo(L, f) || ttype(f+2) == LUA_T_NIL) |
69 | return ""; /* no name available */ | 91 | return ""; /* no name available */ |
70 | else { | 92 | else { |
71 | int i = (f+2)->value.i; | 93 | int i = (f+2)->value.i; |
@@ -79,10 +101,10 @@ static const char *luaG_getname (lua_State *L, const char **name, StkId top) { | |||
79 | } | 101 | } |
80 | 102 | ||
81 | 103 | ||
82 | int lua_nups (lua_State *L, lua_Function f) { | 104 | static int lua_nups (StkId f) { |
83 | UNUSED(L); | 105 | switch (ttype(f)) { |
84 | switch (luaA_normalizedtype(f)) { | ||
85 | case LUA_T_LCLOSURE: case LUA_T_CCLOSURE: | 106 | case LUA_T_LCLOSURE: case LUA_T_CCLOSURE: |
107 | case LUA_T_LCLMARK: case LUA_T_CCLMARK: | ||
86 | return f->value.cl->nelems; | 108 | return f->value.cl->nelems; |
87 | default: | 109 | default: |
88 | return 0; | 110 | return 0; |
@@ -90,67 +112,66 @@ int lua_nups (lua_State *L, lua_Function f) { | |||
90 | } | 112 | } |
91 | 113 | ||
92 | 114 | ||
93 | int lua_currentline (lua_State *L, lua_Function f) { | 115 | static int lua_currentline (lua_State *L, StkId f) { |
94 | return hasdebuginfo(L, f) ? (f+1)->value.i : -1; | 116 | return hasdebuginfo(L, f) ? (f+1)->value.i : -1; |
95 | } | 117 | } |
96 | 118 | ||
97 | 119 | ||
98 | lua_Object lua_getlocal (lua_State *L, lua_Function f, int local_number, | 120 | static TProtoFunc *getluaproto (StkId f) { |
99 | const char **name) { | 121 | if (ttype(f) == LUA_T_LMARK) |
100 | /* check whether `f' is a Lua function */ | 122 | return f->value.tf; |
101 | if (lua_tag(L, f) != LUA_T_LPROTO) | 123 | else if (ttype(f) == LUA_T_LCLMARK) |
102 | return LUA_NOOBJECT; | 124 | return protovalue(f)->value.tf; |
103 | else { | 125 | else return NULL; |
104 | TProtoFunc *fp = luaA_protovalue(f)->value.tf; | ||
105 | *name = luaF_getlocalname(fp, local_number, lua_currentline(L, f)); | ||
106 | if (*name) { | ||
107 | /* if "*name", there must be a LUA_T_LINE and a NAME */ | ||
108 | /* therefore, f+3 points to function base */ | ||
109 | LUA_ASSERT(L, ttype(f+1) == LUA_T_LINE, ""); | ||
110 | return luaA_putluaObject(L, (f+3)+(local_number-1)); | ||
111 | } | ||
112 | else | ||
113 | return LUA_NOOBJECT; | ||
114 | } | ||
115 | } | 126 | } |
116 | 127 | ||
117 | 128 | ||
118 | int lua_setlocal (lua_State *L, lua_Function f, int local_number) { | 129 | int lua_getlocal (lua_State *L, const lua_Dbgactreg *ar, lua_Dbglocvar *v) { |
119 | /* check whether `f' is a Lua function */ | 130 | StkId f = ar->_func; |
120 | if (lua_tag(L, f) != LUA_T_LPROTO) | 131 | TProtoFunc *fp = getluaproto(f); |
121 | return 0; | 132 | if (!fp) return 0; /* `f' is not a Lua function? */ |
122 | else { | 133 | v->name = luaF_getlocalname(fp, v->index, lua_currentline(L, f)); |
123 | TProtoFunc *fp = luaA_protovalue(f)->value.tf; | 134 | if (!v->name) return 0; |
124 | const char *name = luaF_getlocalname(fp, local_number, | 135 | /* if `name', there must be a LUA_T_LINE and a NAME */ |
125 | lua_currentline(L, f)); | 136 | /* therefore, f+3 points to function base */ |
126 | luaA_checkCparams(L, 1); | 137 | LUA_ASSERT(L, ttype(f+1) == LUA_T_LINE, ""); |
127 | --L->top; | 138 | v->value = luaA_putluaObject(L, (f+3)+(v->index-1)); |
128 | if (name) { | 139 | return 1; |
129 | LUA_ASSERT(L, ttype(f+1) == LUA_T_LINE, ""); | ||
130 | *((f+3)+(local_number-1)) = *L->top; | ||
131 | return 1; | ||
132 | } | ||
133 | else | ||
134 | return 0; | ||
135 | } | ||
136 | } | 140 | } |
137 | 141 | ||
138 | 142 | ||
139 | void lua_funcinfo (lua_State *L, lua_Object func, | 143 | int lua_setlocal (lua_State *L, const lua_Dbgactreg *ar, lua_Dbglocvar *v) { |
140 | const char **source, int *linedefined) { | 144 | StkId f = ar->_func; |
141 | if (!lua_isfunction(L, func)) | 145 | TProtoFunc *fp = getluaproto(f); |
142 | lua_error(L, "API error - `funcinfo' called with a non-function value"); | 146 | if (!fp) return 0; /* `f' is not a Lua function? */ |
143 | else { | 147 | v->name = luaF_getlocalname(fp, v->index, lua_currentline(L, f)); |
144 | const TObject *f = luaA_protovalue(func); | 148 | if (!v->name) return 0; |
145 | if (luaA_normalizedtype(f) == LUA_T_LPROTO) { | 149 | LUA_ASSERT(L, ttype(f+1) == LUA_T_LINE, ""); |
146 | *source = tfvalue(f)->source->str; | 150 | *((f+3)+(v->index-1)) = *v->value; |
147 | *linedefined = tfvalue(f)->lineDefined; | 151 | return 1; |
148 | } | 152 | } |
149 | else { | 153 | |
150 | *source = "(C)"; | 154 | |
151 | *linedefined = -1; | 155 | static void lua_funcinfo (lua_Dbgactreg *ar) { |
152 | } | 156 | StkId func = ar->_func; |
157 | switch (ttype(func)) { | ||
158 | case LUA_T_LPROTO: case LUA_T_LMARK: | ||
159 | ar->source = tfvalue(func)->source->str; | ||
160 | ar->linedefined = tfvalue(func)->lineDefined; | ||
161 | ar->what = "Lua"; | ||
162 | break; | ||
163 | case LUA_T_LCLOSURE: case LUA_T_LCLMARK: | ||
164 | ar->source = tfvalue(protovalue(func))->source->str; | ||
165 | ar->linedefined = tfvalue(protovalue(func))->lineDefined; | ||
166 | ar->what = "Lua"; | ||
167 | break; | ||
168 | default: | ||
169 | ar->source = "(C)"; | ||
170 | ar->linedefined = -1; | ||
171 | ar->what = "C"; | ||
153 | } | 172 | } |
173 | if (ar->linedefined == 0) | ||
174 | ar->what = "main"; | ||
154 | } | 175 | } |
155 | 176 | ||
156 | 177 | ||
@@ -159,28 +180,56 @@ static int checkfunc (lua_State *L, TObject *o) { | |||
159 | } | 180 | } |
160 | 181 | ||
161 | 182 | ||
162 | const char *lua_getobjname (lua_State *L, lua_Object o, const char **name) { | 183 | static void lua_getobjname (lua_State *L, StkId f, lua_Dbgactreg *ar) { |
163 | GlobalVar *g; | 184 | GlobalVar *g; |
164 | if (is_T_MARK(ttype(o))) { /* `o' is an active function? */ | 185 | ar->namewhat = luaG_getname(L, &ar->name, f); /* caller debug information */ |
165 | /* look for caller debug information */ | 186 | if (*ar->namewhat) return; |
166 | const char *kind = luaG_getname(L, name, o); | ||
167 | if (*kind) return kind; | ||
168 | /* else go through */ | ||
169 | } | ||
170 | /* try to find a name for given function */ | 187 | /* try to find a name for given function */ |
171 | luaA_setnormalized(L->top, o); /* to be used by `checkfunc' */ | 188 | setnormalized(L->top, f); /* to be used by `checkfunc' */ |
172 | for (g=L->rootglobal; g; g=g->next) { | 189 | for (g=L->rootglobal; g; g=g->next) { |
173 | if (checkfunc(L, &g->value)) { | 190 | if (checkfunc(L, &g->value)) { |
174 | *name = g->name->str; | 191 | ar->name = g->name->str; |
175 | return "global"; | 192 | ar->namewhat = "global"; |
193 | return; | ||
176 | } | 194 | } |
177 | } | 195 | } |
178 | /* not found: try tag methods */ | 196 | /* not found: try tag methods */ |
179 | if ((*name = luaT_travtagmethods(L, checkfunc)) != NULL) | 197 | if ((ar->name = luaT_travtagmethods(L, checkfunc)) != NULL) |
180 | return "tag-method"; | 198 | ar->namewhat = "tag-method"; |
181 | else return ""; /* not found at all */ | 199 | else ar->namewhat = ""; /* not found at all */ |
200 | } | ||
201 | |||
202 | |||
203 | int lua_getinfo (lua_State *L, const char *what, lua_Dbgactreg *ar) { | ||
204 | StkId func = ar->_func; | ||
205 | LUA_ASSERT(L, is_T_MARK(ttype(func)), "invalid activation record"); | ||
206 | for ( ;*what; what++) { | ||
207 | switch (*what) { | ||
208 | case 'S': | ||
209 | lua_funcinfo(ar); | ||
210 | break; | ||
211 | case 'l': | ||
212 | ar->currentline = lua_currentline(L, func); | ||
213 | break; | ||
214 | case 'u': | ||
215 | ar->nups = lua_nups(func); | ||
216 | break; | ||
217 | case 'n': | ||
218 | lua_getobjname(L, func, ar); | ||
219 | break; | ||
220 | case 'f': | ||
221 | setnormalized(L->top, func); | ||
222 | incr_top; | ||
223 | ar->func = luaA_putObjectOnTop(L); | ||
224 | break; | ||
225 | default: return 0; /* invalid option */ | ||
226 | } | ||
227 | } | ||
228 | return 1; | ||
182 | } | 229 | } |
183 | 230 | ||
231 | |||
232 | |||
184 | static void call_index_error (lua_State *L, TObject *o, const char *tp, | 233 | static void call_index_error (lua_State *L, TObject *o, const char *tp, |
185 | const char *v) { | 234 | const char *v) { |
186 | const char *name; | 235 | const char *name; |