comparison src/ex_cmds2.c @ 7605:8fc60af6dbf5 v7.4.1102

commit https://github.com/vim/vim/commit/f1f60f859cdbb2638b3662ccf7b1d179865fe7dc Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jan 16 15:40:53 2016 +0100 patch 7.4.1102 Problem: Debugger has no stack backtrace support. Solution: Add "backtrace", "frame", "up" and "down" commands. (Alberto Fanjul, closes https://github.com/vim/vim/issues/433)
author Christian Brabandt <cb@256bit.org>
date Sat, 16 Jan 2016 15:45:04 +0100
parents 15eefe1b0dad
children b4384c581806
comparison
equal deleted inserted replaced
7604:09a1aca8d980 7605:8fc60af6dbf5
66 #endif 66 #endif
67 67
68 #if defined(FEAT_EVAL) || defined(PROTO) 68 #if defined(FEAT_EVAL) || defined(PROTO)
69 static int debug_greedy = FALSE; /* batch mode debugging: don't save 69 static int debug_greedy = FALSE; /* batch mode debugging: don't save
70 and restore typeahead. */ 70 and restore typeahead. */
71 static int get_maxbacktrace_level(void);
72 static void do_setdebugtracelevel(char_u *arg);
73 static void do_checkbacktracelevel(void);
74 static void do_showbacktrace(char_u *cmd);
71 75
72 /* 76 /*
73 * do_debug(): Debug mode. 77 * do_debug(): Debug mode.
74 * Repeatedly get Ex commands, until told to continue normal execution. 78 * Repeatedly get Ex commands, until told to continue normal execution.
75 */ 79 */
99 #define CMD_NEXT 2 103 #define CMD_NEXT 2
100 #define CMD_STEP 3 104 #define CMD_STEP 3
101 #define CMD_FINISH 4 105 #define CMD_FINISH 4
102 #define CMD_QUIT 5 106 #define CMD_QUIT 5
103 #define CMD_INTERRUPT 6 107 #define CMD_INTERRUPT 6
108 #define CMD_BACKTRACE 7
109 #define CMD_FRAME 8
110 #define CMD_UP 9
111 #define CMD_DOWN 10
104 112
105 #ifdef ALWAYS_USE_GUI 113 #ifdef ALWAYS_USE_GUI
106 /* Can't do this when there is no terminal for input/output. */ 114 /* Can't do this when there is no terminal for input/output. */
107 if (!gui.in_use) 115 if (!gui.in_use)
108 { 116 {
176 # ifdef FEAT_EX_EXTRA 184 # ifdef FEAT_EX_EXTRA
177 ex_normal_busy = save_ex_normal_busy; 185 ex_normal_busy = save_ex_normal_busy;
178 # endif 186 # endif
179 187
180 cmdline_row = msg_row; 188 cmdline_row = msg_row;
189 msg_starthere();
181 if (cmdline != NULL) 190 if (cmdline != NULL)
182 { 191 {
183 /* If this is a debug command, set "last_cmd". 192 /* If this is a debug command, set "last_cmd".
184 * If not, reset "last_cmd". 193 * If not, reset "last_cmd".
185 * For a blank line use previous command. */ 194 * For a blank line use previous command. */
195 tail = "ext"; 204 tail = "ext";
196 break; 205 break;
197 case 's': last_cmd = CMD_STEP; 206 case 's': last_cmd = CMD_STEP;
198 tail = "tep"; 207 tail = "tep";
199 break; 208 break;
200 case 'f': last_cmd = CMD_FINISH; 209 case 'f':
201 tail = "inish"; 210 last_cmd = 0;
211 if (p[1] == 'r')
212 {
213 last_cmd = CMD_FRAME;
214 tail = "rame";
215 }
216 else
217 {
218 last_cmd = CMD_FINISH;
219 tail = "inish";
220 }
202 break; 221 break;
203 case 'q': last_cmd = CMD_QUIT; 222 case 'q': last_cmd = CMD_QUIT;
204 tail = "uit"; 223 tail = "uit";
205 break; 224 break;
206 case 'i': last_cmd = CMD_INTERRUPT; 225 case 'i': last_cmd = CMD_INTERRUPT;
207 tail = "nterrupt"; 226 tail = "nterrupt";
227 break;
228 case 'b': last_cmd = CMD_BACKTRACE;
229 if (p[1] == 't')
230 tail = "t";
231 else
232 tail = "acktrace";
233 break;
234 case 'w': last_cmd = CMD_BACKTRACE;
235 tail = "here";
236 break;
237 case 'u': last_cmd = CMD_UP;
238 tail = "p";
239 break;
240 case 'd': last_cmd = CMD_DOWN;
241 tail = "own";
208 break; 242 break;
209 default: last_cmd = 0; 243 default: last_cmd = 0;
210 } 244 }
211 if (last_cmd != 0) 245 if (last_cmd != 0)
212 { 246 {
215 while (*p != NUL && *p == *tail) 249 while (*p != NUL && *p == *tail)
216 { 250 {
217 ++p; 251 ++p;
218 ++tail; 252 ++tail;
219 } 253 }
220 if (ASCII_ISALPHA(*p)) 254 if (ASCII_ISALPHA(*p) && last_cmd != CMD_FRAME)
221 last_cmd = 0; 255 last_cmd = 0;
222 } 256 }
223 } 257 }
224 258
225 if (last_cmd != 0) 259 if (last_cmd != 0)
248 got_int = TRUE; 282 got_int = TRUE;
249 debug_break_level = 9999; 283 debug_break_level = 9999;
250 /* Do not repeat ">interrupt" cmd, continue stepping. */ 284 /* Do not repeat ">interrupt" cmd, continue stepping. */
251 last_cmd = CMD_STEP; 285 last_cmd = CMD_STEP;
252 break; 286 break;
287 case CMD_BACKTRACE:
288 do_showbacktrace(cmd);
289 continue;
290 case CMD_FRAME:
291 if (*p == NUL)
292 {
293 do_showbacktrace(cmd);
294 }
295 else
296 {
297 p = skipwhite(p);
298 do_setdebugtracelevel(p);
299 }
300 continue;
301 case CMD_UP:
302 debug_backtrace_level++;
303 do_checkbacktracelevel();
304 continue;
305 case CMD_DOWN:
306 debug_backtrace_level--;
307 do_checkbacktracelevel();
308 continue;
253 } 309 }
310 /* Going out reset backtrace_level */
311 debug_backtrace_level = 0;
254 break; 312 break;
255 } 313 }
256 314
257 /* don't debug this command */ 315 /* don't debug this command */
258 n = debug_break_level; 316 n = debug_break_level;
281 redir_off = save_redir_off; 339 redir_off = save_redir_off;
282 340
283 /* Only print the message again when typing a command before coming back 341 /* Only print the message again when typing a command before coming back
284 * here. */ 342 * here. */
285 debug_did_msg = TRUE; 343 debug_did_msg = TRUE;
344 }
345
346 static int
347 get_maxbacktrace_level(void)
348 {
349 char *p, *q;
350 int maxbacktrace = 1;
351
352 maxbacktrace = 0;
353 if (sourcing_name != NULL)
354 {
355 p = (char *)sourcing_name;
356 while ((q = strstr(p, "..")) != NULL)
357 {
358 p = q + 2;
359 maxbacktrace++;
360 }
361 }
362 return maxbacktrace;
363 }
364
365 static void
366 do_setdebugtracelevel(char_u *arg)
367 {
368 int level;
369
370 level = atoi((char *)arg);
371 if (*arg == '+' || level < 0)
372 debug_backtrace_level += level;
373 else
374 debug_backtrace_level = level;
375
376 do_checkbacktracelevel();
377 }
378
379 static void
380 do_checkbacktracelevel(void)
381 {
382 if (debug_backtrace_level < 0)
383 {
384 debug_backtrace_level = 0;
385 MSG(_("frame is zero"));
386 }
387 else
388 {
389 int max = get_maxbacktrace_level();
390
391 if (debug_backtrace_level > max)
392 {
393 debug_backtrace_level = max;
394 smsg((char_u *)_("frame at highest level: %d"), max);
395 }
396 }
397 }
398
399 static void
400 do_showbacktrace(char_u *cmd)
401 {
402 char *cur;
403 char *next;
404 int i = 0;
405 int max = get_maxbacktrace_level();
406
407 if (sourcing_name != NULL)
408 {
409 cur = (char *)sourcing_name;
410 while (!got_int)
411 {
412 next = strstr(cur, "..");
413 if (next != NULL)
414 *next = NUL;
415 if (i == max - debug_backtrace_level)
416 smsg((char_u *)"->%d %s", max - i, cur);
417 else
418 smsg((char_u *)" %d %s", max - i, cur);
419 ++i;
420 if (next == NULL)
421 break;
422 *next = '.';
423 cur = next + 2;
424 }
425 }
426 if (sourcing_lnum != 0)
427 smsg((char_u *)_("line %ld: %s"), (long)sourcing_lnum, cmd);
428 else
429 smsg((char_u *)_("cmd: %s"), cmd);
286 } 430 }
287 431
288 /* 432 /*
289 * ":debug". 433 * ":debug".
290 */ 434 */