/*****************************************************************************
*
* xdbx - X Window System interface to the dbx debugger
*
* Copyright 1989 The University of Texas at Austin
* Copyright 1990 Microelectronics and Computer Technology Corporation
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of The University of Texas
* and Microelectronics and Computer Technology Corporation (MCC) not be
* used in advertising or publicity pertaining to distribution of
* the software without specific, written prior permission. The
* University of Texas and MCC makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* THE UNIVERSITY OF TEXAS AND MCC DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF TEXAS OR MCC BE LIABLE FOR
* ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Po Cheung
* Created: March 10, 1989
*
*****************************************************************************
*
* xxgdb - X Window System interface to the gdb debugger
*
* Copyright 1990,1993 Thomson Consumer Electronics, Inc.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of Thomson Consumer
* Electronics (TCE) not be used in advertising or publicity pertaining
* to distribution of the software without specific, written prior
* permission. TCE makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
*
* TCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
* SHALL TCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*
* Adaptation to GDB: Pierre Willard
* XXGDB Created: December, 1990
*
*****************************************************************************/
/* handler.c
*
* Contain action handlers for the parser to invoke upon a dbx command.
*
* TextSetTopPosition(): Set the top character position of text displayed
* AdjustText(): Adjust the portion of text displayed.
* exec_handler(): Update file, line label, arrow position.
* done_handler(): Progrm execution completed, clear breakpoints
* stop_at_handler(): Place stop sign on line specified.
* stop_in_handler(): Place stop sign on function specified.
* updown_handler(): Update file, line label, updown arrow position.
* delete_handler(): Remove stop sign.
* func_handler(): Display function, if specified.
* file_handler(): Display file, if specified.
* debug_handler(): Check directory use list, display source file.
* cd_handler(): Record current working directory.
* use_handler(): Record directory paths.
* search_handler(): Adjust source file to display matched line.
* list_handler(); Adjust source file to display result.
* display_handler(): Display results in display window.
*/
#include <ctype.h>
#include "global.h"
#ifdef BSD
#define BRACKET "[%d]"
#else
#define BRACKET "(%d)"
#endif
#ifndef GDB
Boolean Echo = True; /* display dbx output if true */
static Boolean Skip_func_handler = False;
#endif
/* Display text starting from the top position specified by pos */
void TextSetTopPosition(w, pos)
Widget w;
XawTextPosition pos;
{
Arg args[MAXARGS];
Cardinal n;
n = 0;
XtSetArg(args[n], XtNdisplayPosition, (XtArgVal) pos); n++;
XtSetValues(w, args, n);
}
/*
* Adjust text so that 'line' will fall into the viewable part of the
* source window.
* Arrows, stop signs, and line label are updated accordingly.
*/
void AdjustText(line)
int line;
{
FileRec *file;
int nlines = 0;
int i;
XawTextPosition pos;
if ((file = displayedFile) == NULL || line <= 0) return;
file->currentline = line;
if (line < file->topline || line > file->bottomline ) {
/* Position line about 30% from the top */
nlines = file->lines*0.3;
if (line < nlines) /* near top */
file->topline = 1;
else if (line > file->lastline - nlines) /* near bottom */
file->topline = MAX(file->lastline - file->lines + 1, 1);
else
file->topline = line - nlines;
file->bottomline = MIN(file->topline + file->lines - 1, file->lastline);
TextSetTopPosition(sourceWindow, file->linepos[file->topline]);
file->topPosition = file->linepos[file->topline];
}
XawTextSetInsertionPoint(sourceWindow, file->linepos[line]);
/* Text window might have scrolled, check topline & bottomline */
pos = XawTextTopPosition(sourceWindow);
for (i=1; pos >= file->linepos[i]; i++);
if (file->topline != i-1) {
file->topline = i-1;
file->bottomline = MIN (file->topline + file->lines - 1,
file->lastline);
}
UpdateLineLabel(line);
UpdateStops(file);
UpdateArrow(file);
UpdateUpdown(file);
UpdateBomb(file);
}
#ifdef GDB
#include "gdb_handler.c"
#else /*>>>>>>>>>> ALL THE FOLLOWING IS NOT COMPILED FOR GDB <<<<<<<<<<<<<<<<<<<*/
/* Handle dbx output of run, cont, next, step, return commands.
* Result of output parsing is returned in a set of tokens.
*/
void exec_handler()
{
int line, status;
char *func, *mesg;
char *segv = "signal SEGV";
char *segfault = "Segmentation fault";
/* Print "stopped in ..." line in message window
* Adjust text displayed
*/
if (Token.func == NULL || Token.line == 0)
return;
UpdateMessageWindow(Token.mesg,NULL);
line = Token.line;
func = XtNewString(Token.func);
mesg = XtNewString(Token.mesg);
#ifdef MIPS
status = LoadCurrentFile();
#else
if (Token.file)
status = LoadFile(Token.file);
#endif
arrow.line = line; /* update arrow sign position */
strcpy(arrow.func, func);
updown.line = 0; /* remove updown, if any */
if (displayedFile) {
strcpy(arrow.file, displayedFile->pathname);
}
/* Display bomb sign if segmentation fault occurs in source code */
if (status != -1 && (strncmp(mesg, segv, strlen(segv)) == 0 ||
strncmp(mesg, segfault, strlen(segfault)) == 0)) {
arrow.line = 0;
bomb.line = line;
strcpy(bomb.func, func);
if (displayedFile) strcpy(bomb.file, displayedFile->pathname);
}
else
bomb.line = 0;
AdjustText(line);
#ifndef BSD
display_handler();
#endif
XtFree(func);
XtFree(mesg);
}
/* Remove all the arrow and updown signs, print message, then
* change the file variable to the file name displayed.
*/
void done_handler()
{
char command[LINESIZ];
arrow.line = 0;
updown.line = 0;
UpdateArrow(displayedFile);
UpdateUpdown(displayedFile);
UpdateMessageWindow("Ready for execution",NULL);
if (displayedFile == NULL) return;
#ifdef MIPS
sprintf(command, "file %s\n", displayedFile->filename);
#else
sprintf(command, "file %s\n", displayedFile->pathname);
#endif
Parse = False;
query_dbx(command);
}
/* Place a stop sign next to the line specified on the source file window
* if it is to be viewable.
*/
void stop_at_handler()
{
if (Token.stop == 0 || Token.line == 0 || displayedFile == NULL)
return;
if (Token.file == NULL)
stops[Token.stop].file = displayedFile->pathname;
else
stops[Token.stop].file = GetPathname(Token.file);
DisplayStop(displayedFile, Token.line);
stops[Token.stop].line = Token.line;
stops[Token.stop].tag = 0;
nstops = Token.stop;
}
/*
* Place a stop sign next to the function routine, getting the line number
* by "list <func>", (or "func <func>" on a MIPS), and resetting the file
* variable properly.
*/
void stop_in_handler()
{
char command[LINESIZ], *file;
int stop;
int line;
if (Token.stop == 0 || Token.func == NULL || displayedFile == NULL)
return;
stop = Token.stop;
#ifdef MIPS
/* For mips dbx, need to use func command to locate the function */
Skip_func_handler = True;
sprintf(command, "func %s\n", Token.func);
query_dbx(command);
#else
#ifdef BSD
sprintf(command, "list %s\n", Token.func);
query_dbx(command);
#else
sprintf(command, "list %s\n", Token.func);
query_dbx(command);
if (Token.line <= 0)
return;
else
Token.line += 5;
#endif
#endif
stops[stop].line = Token.line;
nstops = stop;
line = Token.line;
/* Check the name of the file containing Token.func */
query_dbx("file\n");
if ((file = GetPathname(CurrentFile)) &&
strcmp(file, displayedFile->pathname)) { /* new file, record stop */
stops[nstops].file = file;
#ifdef MIPS
sprintf(command, "file %s\n", displayedFile->filename);
#else
sprintf(command, "file %s\n", displayedFile->pathname);
#endif
Parse = False;
query_dbx(command);
}
else { /* same file, display stop */
stops[nstops].file = displayedFile->pathname;
DisplayStop(displayedFile, line);
}
}
/*
* Display an outlined arrow to locate the calling routine in a stack
* frame. BSD and SUN dbx have slightly different output semantics here.
* The appropriate file with the calling routine is displayed and the
* file variable is set accordingly.
*/
void updown_handler()
{
char command[LINESIZ], *func, *file;
int line;
line = Token.line;
func = XtNewString(Token.func);
#ifdef MIPS
LoadCurrentFile();
#endif
#ifdef BSD
file = GetPathname(Token.file);
#else
if (line <= 0) line = 1;
LoadCurrentFile();
if (displayedFile)
file = displayedFile->pathname;
#endif
if (line <= 0 || func == NULL || file == NULL)
return;
if (displayedFile && strcmp(file, displayedFile->pathname)) {
LoadFile(file);
/* set dbx file variable to file */
#ifdef MIPS
sprintf(command, "file %s\n", displayedFile->filename);
#else
sprintf(command, "file %s\n", displayedFile->pathname);
#endif
Parse = False;
query_dbx(command);
}
updown.line = line;
strcpy(updown.func, func);
if (displayedFile)
strcpy(updown.file, displayedFile->pathname);
AdjustText(line);
XtFree(func);
}
/*
* Delete handler remove the stop specified and undisplayed the stopsign
* if it's visible.
* It calls the dbx status command to find out what stops are left, and
* then update the array of stops accordingly.
*/
/* ARGSUSED */
void delete_handler()
{
char s[LINESIZ];
int i;
int line;
write_dbx("status\n");
while (fgets(s, LINESIZ, dbxfp) == NULL);
do {
if (strcmp(s, dbxprompt) || strcmp(s, "")) {
sscanf(s, BRACKET, &i);
if (i > 0 && i <= nstops && stops[i].line > 0)
stops[i].tag = 1;
}
} while (fgets(s, LINESIZ, dbxfp));
for (i=1; i<=nstops; i++)
if (stops[i].line > 0) {
if (stops[i].tag)
stops[i].tag = 0;
else {
line = stops[i].line;
stops[i].line = 0;
stops[i].file = NULL;
if (LineToStop_no(line) == 0)
RemoveStop(line);
}
}
}
/*
* This handler displays the function routine on the source window.
* It locates the function by sending the dbx command "list <func>",
* and loads the appropriate file accordingly.
*/
void func_handler()
{
int line;
char command[LINESIZ];
if (Token.func && !Skip_func_handler) {
#ifdef MIPS
line = Token.line;
#else
sprintf(command, "list %s\n", Token.func);
query_dbx(command);
line = Token.line + 5;
#endif
LoadCurrentFile();
AdjustText(line);
}
Skip_func_handler = False;
}
/* File handler first queries the current file set by the user command,
* and then loads the file.
*/
/* ARGSUSED */
void file_handler() /* Command was 'file' */
{
if (Token.file)
strcpy(CurrentFile, Token.file);
else
strcpy(CurrentFile, "");
}
/* ARGSUSED */
void debug_handler()
{
query_dbx("use\n");
displayedFile = NULL; /* force reloading of source file */
if (LoadCurrentFile() == 0) {
arrow.line = 0; /* clear arrow sign */
updown.line = 0; /* clear updown sign */
bomb.line = 0; /* clear bomb sign */
UpdateArrow(displayedFile);
UpdateUpdown(displayedFile);
UpdateBomb(displayedFile);
ClearStops();
UpdateStops(displayedFile);
UpdateMessageWindow("Ready for execution",NULL);
query_dbx("func main\n");
#ifndef BSD
query_dbx("display\n"); /* clear display window */
#endif
}
}
/* ARGSUSED */
void cd_handler()
{
query_dbx("pwd\n");
}
/* ARGSUSED */
void pwd_handler(s)
char *s;
{
strcpy(cwd, (char *)strtok(s, "\n"));
}
/* ARGSUSED */
void use_handler(output)
char *output;
{
if (strcmp(output, "") == 0)
query_dbx("use\n");
else
MakeDirList(output);
}
/* ARGSUSED */
void search_handler()
{
AdjustText(Token.line);
}
/* ARGSUSED */
void list_handler()
{
int line;
if (Echo) {
line = Token.line;
LoadCurrentFile();
AdjustText(line);
}
}
/* ARGSUSED */
/* Show output on the display window.
* If output is null but the display window is managed, replace contents of
* the display window with the null string.
*/
void display_handler()
{
Arg args[MAXARGS];
Cardinal n;
if (!Token.display || strcmp(Token.display, "") == 0) {
#ifndef NEW_INTERFACE
if (!XtIsManaged(displayWindow))
return;
else {
#endif
XtFree(Token.display);
Token.display = XtNewString("");
#ifndef NEW_INTERFACE
}
#endif
}
#ifndef NEW_INTERFACE
if (!XtIsManaged(displayWindow)) {
XtManageChild(separator);
XtManageChild(displayWindow);
}
#endif
n = 0;
XtSetArg(args[n], XtNstring, (XtArgVal) Token.display); n++;
XtSetValues(displayWindow, args, n);
XtFree(Token.display);
}
#endif /* NOT GDB */
syntax highlighted by Code2HTML, v. 0.9.1