[comp.sources.x] REPOST: v11i053: xxgdb - X front end for gdb, Part06/08

pierre@tce.COM (Pierre Willard) (03/07/91)

Submitted-by: pierre@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@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@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, &regs);
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	&regs) > 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@ora.com			argv@zipcode.com