debug.c
来自「具有IDE功能的编辑器」· C语言 代码 · 共 1,371 行 · 第 1/3 页
C
1,371 行
/* debug.c - interactive debugger Copyright (C) 1996-2000 Paul Sheer This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */#include <config.h>#include <stdio.h>#include <my_string.h>#include <stdlib.h>#include <stdio.h>#include <signal.h>#include <sys/types.h>#if HAVE_SYS_WAIT_H#include <sys/wait.h>#endif#include <sys/stat.h>#ifdef HAVE_SYS_TIME_H#include <sys/time.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_PWD_H#include <pwd.h>#endif#ifdef HAVE_GRP_H# include <grp.h>#endif#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/Xatom.h>#include "lkeysym.h"#ifdef HAVE_SYS_IOCTL_H#include <sys/ioctl.h>#endif#include "stringtools.h"#include "coolwidget.h"#include "edit.h"#include "editcmddef.h"#include "loadfile.h"#include "editoptions.h"#include "cmdlineopt.h"#include "shell.h"#include "widget/pool.h"#include "find.h"#include "mad.h"extern struct look *look;#define DEBUG_TIME_OUT 15#define DEBUG_BREAKPOINT_COLOR 18#define DEBUG_CURRENT_COLOR 6#define ACTION_PROMPT 1#define ACTION_MESSAGE 2#define ACTION_BREAKPOINT 3#define ACTION_INFO_SOURCE 4#define ACTION_BACKTRACE 5#define ACTION_RUNNING 6#define ACTION_STEP 7#define ACTION_INFO_PROGRAM 8#define ACTION_VERSION 9#define ACTION_CONDITION 10#define ACTION_QUIT 11#define ACTION_SHOW 12#define ACTION_UNTIL 13#define ACTION_VARIABLE 14#define ACTION_LASTVAR 15#define ACTION_WATCH 16#define GDB_VERSION1 "GNU gdb 4.17"#define GDB_VERSION2 "GNU gdb 4.18"#define GDB_VERSION3 "GNU gdb 5.0"static void debug_read_callback (int fd, fd_set * reading, fd_set * writing, fd_set * error, void *data);static void debug_write_callback (int fd, fd_set * reading, fd_set * writing, fd_set * error, void *data);#define MAX_DEBUG_CMD_LEN MAX_PATH_LEN#define MAX_QUEUED_COMMANDS 100#define MAX_VARIABLES 60typedef struct struct_debug { int x, y, r; Window w; int in; int out; char *prompt; char *get_line; char *get_source; char *get_backtrace; struct debug_query { char *query; char *response; } query[10]; char *progname; char *debugger; char *args; pid_t pid; pid_t child; struct _command { int action; char *command; char *editor; int line; } command[MAX_QUEUED_COMMANDS]; struct _variable { char *name; char *output; int watch; int changed; } variable[MAX_VARIABLES]; int last_variable_displayed; int n_commands; int action; POOL *pool; int line; char *file; char *condition; int show_output, stop_at_main, show_on_stdout; int ignore_SIGTTOU; pid_t xterm_pid; int break_point_line; char *break_point_editor;} Debug;extern CWidget *edit[50];extern int current_edit;extern int last_edit;static void debug_message (Debug * d, char *heading, char *str, int options){ if (d->pid) { CRemoveWatch (d->in, debug_write_callback, WATCH_WRITING); CRemoveWatch (d->out, debug_read_callback, WATCH_READING); } CMessageDialog (0, 20, 20, options, heading, "%s", str); if (d->pid) { if (d->n_commands && !d->action) CAddWatch (d->in, debug_write_callback, WATCH_WRITING, 0); CAddWatch (d->out, debug_read_callback, WATCH_READING, 0); }}static void debug_error2 (Debug * d, char *par1, char *par2){ char *t; if (d->pid) { CRemoveWatch (d->in, debug_write_callback, WATCH_WRITING); CRemoveWatch (d->out, debug_read_callback, WATCH_READING); } t = malloc (strlen (par1) + strlen (par2) + 80); if (*par2) sprintf (t, " %s: %s ", par1, par2); else sprintf (t, " %s ", par1); CErrorDialog (0, 0, 0, _ (" Debug Message "), "%s", t); free (t); if (d->pid) { if (d->n_commands && !d->action) CAddWatch (d->in, debug_write_callback, WATCH_WRITING, 0); CAddWatch (d->out, debug_read_callback, WATCH_READING, 0); }}#define debug_error1(d, x) debug_error2(d, x, "")static void xdebug_cursor_bookmark_flush (void){ int i; for (i = 0; i < last_edit; i++) if (edit[i]->editor) book_mark_flush (edit[i]->editor, DEBUG_CURRENT_COLOR);}static void xdebug_append_command (Debug * d, char *s, int action, char *editor, int line){ if (d->n_commands < MAX_QUEUED_COMMANDS - 2) { d->command[d->n_commands].command = (char *) strdup (s); d->command[d->n_commands].action = action; if (editor) d->command[d->n_commands].editor = (char *) strdup (editor); else d->command[d->n_commands].editor = 0; d->command[d->n_commands].line = line; d->n_commands++; if (!d->action) CAddWatch (d->in, debug_write_callback, WATCH_WRITING, 0); }}static void xdebug_flush_commands (Debug * d){ int i; for (i = 0; i < d->n_commands; i++) { if (d->command[i].editor) free (d->command[i].editor); free (d->command[i].command); d->command[i].command = 0; } d->action = 0; d->n_commands = 0; d->last_variable_displayed = 0; CRemoveWatch (d->in, debug_write_callback, WATCH_WRITING);}/* {{{ variables */static void xdebug_show_variables (Debug * d){ int i; char s[1024]; for (i = 0; d->variable[i].name; i++) { sprintf (s, "p %s\n", d->variable[i].name); xdebug_append_command (d, s, d->variable[i + 1].name ? ACTION_VARIABLE : ACTION_LASTVAR, 0, 0); }}static int xdebug_add_variable (Debug * d, char *s){ int i; for (i = 0; d->variable[i].name; i++); if (i >= MAX_VARIABLES - 1) { debug_error1 (d, _ ("Max variables exceeded")); return 1; } d->variable[i].output = 0; d->variable[i].name = (char *) strdup (s); d->variable[i + 1].name = 0; d->variable[i + 1].output = 0; return 0;}static void xdebug_remove_variable (Debug * d, int i){ if (d->variable[i].name) { free (d->variable[i].name); if (d->variable[i].output) free (d->variable[i].output); } memcpy (&d->variable[i], &d->variable[i + 1], (MAX_VARIABLES - i) * sizeof (struct _variable));}static char **xdebug_get_line (void *data, int line, int *numfields, int *tagged){ static char *fields[3]; Debug *d = (Debug *) data; *numfields = 3; if (!d->variable[line].name || !d->variable[line].output) return 0; *tagged = (d->variable[line].watch != 0); fields[0] = d->variable[line].name; fields[1] = d->variable[line].changed ? "\bX" : " "; fields[2] = d->variable[line].output; fields[3] = 0; return fields;}static int xdebug_varlist_callback (CWidget * w, XEvent * x, CEvent * c){ Debug *d; d = (Debug *) w->hook; if (c->command == CK_Delete || c->command == CK_BackSpace) { xdebug_remove_variable (d, w->cursor); CRedrawFieldedTextbox ("debug_vars", 1); } if (c->command == CK_Toggle_Insert && !d->action && !d->n_commands) { char s[MAX_DEBUG_CMD_LEN]; if (d->variable[w->cursor].watch) { sprintf (s, "delete %d\n", d->variable[w->cursor].watch); xdebug_append_command (d, s, ACTION_WATCH, 0, w->cursor); } else { sprintf (s, "watch %s\n", d->variable[w->cursor].name); xdebug_append_command (d, s, ACTION_WATCH, 0, w->cursor); } } return 0;}static void xdebug_display_variable (Debug * d, char *message, int action){ char *p; int i; if (*message == '$') { p = message; message = strstr (message, "= "); if (message) message += 2; else message = p; } for (p = message, i = 0; *p && i < 255; p++, i++) { if (isspace (*p)) *p = ' '; else if (!isprint ((unsigned char) *p)) *p = '?'; } *p = '\0'; if (d->variable[d->last_variable_displayed].output) { d->variable[d->last_variable_displayed].changed = strcmp (message, d->variable[d->last_variable_displayed].output); free (d->variable[d->last_variable_displayed].output); } d->variable[d->last_variable_displayed++].output = (char *) strdup (message); if (action == ACTION_LASTVAR) { d->last_variable_displayed = 0; if (CIdent ("debug_vars")) { CRedrawFieldedTextbox ("debug_vars", 1); } else { Window win; CWidget *w; int x, y; win = CDrawMainWindow ("debug_vars.win", _ ("Variables")); CGetHintPos (&x, &y); CPushFont ("editor", 0); w = CDrawFieldedTextbox ("debug_vars", win, x, y, FONT_MEAN_WIDTH * 50 + 7, FONT_PIX_PER_LINE * 15 + 6, 0, 0, xdebug_get_line, 0, d); w->hook = d; CSetMovement ("debug_vars", POSITION_WIDTH | POSITION_HEIGHT); CAddCallback ("debug_vars", xdebug_varlist_callback); CSetMovement ("debug_vars.vsc", POSITION_HEIGHT | POSITION_RIGHT); CSetMovement ("debug_vars.hsc", POSITION_WIDTH | POSITION_BOTTOM); CSetSizeHintPos ("debug_vars.win"); CMapDialog ("debug_vars.win"); CSetWindowResizable ("debug_vars.win", FONT_MEAN_WIDTH * 20, FONT_PIX_PER_LINE * 10, 1600, 1200); CSetToolHint ("debug_vars", _ ("Use Del to delete from this list. Use Ins to\nmark variable as a watchpoint. This will cause\ndebugger to break if the variable changes.")); CPopFont (); } }}/* }}} variables *//* returns 1 on error */static void xdebug_break_point_special (Debug * d, char *cmd, char *editor, int line, int action){ CWidget *w; if ((w = CIdent (editor))) { char s[MAX_DEBUG_CMD_LEN]; sprintf (s, "%s %s:%d\n", cmd, w->editor->filename, line); xdebug_append_command (d, s, action, editor, line); }}static void xdebug_break_point (Debug * d, char *cmd, char *editor, int line){ xdebug_break_point_special (d, cmd, editor, line, ACTION_BREAKPOINT);}static void xdebug_set_break_points (Debug * d){ int i; for (i = 0; i < last_edit; i++) { struct _book_mark *b; if (!edit[i]->editor->book_mark) continue; for (b = edit[i]->editor->book_mark; b->prev; b = b->prev); /* rewind */ for (; b; b = b->next) if (b->line >= 0 && b->c == DEBUG_BREAKPOINT_COLOR) xdebug_break_point (d, "b", edit[i]->ident, b->line + 1); }}int goto_error (char *message, int raise_wm_window);static int xdebug_set_current (char *file, int line){ char s[MAX_DEBUG_CMD_LEN]; sprintf (s, "%s:%d", file, line); return goto_error (s, 0);}static int xdebug_goto_line (Debug * d, char *file, int line){ xdebug_cursor_bookmark_flush (); if (!xdebug_set_current (file, line)) { book_mark_insert (edit[current_edit]->editor, edit[current_edit]->editor->curs_line, DEBUG_CURRENT_COLOR); edit_render_keypress (edit[current_edit]->editor); return 0; } edit_render_keypress (edit[current_edit]->editor); return 1;}void goto_file_dialog (char *heading, char *tool_hint, char *text);static Debug debug_session;static void debug_finish (unsigned long x);void debug_callback (void){ static int animation = 0; static int refresh = 0; if ((animation++) % 50) { if (debug_session.action) { CSetColor (color_widget (4)); XFillArc (CDisplay, debug_session.w, CGC, debug_session.x, debug_session.y, debug_session.r * 2, debug_session.r * 2, (animation * 487) % (360 * 64) - 180 * 64, 90 * 64); XFillArc (CDisplay, debug_session.w, CGC, debug_session.x, debug_session.y, debug_session.r * 2, debug_session.r * 2, (animation * 487 + 180 * 64) % (360 * 64) - 180 * 64, 90 * 64); CSetColor (color_widget (13)); XFillArc (CDisplay, debug_session.w, CGC, debug_session.x, debug_session.y, debug_session.r * 2, debug_session.r * 2, (animation * 487 + 90 * 64) % (360 * 64) - 180 * 64, 90 * 64); XFillArc (CDisplay, debug_session.w, CGC, debug_session.x, debug_session.y, debug_session.r * 2, debug_session.r * 2, (animation * 487 + 270 * 64) % (360 * 64) - 180 * 64, 90 * 64); refresh = 1; } else if (refresh) { refresh = 0; CSetColor (COLOR_FLAT); XFillArc (CDisplay, debug_session.w, CGC, debug_session.x, debug_session.y, debug_session.r * 2, debug_session.r * 2, 0, 360 * 64); CSendExpose (debug_session.w, 0, 0, 1000, 1000); } }}static char *from_start (char *s, char *p, int n){ p = strstr (s, p); if (!p) return 0; if ((unsigned long) p > (unsigned long) s + n) return 0; return p;}static char *from_end (char *s, char *p, int n){ int i, l, k; if ((l = strlen (s)) >= (k = strlen (p)) + n) for (i = l - k; i >= l - k - n; i--) if (!memcmp (s + i, p, k)) return s + i; return 0;}static void xdebug_check_watch_point (Debug * d, char *m){ char *p, *q, *s, *r; CWidget *w; p = strstr (m, "\nHardware watchpoint "); if (!p) return; w = CIdent ("debug_vars"); if (w) { CSetTextboxPos (w, TEXT_SET_CURSOR_LINE, atoi (p + 12));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?