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 + -
显示快捷键?