REPOST: v11i053: xxgdb - X front end for gdb, Part06/08
Pierre Willard
pierre at tce.COM
Thu Mar 7 18:19:45 AEST 1991
Submitted-by: pierre at tce.COM (Pierre Willard)
Posting-number: Volume 11, Issue 53
Archive-name: xxgdb/part06
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 4 (of 8)."
# Contents: filemenu.c gdb_handler.c parser.c
# Wrapped by gilbert at phi on Tue Jan 15 13:12:47 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'filemenu.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'filemenu.c'\"
else
echo shar: Extracting \"'filemenu.c'\" \(13542 characters\)
sed "s/^X//" >'filemenu.c' <<'END_OF_FILE'
X/*****************************************************************************
X *
X * xdbx - X Window System interface to the dbx debugger
X *
X * Copyright 1989 The University of Texas at Austin
X * Copyright 1990 Microelectronics and Computer Technology Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of The University of Texas
X * and Microelectronics and Computer Technology Corporation (MCC) not be
X * used in advertising or publicity pertaining to distribution of
X * the software without specific, written prior permission. The
X * University of Texas and MCC makes no representations about the
X * suitability of this software for any purpose. It is provided "as is"
X * without express or implied warranty.
X *
X * THE UNIVERSITY OF TEXAS AND MCC DISCLAIMS ALL WARRANTIES WITH REGARD TO
X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF TEXAS OR MCC BE LIABLE FOR
X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author: Po Cheung
X * Created: March 10, 1989
X *
X *****************************************************************************
X *
X * xxgdb - X Window System interface to the gdb debugger
X *
X * Copyright 1990 Thomson Consumer Electronics, Inc.
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Thomson Consumer
X * Electronics (TCE) not be used in advertising or publicity pertaining
X * to distribution of the software without specific, written prior
X * permission. TCE makes no representations about the suitability of
X * this software for any purpose. It is provided "as is" without express
X * or implied warranty.
X *
X * TCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
X * SHALL TCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
X * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
X * SOFTWARE.
X *
X * Adaptation to GDB: Pierre Willard
X * XXGDB Created: December, 1990
X *
X *****************************************************************************/
X
X/* filemenu.c
X *
X * Construct a file menu (directory browser) which allows a user to go
X * up and down the directory tree, to select text files to display, and
X * to select executable files to debug. The file menu is popped up by
X * the 'file' command button.
X * Duane Voth (duanev at mcc.com) contributed to the layout of the file menu,
X * plus some code and ideas.
X *
X * changeDir(): Record the current working directory.
X * InList(): Select files to be displayed in the menu.
X * ScanDir(): Scan the directory and record selected filenames.
X * DisplayMenuFile(): Callback for the file menu.
X * CancelFileMenu(): Pop down the file menu.
X * SetUpFileMenu(): Create the file menu popupshell.
X * UpdateFileMenu(): Update entries in the file menu.
X * File(): Command callback for the 'file' command button.
X */
X
X#include <ctype.h>
X#include <X11/Xos.h>
X#include <sys/stat.h>
X#ifdef SUNOS4
X#include <dirent.h>
X#else
X#include <sys/dir.h>
X#endif
X#include "global.h"
X
X#define MAXCOLUMNS 8 /* max number of columns in file menu */
X#define FILES_PER_COL 10 /* # of files per column in file menu */
X
Xchar cwd[MAXPATHLEN]; /* current working directory of dbx */
Xstatic char fileMenuDir[MAXPATHLEN];/* current directory of file menu */
Xstatic char **filelist; /* list of file names in fileMenu */
Xstatic int nfiles = 0; /* number of files in filelist */
Xstatic Widget popupshell, /* parent of popup */
X popup, /* vpane widget containing file menu */
X fileMenu, /* list widget as file menu */
X fileMenuLabel; /* label widget as file menu label */
X
Xvoid File(), UpdateFileMenu();
X
X/* Change working directory to 'dir'.
X * For Berkeley dbx, modify static global variable, cwd, to keep track of
X * current working directory.
X * For Sun dbx, change working directory of dbx.
X */
Xstatic void changeDir(dir)
Xchar *dir;
X{
X char command[LINESIZ];
X
X#ifdef BSD
X int i;
X
X if (strcmp(dir, "./") == NULL)
X return;
X if (dir[0] == '/' || dir[0] == '~')
X strcpy(cwd, dir);
X if (strcmp(dir, "../") == NULL) {
X for (i=strlen(cwd); cwd[i] != '/' && i > 0; i--);
X cwd[i] = '\0';
X if (strcmp(cwd, "") == NULL)
X strcpy(cwd, "/");
X }
X else {
X sprintf(cwd, "%s/%s", cwd, dir);
X LASTCH(cwd) = '\0';
X }
X#else
X sprintf(command, "cd %s\n", dir);
X query_dbx(command);
X#endif
X}
X
X
X/* Determines if a directory entry should appear in the file menu.
X * The files included in the menu are :
X * .. (parent directory)
X * directories
X * text files
X * executable files
X */
Xstatic int InList(entry)
XDirectory *entry;
X{
X char pathname[LINESIZ];
X struct stat statbuf;
X
X if (strcmp(entry->d_name, ".") == NULL || /* ignore current directory */
X LASTCH(entry->d_name) == '~' || /* ignore Emacs backup files */
X (LASTCH(entry->d_name) == 'o' && SECLASTCH(entry->d_name) == '.'))
X /* ignore object files */
X return False;
X if (entry->d_name[0] == '.' && entry->d_name[1] != '.')
X return False; /* ignore hidden files */
X if (strcmp(cwd, "")) /* give full path name */
X sprintf(pathname, "%s/%s", cwd, entry->d_name);
X else
X strcpy(pathname, entry->d_name);
X if (stat(pathname, &statbuf) == -1)
X return False;
X if (statbuf.st_mode & S_IFDIR) { /* is directory */
X strcat(entry->d_name, "/");
X ++(entry->d_namlen);
X return True;
X }
X if (statbuf.st_mode & S_IEXEC) { /* is executable */
X strcat(entry->d_name, "*");
X ++(entry->d_namlen);
X return True;
X }
X#ifdef GDB
X /* for GDB, we only want directories and executable files */
X return FALSE;
X#else
X return True;
X#endif /* GDB */
X}
X
X
X/* Scans the working directory for files selected by InList(), sorted
X * alphabetically, and stored in an array of pointers to directory
X * entries called namelist.
X * The names of the selected files are stored in filelist.
X */
Xstatic void ScanDir(dir)
Xchar *dir;
X{
X extern alphasort();
X Directory **namelist;
X int i, j;
X
X nfiles = scandir(dir, &namelist, InList, alphasort);
X if (nfiles == -1) {
X UpdateMessageWindow("scandir: cannot open %s", dir);
X return;
X }
X if (filelist) {
X for (i=0; filelist[i]; i++)
X XtFree(filelist[i]);
X XtFree(filelist);
X }
X filelist = (char **) XtMalloc((nfiles+1) * sizeof(char *));
X i = 0;
X for (j=0; j<nfiles; j++) {
X filelist[i++] = XtNewString(namelist[j]->d_name);
X XtFree(namelist[j]);
X }
X filelist[i++] = NULL;
X XtFree(namelist);
X return;
X}
X
X
X/* Callback for the fileMenu list widget.
X * > if the selected item is a directory, display contents of that directory.
X * > (Sun dbx only) if the selected item is an executable file, issue the
X * debug command.
X * > if the selected item is a readable file, display the file.
X */
X/* ARGSUSED */
Xstatic void DisplayMenuFile(w, popupshell, call_data)
X Widget w;
X Widget popupshell;
X XawListReturnStruct *call_data;
X{
X char string[LINESIZ], *filename, command[LINESIZ];
X
X XtPopdown(popupshell);
X filename = call_data->string;
X if (filename == NULL) return;
X if (LASTCH(filename) == '/') {
X changeDir(filename);
X XtDestroyWidget(popupshell);
X UpdateFileMenu(); /* create new menu */
X File(); /* pop it up */
X }
X else if (LASTCH(filename) == '*') {
X UpdateMessageWindow("");
X#ifdef GDB
X /* for GDB, we send the commands : exec-file & symbol-file */
X
X /* (PW)21DEC90 : this button is special because it has to send
X TWO commands to GDB. We should wait for the prompt before
X sending the second command !.
X I think it is cleaner to send this 2nd command in the parser
X after it matches 'exec-file' command.
X But do that latter
X */
X
X strcpy(string, filename);
X LASTCH(string) = '\0';
X
X sprintf(command, "exec-file %s\n", string);
X send_command(command);
X AppendDialogText(command);
X
X Echo = True;
X Parse = True;
X Prompt = False;
X while (!Prompt)
X read_dbx();
X
X sprintf(command, "symbol-file %s\n", string);
X send_command(command);
X AppendDialogText(command);
X#else
X#ifndef BSD
X strcpy(string, filename);
X LASTCH(string) = '\0';
X sprintf(command, "debug %s\n", string);
X send_command(command);
X AppendDialogText(command);
X#endif
X#endif /* GDB */
X }
X else {
X UpdateMessageWindow("");
X#ifndef GDB
X sprintf(command, "file %s\n", filename);
X send_command(command);
X AppendDialogText(command);
X#endif /* GDB */
X }
X}
X
X
X/* Callback to popdown the file menu
X */
X/* ARGSUSED */
Xstatic void CancelFileMenu(w, popupshell, call_data)
X Widget w;
X Widget popupshell;
X caddr_t call_data;
X{
X XtPopdown(popupshell);
X UpdateMessageWindow("");
X}
X
X
X/* Creates a popup shell with its child being a vpane widget containing
X * a file menu label, a file menu containing file names returned from
X * ScanDir(), and a cancel command button.
X * When an item in the list is selected, DisplayMenuFile is called.
X */
Xstatic void SetUpFileMenu(dir)
Xchar *dir;
X{
X Widget cancelButton;
X Arg args[MAXARGS];
X Cardinal n;
X char menulabel[LINESIZ];
X int ncolumns;
X
X n = 0;
X popupshell = XtCreatePopupShell("File Directory", transientShellWidgetClass,
X toplevel, args, n);
X
X n = 0;
X popup = XtCreateManagedWidget("popup", panedWidgetClass, popupshell,
X args, n);
X ScanDir(dir);
X strcpy(fileMenuDir, dir);
X
X n = 0;
X sprintf(menulabel, " %s ", dir);
X XtSetArg(args[n], XtNlabel, (XtArgVal) menulabel); n++;
X XtSetArg(args[n], XtNjustify, (XtArgVal) XtJustifyCenter); n++;
X fileMenuLabel = XtCreateManagedWidget("fileMenuLabel", labelWidgetClass,
X popup, args, n);
X
X n = 0;
X ncolumns = nfiles/FILES_PER_COL + 1;
X ncolumns = MIN(ncolumns, MAXCOLUMNS);
X XtSetArg(args[n], XtNlist, filelist); n++;
X XtSetArg(args[n], XtNverticalList, True); n++;
X XtSetArg(args[n], XtNdefaultColumns, (XtArgVal) ncolumns); n++;
X fileMenu = XtCreateManagedWidget("fileMenu", listWidgetClass,
X popup, args, n);
X XtAddCallback(fileMenu, XtNcallback, DisplayMenuFile, popupshell);
X
X n = 0;
X XtSetArg(args[n], XtNresize, False); n++;
X XtSetArg(args[n], XtNlabel, "CANCEL"); n++;
X cancelButton = XtCreateManagedWidget("cancelButton", commandWidgetClass,
X popup, args, n);
X XtAddCallback(cancelButton, XtNcallback, CancelFileMenu, popupshell);
X
X DisableWindowResize(fileMenuLabel);
X DisableWindowResize(cancelButton);
X}
X
X
X/* This routine is called when there is a a change in current directory.
X * It destroys the existing popup shell and creates a new file menu based
X * on the new current directory. A new directory list is created.
X */
Xstatic void UpdateFileMenu()
X{
X SetUpFileMenu(cwd);
X#ifdef GDB
X query_dbx("info directories\n");
X#else
X query_dbx("use\n");
X#endif /* GDB */
X}
X
X
X/* File command button callback.
X */
X/* ARGSUSED */
Xvoid File(w, client_data, call_data)
X Widget w;
X caddr_t client_data;
X caddr_t call_data;
X{
X Arg args[MAXARGS];
X Cardinal n;
X Position x, y, x_offset;
X Dimension fileMenu_width, fileMenuLabel_width, border_width,
X width, dialog_width;
X
X XDefineCursor(display, XtWindow(toplevel), watch);
X XDefineCursor(display, XtWindow(sourceWindow), watch);
X XDefineCursor(display, XtWindow(dialogWindow), watch);
X XFlush(display);
X if (strcmp(fileMenuDir, cwd))
X UpdateFileMenu();
X
X n = 0;
X XtSetArg(args[n], XtNwidth, &fileMenu_width); n++;
X XtSetArg(args[n], XtNborderWidth, &border_width); n++;
X XtGetValues(fileMenu, args, n);
X
X n = 0;
X XtSetArg(args[n], XtNwidth, &fileMenuLabel_width); n++;
X XtGetValues(fileMenuLabel, args, n);
X
X n = 0;
X XtSetArg(args[n], XtNwidth, &dialog_width); n++;
X XtGetValues(dialogWindow, args, n);
X
X width = MAX(fileMenu_width, fileMenuLabel_width);
X x_offset = (Position) (dialog_width - width - border_width);
X XtTranslateCoords(dialogWindow, x_offset, 0, &x, &y);
X
X x = MAX(0, x);
X y = MAX(0, y);
X
X n = 0;
X XtSetArg(args[n], XtNx, x); n++;
X XtSetArg(args[n], XtNy, y); n++;
X XtSetValues(popupshell, args, n);
X XtPopup(popupshell, XtGrabNonexclusive);
X
X#ifdef GDB
X UpdateMessageWindow("Select an executable file or a directory");
X#else
X UpdateMessageWindow("Select a file or directory");
X#endif /* GDB */
X XUndefineCursor(display, XtWindow(toplevel));
X XUndefineCursor(display, XtWindow(sourceWindow));
X XUndefineCursor(display, XtWindow(dialogWindow));
X}
END_OF_FILE
if test 13542 -ne `wc -c <'filemenu.c'`; then
echo shar: \"'filemenu.c'\" unpacked with wrong size!
fi
# end of 'filemenu.c'
fi
if test -f 'gdb_handler.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'gdb_handler.c'\"
else
echo shar: Extracting \"'gdb_handler.c'\" \(14177 characters\)
sed "s/^X//" >'gdb_handler.c' <<'END_OF_FILE'
X/*****************************************************************************
X *
X * xdbx - X Window System interface to the dbx debugger
X *
X * Copyright 1989 The University of Texas at Austin
X * Copyright 1990 Microelectronics and Computer Technology Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of The University of Texas
X * and Microelectronics and Computer Technology Corporation (MCC) not be
X * used in advertising or publicity pertaining to distribution of
X * the software without specific, written prior permission. The
X * University of Texas and MCC makes no representations about the
X * suitability of this software for any purpose. It is provided "as is"
X * without express or implied warranty.
X *
X * THE UNIVERSITY OF TEXAS AND MCC DISCLAIMS ALL WARRANTIES WITH REGARD TO
X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF TEXAS OR MCC BE LIABLE FOR
X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author: Po Cheung
X * Created: March 10, 1989
X *
X *****************************************************************************
X *
X * xxgdb - X Window System interface to the gdb debugger
X *
X * Copyright 1990 Thomson Consumer Electronics, Inc.
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Thomson Consumer
X * Electronics (TCE) not be used in advertising or publicity pertaining
X * to distribution of the software without specific, written prior
X * permission. TCE makes no representations about the suitability of
X * this software for any purpose. It is provided "as is" without express
X * or implied warranty.
X *
X * TCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
X * SHALL TCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
X * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
X * SOFTWARE.
X *
X * Adaptation to GDB: Pierre Willard
X * XXGDB Created: December, 1990
X *
X *****************************************************************************/
X
X/* gdb_handler.c
X *
X * WARNING : gdb_handler.c is included by handler.c for GDB.
X *
X * Contain action handlers for the parser to invoke upon a dbx command.
X *
X * updown_handler(): Update file, line label, updown arrow position.
X * debug_handler(): Check directory use list, display main source file.
X * pwd_handler(): Update current working directory.
X * search_handler(): Adjust source file to display matched line.
X * display_info_handler(): Update display window.
X * break_handler(): Place stop sign on line or function or address specified.
X * info_dir_handler(): Update search directory list.
X * directory_handler(): Update search directory list.
X * list_handler(): Adjust source file to display result.
X * info_line_handler(): Update current file.
X * delete_handler(): Remove stop sign.
X * display_handler(): Update display window.
X * info_break_handler(): Update stop signs.
X * cd_handler(): Record current working directory.
X * frame_curr_handler(): Update current function name.
X * exec_handler(): Update file, line label, arrow position.
X * done_handler(): Progrm execution completed, clear breakpoints
X * source_handler(): Exec commands of source file specified.
X * query_dbx_echo(): Send command with echo on.
X */
X
X
Xvoid query_dbx_echo();
X
X/*
X * Display an outlined arrow to locate the calling routine in a stack
X * frame. BSD and SUN dbx have slightly different output semantics here.
X * The appropriate file with the calling routine is displayed and the
X * file variable is set accordingly.
X */
Xvoid updown_handler()
X{
X char command[LINESIZ], *func, *file;
X int line;
X
X line = Token.line;
X func = XtNewString(Token.func);
X#ifdef MIPS
X LoadCurrentFile();
X#endif
X#ifdef BSD
X file = GetPathname(Token.file);
X#else
X if (line <= 0) line = 1;
X LoadCurrentFile();
X if (displayedFile)
X file = displayedFile->pathname;
X#endif
X
X if (line <= 0 || func == NULL || file == NULL)
X {
X XtFree(func);
X return;
X }
X
X if (displayedFile && strcmp(file, displayedFile->pathname)) {
X LoadFile(file);
X }
X updown.line = line;
X strcpy(updown.func, func);
X if (displayedFile)
X strcpy(updown.file, displayedFile->pathname);
X AdjustText(line);
X XtFree(func);
X}
X
X/* ARGSUSED */
Xvoid debug_handler()
X{
X /* debug_handler is executed at start-up and with 'symbol-file' command */
X
X query_dbx("set screensize 0\n");
X query_dbx("set prettyprint on\n");
X query_dbx("info directories\n");
X
X displayedFile = NULL; /* force reloading of source file */
X
X /* here we use query_dbx_echo instead of query_dbx so that any
X error message will be displayed ! */
X
X query_dbx_echo("list ,main\n"); /* tell gdb to use main file
X and get line number of main(). (,main will end at main) */
X
X if (LoadCurrentFile() == 0)
X {
X arrow.line = 0; /* clear arrow sign */
X updown.line = 0; /* clear updown sign */
X bomb.line = 0; /* clear bomb sign */
X UpdateArrow(displayedFile);
X UpdateUpdown(displayedFile);
X UpdateBomb(displayedFile);
X ClearStops();
X UpdateStops(displayedFile);
X }
X
X UpdateMessageWindow("Ready for execution");
X query_dbx("display\n"); /* clear display window */
X}
X
X/* ARGSUSED */
Xvoid pwd_handler(s)
Xchar *s;
X{
X strcpy(cwd, (char *)strtok(s, "\n"));
X}
X
X/* ARGSUSED */
Xvoid search_handler()
X{
X AdjustText(Token.line);
X}
X
X/* ARGSUSED */
X/* Show output on the display window.
X * If output is null but the display window is managed, replace contents of
X * the display window with the null string.
X */
Xvoid display_info_handler()
X{
X Arg args[MAXARGS];
X Cardinal n;
X
X if (!Token.display || strcmp(Token.display, "") == NULL) {
X if (!XtIsManaged(displayWindow))
X return;
X else {
X XtFree(Token.display);
X Token.display = XtNewString("");
X }
X }
X if (!XtIsManaged(displayWindow)) {
X XtManageChild(separator);
X XtManageChild(displayWindow);
X }
X n = 0;
X XtSetArg(args[n], XtNstring, (XtArgVal) Token.display); n++;
X XtSetValues(displayWindow, args, n);
X XtFree(Token.display);
X Token.display = 0; /*(PW)14JAN91 */
X}
X
X/* Place a stop sign next to the line specified on the source file window
X * if it is to be viewable.
X */
Xvoid break_handler()
X{
Xchar * file;
Xint line;
Xint stop;
X
X if (Token.stop == 0 || Token.line == 0 || Token.file == 0)
X return;
X
X line = Token.line;
X stop = Token.stop;
X
X if (Token.stop >= 256) /* see MAXSTOPS in signs.c */
X {
X fprintf(stderr,"Too many breakpoints\n");
X return;
X }
X
X /* load & display file if none is displayed */
X
X file = GetPathname(Token.file);
X
X if (file == NULL)
X return; /* (PW)11JAN91 */
X
X if (displayedFile == NULL)
X {
X LoadFile(file);
X AdjustText(line);
X }
X
X stops[stop].file = file;
X stops[stop].line = line;
X stops[stop].tag = 0;
X nstops = stop;
X
X /* display breakpoint sign if file is displayed */
X
X if (displayedFile)
X {
X if (!strcmp(file, displayedFile->pathname))
X DisplayStop(displayedFile, line);
X }
X}
X
X/* info directories
X */
Xvoid info_dir_handler()
X{
X if (Token.file)
X MakeDirList(Token.file);
X}
X
X/* ARGSUSED */
Xvoid directory_handler(output)
Xchar *output;
X{
X /* Note : for GDB, the 'directory' command with no
X parameter will reset search directories to current
X directory only. GDB requires confirmation */
X
X query_dbx("info directories\n");
X}
X
Xvoid list_handler()
X{
X int line;
X
X line = Token.line;
X
X if (line)
X {
X /* We will display the last line listed.
X Since we used 'list ,main' we will effectively display main in that case. */
X
X LoadCurrentFile();
X AdjustText(line);
X }
X else
X {
X AppendDialogText("Error list command\n");
X bell(0);
X }
X}
X
X/* ARGSUSED */
Xvoid info_line_handler() /* Command was 'info line' */
X{
X if (Token.file)
X strcpy(CurrentFile, Token.file);
X else
X strcpy(CurrentFile, "");
X}
X
X/*
X * Delete handler remove the stop specified and undisplayed the stopsign
X * if it's visible.
X * It calls the dbx status command to find out what stops are left, and
X * then update the array of stops accordingly.
X */
X/* ARGSUSED */
X
Xvoid delete_handler()
X{
X query_dbx("info break\n"); /* update breakpoints */
X}
X
Xvoid display_handler() /* display or undisplay */
X{
X query_dbx("display\n"); /* update display */
X}
X
X/*
X(gdb) info break
XBreakpoints:
XNum Enb Address Where
X#1 y 0x000022f4 in main (pw.c line 34)
X#2 y 0x000022a0 in foo (pw.c line 5)
X(gdb) info break
XNo breakpoints.
X*/
X
Xvoid info_break_handler(output_string)
Xchar *output_string;
X{
Xint i;
Xint line;
Xchar c;
X
X if (!output_string)
X return;
X
X while(*output_string)
X {
X if (*(output_string++) == '#')
X {
X if (sscanf(output_string, "%d %c", &i,&c) == 2)
X if (i > 0 && i <= nstops && stops[i].line > 0 && c == 'y')
X stops[i].tag = 1;
X }
X }
X
X for (i=1; i<=nstops; i++)
X if (stops[i].line > 0)
X {
X if (stops[i].tag)
X stops[i].tag = 0;
X else
X {
X line = stops[i].line;
X stops[i].line = 0;
X stops[i].file = NULL;
X if (LineToStop_no(line) == 0)
X RemoveStop(line);
X }
X }
X}
X
X/* ARGSUSED */
Xvoid cd_handler(s)
Xchar *s;
X{
X strcpy(cwd,s);
X}
X
X/* this handler justs update the function name.
XBecause the function name is not always displayed
Xafter next,step ... */
X
Xstatic char* funcname = 0;
X
Xvoid frame_curr_handler()
X{
X if (Token.func == NULL)
X return;
X
X if (funcname)
X {
X XtFree(funcname);
X funcname = 0;
X }
X
X funcname = XtNewString(Token.func);
X}
X
X/* Handle dbx output of run, cont, next, step, return commands.
X * Result of output parsing is returned in a set of tokens.
X *
X * If message is not 0, this is an important message and should
X * be displayed instead of Token.mesg.
X * This message will hold the Bus error and segmentation violation errors.
X * signal is the signal number received (if any).
X */
Xvoid exec_handler(message,signal)
Xchar *message;
Xint signal;
X{
X int line, status;
X char *func;
X
X /* Print "stopped in ..." line in message window
X * Adjust text displayed
X */
X if (Token.line == 0)
X return;
X
X if (message)
X UpdateMessageWindow(message);
X else
X UpdateMessageWindow(Token.mesg);
X
X line = Token.line;
X func = (Token.func) ? XtNewString(Token.func) : 0;
X
X#ifdef MIPS
X status = LoadCurrentFile();
X#else
X if (Token.file)
X status = LoadFile(Token.file);
X#endif
X
X#ifndef BSD
X display_info_handler(); /* uses Token.display ! */
X#endif
X
X /* because of tbreak, we have to call info break here */
X
X query_dbx("info break\n"); /* update breakpoints */
X
X if (func == NULL)
X {
X query_dbx("frame\n"); /* this will just update funcname (see frame_curr_handler) */
X func = funcname;
X if (func == NULL)
X return;
X funcname = 0; /* tell frame_curr_handler WE are going to XtFree it */
X }
X
X arrow.line = line; /* update arrow sign position */
X strcpy(arrow.func, func);
X
X updown.line = 0; /* remove updown, if any */
X if (displayedFile) {
X strcpy(arrow.file, displayedFile->pathname);
X }
X
X /* Display bomb sign if segmentation fault occurs in source code */
X
X if (status != -1 && message && signal == SIGSEGV) {
X arrow.line = 0;
X bomb.line = line;
X if (func)
X strcpy(bomb.func, func);
X if (displayedFile) strcpy(bomb.file, displayedFile->pathname);
X }
X else
X bomb.line = 0;
X
X AdjustText(line);
X XtFree(func);
X}
X
X/* Remove all the arrow and updown signs, print message, then
X * change the file variable to the file name displayed.
X */
Xvoid done_handler(message,signal)
Xchar *message;
Xint signal;
X{
X char command[LINESIZ];
X
X arrow.line = 0;
X updown.line = 0;
X UpdateArrow(displayedFile);
X UpdateUpdown(displayedFile);
X UpdateMessageWindow("Ready for execution");
X}
X
X/* WARNING : source_handler() is NOT called by the parser.
XIt is called by gdb_source_command() in gdb_parser.c.
XThis is because 'source' command is NEVER sent to gdb,
Xinstead xxgdb sends the commands in the specified file
Xone by one. */
X
Xvoid source_handler()
X{
Xchar *file;
XFILE *fp;
Xchar s[LINESIZ];
X
X if (!Token.file || strcmp(Token.file, "") == NULL)
X {
X XtFree(Token.file);
X Token.file = XtNewString(".gdbinit"); /* default is .gdbinit */
X }
X
X file = GetPathname(Token.file);
X
X if (file == NULL)
X return; /* (PW)11JAN91 */
X
X if (fp = fopen(file, "r"))
X {
X while (fgets(s, LINESIZ, fp))
X {
X /* DO NOT SEND \n and Take care of source command */
X if ((*s != '#') && strcmp(s,"\n") && (!gdb_source_command(s,TRUE)))
X {
X write_dbx(s);
X insert_command(s);
X AppendDialogText(s);
X Prompt = False;
X while (!Prompt)
X read_dbx();
X }
X }
X close(fp);
X }
X}
X
X/* Sends a command to dbx and read the corresponding output, directly
X * invoking the Xt input procedure, read_dbx().
X *
X * Same as query_dbx() in dbx.c except that Echo = True.
X */
Xvoid query_dbx_echo(command)
Xchar *command;
X{
X write_dbx(command);
X insert_command(command);
X
X Echo = True;
X Prompt = False;
X while (!Prompt)
X read_dbx();
X
X Parse = True; /* Always reset Parse and Echo to True */
X Echo = True;
X}
END_OF_FILE
if test 14177 -ne `wc -c <'gdb_handler.c'`; then
echo shar: \"'gdb_handler.c'\" unpacked with wrong size!
fi
# end of 'gdb_handler.c'
fi
if test -f 'parser.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'parser.c'\"
else
echo shar: Extracting \"'parser.c'\" \(12874 characters\)
sed "s/^X//" >'parser.c' <<'END_OF_FILE'
X/*****************************************************************************
X *
X * xdbx - X Window System interface to the dbx debugger
X *
X * Copyright 1989 The University of Texas at Austin
X * Copyright 1990 Microelectronics and Computer Technology Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of The University of Texas
X * and Microelectronics and Computer Technology Corporation (MCC) not be
X * used in advertising or publicity pertaining to distribution of
X * the software without specific, written prior permission. The
X * University of Texas and MCC makes no representations about the
X * suitability of this software for any purpose. It is provided "as is"
X * without express or implied warranty.
X *
X * THE UNIVERSITY OF TEXAS AND MCC DISCLAIMS ALL WARRANTIES WITH REGARD TO
X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF TEXAS OR MCC BE LIABLE FOR
X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author: Po Cheung
X * Created: March 10, 1989
X *
X *****************************************************************************
X *
X * xxgdb - X Window System interface to the gdb debugger
X *
X * Copyright 1990 Thomson Consumer Electronics, Inc.
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Thomson Consumer
X * Electronics (TCE) not be used in advertising or publicity pertaining
X * to distribution of the software without specific, written prior
X * permission. TCE makes no representations about the suitability of
X * this software for any purpose. It is provided "as is" without express
X * or implied warranty.
X *
X * TCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
X * SHALL TCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
X * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
X * SOFTWARE.
X *
X * Adaptation to GDB: Pierre Willard
X * XXGDB Created: December, 1990
X *
X *****************************************************************************/
X
X/* parser.c:
X *
X * Parse output messages from dbx using regular expression pattern matching,
X * and take appropriate action.
X *
X * compile(): Compile the regular expressions in a table.
X * match(): Try to best match a given string with the regular
X * expressions found in the table and return an index.
X * parser_init(): Initialization.
X * parse(): Parse the dbx output and invoke the appropriate action
X * handler.
X * filter(): Modify the dbx output before it gets displayed on the
X * dialog window.
X * query_dbx(): Send a query command to dbx and process it.
X */
X
X#include "global.h"
X#include "regex.h"
X#ifdef GDB
X#include "gdb_regex.h"
X#else
X#ifdef BSD
X#ifdef MIPS
X#include "mips_regex.h"
X#else
X#include "bsd_regex.h"
X#endif
X#else
X#include "sun_regex.h"
X#endif
X#endif /* GDB */
X
X#define BYTEWIDTH 8
X#define RE_BUFFER 100
X
XTokens Token; /* gloabl token structure */
XBoolean Parse = True; /* Parse flag for parse routine */
X
X/*
X * Compile all the regular expression patterns in a pattern table.
X * A pattern table is an array of pattern records.
X * Each pattern record consists of a regular
X * expression, a buffer for the to-be-compiled regular expression,
X * and an array to associate a given token with a matched register number.
X */
Xstatic void compile(patternTable)
XPatternRec *patternTable;
X{
X PatternRec *p;
X char fastmap[(1 << BYTEWIDTH)];
X int i;
X
X for (i=0; patternTable[i].pat; i++) {
X p = &patternTable[i];
X p->buf = (struct re_pattern_buffer *)
X XtMalloc (sizeof (struct re_pattern_buffer));
X p->buf->allocated = RE_BUFFER;
X p->buf->buffer = (char *) XtMalloc (p->buf->allocated);
X p->buf->fastmap = fastmap;
X p->buf->translate = NULL;
X re_compile_pattern(p->pat, strlen(p->pat), p->buf);
X re_compile_fastmap(p->buf);
X }
X}
X
X/*
X * This routine tries to match a given string with each regular
X * expression in a given pattern table. The best match is found, and
X * the function returns an index to the pattern table.
X */
X#ifndef GDB /* for GDB, match is called from gdb_parser.c */
Xstatic
X#endif
Xint match(patternTable, string, type)
X PatternRec *patternTable;
X char *string;
X int type;
X{
X struct re_registers regs;
X int m, bestmatch = -1, index = -1, i, j, r, start, n;
X char *s;
X
X if (strcmp(string, "") == NULL) return -1;
X for (i=0; patternTable[i].pat; i++) {
X if (type != C_ANY && type != i)
X continue;
X m = re_match(patternTable[i].buf, string, strlen(string), 0, ®s);
X if (m == -2 ) { /* match error - failure stack overflow */
X#ifdef GDB
X fprintf(stderr, "xxgdb error: regular expression matching failed \
X(failure stack overflow)\n");
X#else
X fprintf(stderr, "xdbx error: regular expression matching failed \
X(failure stack overflow)\n");
X#endif
X return (-1);
X }
X if (m > bestmatch) {
X bestmatch = m;
X index = i;
X#ifdef GDB
X /* for GDB, free memory (if not done earlier) */
X XtFree(Token.mesg);
X XtFree(Token.file);
X XtFree(Token.func);
X XtFree(Token.display);
X#endif /* GDB */
X Token.mesg = Token.file = Token.func = Token.display = NULL;
X Token.line = Token.stop = 0;
X for (j=0; j<NTOKENS; j++) {
X if ((r = patternTable[i].reg_token[j]) >= 0) {
X start = regs.start[r];
X if ((n = regs.end[r] - start) > 0) {
X#ifdef GDB
X /* The following error could happen if the pattern table is not correct,
X better test it here.. */
X
X if ( n > strlen(string)) /* Something is wrong here ! */
X {
X fprintf(stderr,"Error match() : n = %d is too big\n",n);
X n = 0;
X }
X#endif /* GDB */
X s = (char *) XtMalloc ((n+1) * sizeof(char));
X strncpy(s, string+start, n);
X s[n] = '\0';
X switch (j) {
X case TK_MESG: Token.mesg = s; break;
X case TK_STOP: Token.stop = atoi(s); XtFree(s); break;
X case TK_FUNC: Token.func = s; break;
X case TK_LINE: Token.line = atoi(s); XtFree(s); break;
X case TK_FILE: Token.file = s; break;
X case TK_DISP: Token.display = s; break;
X }
X }
X }
X }
X }
X }
X return index;
X}
X
X/* Compile the regular expressions in the output and command pattern tables. */
X
Xvoid parser_init()
X{
X compile(output_pattern);
X compile(command_pattern);
X compile(dataPattern);
X}
X
X
X#ifdef GDB
X
X#include "gdb_parser.c"
X
X#else /*>>>>>>>>>> ALL THE FOLLOWING IS NOT COMPILED FOR GDB <<<<<<<<<<<<<<<<<<<*/
X
X/* This routine first parses the command string.
X * If the command is one of run, cont, next, step, stop at, stop in,
X * where, up, or down, it parses the dbx output to decide what action
X * to take and dispatch it to one of the handlers.
X * For other commands, the appropriate handler is called.
X *
X * !!! This routine has to be re-entrant.
X */
Xvoid parse(output, command)
Xchar *output;
Xchar *command;
X{
X int command_type;
X char *output_string;
X
X if (debug) {
X fprintf(stderr, "parse(output = %s, command = %s)\n", output, command);
X }
X
X /* Make a local copy of `output' and use that instead */
X output_string = XtNewString(output);
X if (output) strcpy(output, "");
X
X if (!command) {
X if (match(output_pattern, output_string, O_DEBUG) != -1)
X debug_handler();
X debug_init();
X return;
X }
X if (!Parse)
X return;
X
X command_type = match(command_pattern, command, C_ANY);
X switch (command_type) {
X case C_EXEC:
X if (match(output_pattern, output_string, O_EXEC) != -1)
X exec_handler();
X else if (match(output_pattern, output_string, O_DONE) != -1)
X done_handler();
X else
X bell(0);
X break;
X case C_STOPAT:
X if (match(output_pattern, output_string, O_STOPAT) != -1)
X stop_at_handler();
X else
X bell(0);
X break;
X case C_STOPIN:
X if (match(output_pattern, output_string, O_STOPIN) != -1)
X stop_in_handler();
X else
X bell(0);
X break;
X case C_UPDOWN:
X if (match(output_pattern, output_string, O_UPDOWN) != -1)
X updown_handler();
X else
X bell(0);
X break;
X case C_SEARCH:
X if (match(output_pattern, output_string, O_SEARCH) != -1)
X search_handler();
X else
X bell(0);
X break;
X case C_DELETE:
X delete_handler();
X break;
X case C_FILE:
X if (match(output_pattern, output_string, O_FILE) != -1)
X file_handler(); /* command was 'file' */
X else
X LoadCurrentFile(); /* command was 'file ...' */
X break;
X case C_LIST:
X if (match(output_pattern, output_string, O_LIST) != -1)
X list_handler();
X else
X bell(0);
X break;
X case C_FUNC:
X#ifdef MIPS
X if (match(output_pattern, output_string, O_FUNC) != -1)
X#else
X if (strcmp(output_string, "") == NULL)
X#endif
X func_handler();
X else
X bell(0);
X break;
X case C_USE:
X use_handler(output_string);
X break;
X
X#ifndef BSD
X case C_PRINT:
X if (match(output_pattern, output_string, O_PRINT) != -1)
X print_handler(output_string);
X else
X bell(0);
X break;
X case C_DEBUG:
X if (match(output_pattern, output_string, O_DEBUG) != -1)
X debug_handler();
X else
X bell(0);
X break;
X case C_CD:
X if (strcmp(output_string, "") == NULL)
X cd_handler();
X else
X bell(0);
X break;
X case C_PWD:
X pwd_handler(output_string);
X break;
X case C_DISPLAY:
X if (strcmp(output_string, "") == NULL ||
X match(output_pattern, output_string, O_PRINT) != -1)
X display_handler();
X else
X bell(0);
X break;
X#endif
X#ifdef BSD
X case C_STATUS:
X break;
X#endif
X
X default:
X break;
X }
X XtFree(output_string);
X}
X
X/* This function edits the dbx output so that unnecessary information is
X * not displayed on the dialog window.
X * It filters away the some output returned by the execution commands;
X * output from the search commands, and the display command.
X * On Sun dbx, it also filters away part of the output returned by the
X * up and down commands.
X */
Xvoid filter(string, output, command)
Xchar *string, *output, *command;
X{
X struct re_registers regs;
X char *p;
X int r;
X static Boolean deleteRest = False;
X int command_type = -1;
X
X if (output == NULL || strcmp(output, "") == NULL)
X return;
X
X
X#ifdef BSD
X if (!command) {
X AppendDialogText(string);
X return;
X }
X#endif
X
X if (command)
X command_type = match(command_pattern, command, C_ANY);
X if (command_type == C_EXEC) {
X if (re_match(output_pattern[O_EXEC].buf, string, strlen(string), 0,
X ®s) > 0) {
X r = output_pattern[O_EXEC].reg_token[TK_MESG];
X for (p=string+regs.start[r]; p!=string && *(p-1) != '\n'; p--);
X strcpy(p, "");
X if (!Prompt)
X deleteRest = True;
X }
X else if (deleteRest) {
X strcpy(string, "");
X if (Prompt)
X deleteRest = False;
X }
X AppendDialogText(string);
X return;
X }
X
X if (Prompt) {
X char *s;
X
X s = XtNewString(output);
X switch (command_type) {
X#ifndef BSD
X case C_UPDOWN:
X if (match(output_pattern, s, O_UPDOWN) != -1)
X strcpy(s, Token.mesg);
X break;
X case C_DISPLAY:
X if (match(output_pattern, s, O_PRINT) != -1)
X strcpy(s, "");
X break;
X#endif
X#ifdef MIPS
X case C_UPDOWN:
X if (match(output_pattern, s, O_UPDOWN) != -1)
X strcpy(s, Token.mesg);
X strcat(s, "\n");
X break;
X case C_FUNC:
X if (match(output_pattern, s, O_FUNC) != -1)
X strcpy(s, "");
X break;
X#endif
X case C_SEARCH:
X if (match(output_pattern, s, O_SEARCH) != -1)
X strcpy(s, "");
X break;
X case C_LIST:
X if (match(output_pattern, s, O_LIST) != -1)
X strcpy(s, "");
X break;
X default:
X s = XtNewString(string); /* append 'string' only */
X break;
X }
X AppendDialogText(s);
X XtFree(s);
X }
X else {
X switch (command_type) {
X#ifndef BSD
X case C_UPDOWN:
X case C_DISPLAY:
X#endif
X#ifdef MIPS
X case C_UPDOWN:
X case C_FUNC:
X#endif
X case C_SEARCH:
X case C_LIST:
X break;
X default:
X AppendDialogText(string);
X break;
X }
X }
X}
X#endif /* NOT GDB */
END_OF_FILE
if test 12874 -ne `wc -c <'parser.c'`; then
echo shar: \"'parser.c'\" unpacked with wrong size!
fi
# end of 'parser.c'
fi
echo shar: End of archive 4 \(of 8\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 8 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Dan Heller
------------------------------------------------
O'Reilly && Associates Z-Code Software
Senior Writer President
argv at ora.com argv at zipcode.com
More information about the Comp.sources.x
mailing list