1 /*****************************************************************************
2  *
3  *  xdbx - X Window System interface to the dbx debugger
4  *
5  *  Copyright 1989 The University of Texas at Austin
6  *  Copyright 1990 Microelectronics and Computer Technology Corporation
7  *
8  *  Permission to use, copy, modify, and distribute this software and its
9  *  documentation for any purpose and without fee is hereby granted,
10  *  provided that the above copyright notice appear in all copies and that
11  *  both that copyright notice and this permission notice appear in
12  *  supporting documentation, and that the name of The University of Texas
13  *  and Microelectronics and Computer Technology Corporation (MCC) not be
14  *  used in advertising or publicity pertaining to distribution of
15  *  the software without specific, written prior permission.  The
16  *  University of Texas and MCC makes no representations about the
17  *  suitability of this software for any purpose.  It is provided "as is"
18  *  without express or implied warranty.
19  *
20  *  THE UNIVERSITY OF TEXAS AND MCC DISCLAIMS ALL WARRANTIES WITH REGARD TO
21  *  THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
22  *  FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF TEXAS OR MCC BE LIABLE FOR
23  *  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
24  *  RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
25  *  CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
26  *  CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27  *
28  *  Author:  	Po Cheung
29  *  Created:   	March 10, 1989
30  *
31  *****************************************************************************
32  *
33  *  xxgdb - X Window System interface to the gdb debugger
34  *
35  * 	Copyright 1990,1993 Thomson Consumer Electronics, Inc.
36  *
37  *  Permission to use, copy, modify, and distribute this software and its
38  *  documentation for any purpose and without fee is hereby granted,
39  *  provided that the above copyright notice appear in all copies and that
40  *  both that copyright notice and this permission notice appear in
41  *  supporting documentation, and that the name of Thomson Consumer
42  *  Electronics (TCE) not be used in advertising or publicity pertaining
43  *  to distribution of the software without specific, written prior
44  *  permission.  TCE makes no representations about the suitability of
45  *  this software for any purpose.  It is provided "as is" without express
46  *  or implied warranty.
47  *
48  *  TCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
49  *  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
50  *  SHALL TCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
51  *  OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
52  *  WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
53  *  ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
54  *  SOFTWARE.
55  *
56  *  Adaptation to GDB:  Pierre Willard
57  *  XXGDB Created:   	December, 1990
58  *
59  *****************************************************************************/
60 
61 /*  handler.c
62  *
63  *    Contain action handlers for the parser to invoke upon a dbx command.
64  *
65  *    TextSetTopPosition():	Set the top character position of text displayed
66  *    AdjustText():		Adjust the portion of text displayed.
67  *    exec_handler():		Update file, line label, arrow position.
68  *    done_handler():		Progrm execution completed, clear breakpoints
69  *    stop_at_handler():	Place stop sign on line specified.
70  *    stop_in_handler():	Place stop sign on function specified.
71  *    updown_handler():		Update file, line label, updown arrow position.
72  *    delete_handler():		Remove stop sign.
73  *    func_handler():		Display function, if specified.
74  *    file_handler():		Display file, if specified.
75  *    debug_handler():		Check directory use list, display source file.
76  *    cd_handler():		Record current working directory.
77  *    use_handler():		Record directory paths.
78  *    search_handler():		Adjust source file to display matched line.
79  *    list_handler();		Adjust source file to display result.
80  *    display_handler():	Display results in display window.
81  */
82 
83 #include <ctype.h>
84 #include "global.h"
85 #ifdef BSD
86 #define	BRACKET	"[%d]"
87 #else
88 #define	BRACKET	"(%d)"
89 #endif
90 
91 #ifndef GDB
92 Boolean		Echo = True;		/* display dbx output if true */
93 static Boolean	Skip_func_handler = False;
94 #endif
95 
96 /*  Display text starting from the top position specified by pos */
97 
TextSetTopPosition(w,pos)98 void TextSetTopPosition(w, pos)
99     Widget w;
100     XawTextPosition pos;
101 {
102     Arg args[MAXARGS];
103     Cardinal n;
104 
105     n = 0;
106     XtSetArg(args[n], XtNdisplayPosition, (XtArgVal) pos);               n++;
107     XtSetValues(w, args, n);
108 }
109 
110 /*
111  *  Adjust text so that 'line' will fall into the viewable part of the
112  *  source window.
113  *  Arrows, stop signs, and line label are updated accordingly.
114  */
AdjustText(line)115 void AdjustText(line)
116     int	   	line;
117 {
118     FileRec 		*file;
119     int	    		nlines = 0;
120     int			i;
121     XawTextPosition 	pos;
122 
123     if ((file = displayedFile) == NULL || line <= 0) return;
124     file->currentline = line;
125 
126     if (line < file->topline || line > file->bottomline ) {
127 	/* Position line about 30% from the top */
128 	nlines = file->lines*0.3;
129 	if (line < nlines)			   /* near top */
130 	    file->topline = 1;
131 	else if (line > file->lastline - nlines)  /* near bottom */
132 	    file->topline = MAX(file->lastline - file->lines + 1, 1);
133 	else
134 	    file->topline = line - nlines;
135 	file->bottomline = MIN(file->topline + file->lines - 1, file->lastline);
136 	TextSetTopPosition(sourceWindow, file->linepos[file->topline]);
137 	file->topPosition = file->linepos[file->topline];
138     }
139     XawTextSetInsertionPoint(sourceWindow, file->linepos[line]);
140 
141     /* Text window might have scrolled, check topline & bottomline */
142     pos = XawTextTopPosition(sourceWindow);
143     for (i=1; pos >= file->linepos[i]; i++);
144     if (file->topline != i-1) {
145 	file->topline = i-1;
146 	file->bottomline = MIN (file->topline + file->lines - 1,
147 				file->lastline);
148     }
149     UpdateLineLabel(line);
150     UpdateStops(file);
151     UpdateArrow(file);
152     UpdateUpdown(file);
153     UpdateBomb(file);
154 }
155 
156 #ifdef GDB
157 
158 #include "gdb_handler.c"
159 
160 #else /*>>>>>>>>>> ALL THE FOLLOWING IS NOT COMPILED FOR GDB <<<<<<<<<<<<<<<<<<<*/
161 
162 /*  Handle dbx output of run, cont, next, step, return commands.
163  *  Result of output parsing is returned in a set of tokens.
164  */
exec_handler()165 void exec_handler()
166 {
167     int	 line, status;
168     char *func, *mesg;
169     char *segv = "signal SEGV";
170     char *segfault = "Segmentation fault";
171 
172     /* Print "stopped in ..." line in message window
173      * Adjust text displayed
174      */
175     if (Token.func == NULL || Token.line == 0)
176 	return;
177     UpdateMessageWindow(Token.mesg,NULL);
178     line = Token.line;
179     func = XtNewString(Token.func);
180     mesg = XtNewString(Token.mesg);
181 #ifdef MIPS
182     status = LoadCurrentFile();
183 #else
184     if (Token.file)
185 	status = LoadFile(Token.file);
186 #endif
187     arrow.line = line;			/* update arrow sign position */
188     strcpy(arrow.func, func);
189     updown.line = 0;			/* remove updown, if any */
190     if (displayedFile) {
191     	strcpy(arrow.file, displayedFile->pathname);
192     }
193     /* Display bomb sign if segmentation fault occurs in source code */
194     if (status != -1 && (strncmp(mesg, segv, strlen(segv)) == 0 ||
195 	strncmp(mesg, segfault, strlen(segfault)) == 0)) {
196 	arrow.line = 0;
197 	bomb.line = line;
198 	strcpy(bomb.func, func);
199     	if (displayedFile) strcpy(bomb.file, displayedFile->pathname);
200     }
201     else
202 	bomb.line = 0;
203 
204     AdjustText(line);
205 #ifndef BSD
206     display_handler();
207 #endif
208     XtFree(func);
209     XtFree(mesg);
210 }
211 
212 /*  Remove all the arrow and updown signs, print message, then
213  *  change the file variable to the file name displayed.
214  */
done_handler()215 void done_handler()
216 {
217     char command[LINESIZ];
218 
219     arrow.line = 0;
220     updown.line = 0;
221     UpdateArrow(displayedFile);
222     UpdateUpdown(displayedFile);
223     UpdateMessageWindow("Ready for execution",NULL);
224     if (displayedFile == NULL) return;
225 #ifdef MIPS
226     sprintf(command, "file %s\n", displayedFile->filename);
227 #else
228     sprintf(command, "file %s\n", displayedFile->pathname);
229 #endif
230     Parse = False;
231     query_dbx(command);
232 }
233 
234 /*  Place a stop sign next to the line specified on the source file window
235  *  if it is to be viewable.
236  */
stop_at_handler()237 void stop_at_handler()
238 {
239     if (Token.stop == 0 || Token.line == 0 || displayedFile == NULL)
240 	return;
241     if (Token.file == NULL)
242 	stops[Token.stop].file = displayedFile->pathname;
243     else
244 	stops[Token.stop].file = GetPathname(Token.file);
245     DisplayStop(displayedFile, Token.line);
246     stops[Token.stop].line = Token.line;
247     stops[Token.stop].tag = 0;
248     nstops = Token.stop;
249 }
250 
251 
252 /*
253  *  Place a stop sign next to the function routine, getting the line number
254  *  by "list <func>", (or "func <func>" on a MIPS), and resetting the file
255  *  variable properly.
256  */
stop_in_handler()257 void stop_in_handler()
258 {
259     char command[LINESIZ], *file;
260     int  stop;
261     int	 line;
262 
263     if (Token.stop == 0 || Token.func == NULL || displayedFile == NULL)
264 	return;
265     stop = Token.stop;
266 #ifdef MIPS
267     /* For mips dbx, need to use func command to locate the function */
268     Skip_func_handler = True;
269     sprintf(command, "func %s\n", Token.func);
270     query_dbx(command);
271 #else
272 #ifdef BSD
273     sprintf(command, "list %s\n", Token.func);
274     query_dbx(command);
275 #else
276     sprintf(command, "list %s\n", Token.func);
277     query_dbx(command);
278     if (Token.line <= 0)
279 	return;
280     else
281 	Token.line += 5;
282 #endif
283 #endif
284 
285     stops[stop].line = Token.line;
286     nstops = stop;
287     line = Token.line;
288 
289     /* Check the name of the file containing Token.func */
290     query_dbx("file\n");
291     if ((file = GetPathname(CurrentFile)) &&
292         strcmp(file, displayedFile->pathname)) {   /* new file, record stop */
293 	stops[nstops].file = file;
294 #ifdef MIPS
295 	sprintf(command, "file %s\n", displayedFile->filename);
296 #else
297 	sprintf(command, "file %s\n", displayedFile->pathname);
298 #endif
299 	Parse = False;
300 	query_dbx(command);
301     }
302     else { 					   /* same file, display stop */
303 	stops[nstops].file = displayedFile->pathname;
304 	DisplayStop(displayedFile, line);
305     }
306 }
307 
308 /*
309  *  Display an outlined arrow to locate the calling routine in a stack
310  *  frame.  BSD and SUN dbx have slightly different output semantics here.
311  *  The appropriate file with the calling routine is displayed and the
312  *  file variable is set accordingly.
313  */
updown_handler()314 void updown_handler()
315 {
316     char command[LINESIZ], *func, *file;
317     int	 line;
318 
319     line = Token.line;
320     func = XtNewString(Token.func);
321 #ifdef MIPS
322     LoadCurrentFile();
323 #endif
324 #ifdef BSD
325     file = GetPathname(Token.file);
326 #else
327     if (line <= 0) line = 1;
328     LoadCurrentFile();
329     if (displayedFile)
330 	file = displayedFile->pathname;
331 #endif
332 
333     if (line <= 0 || func == NULL || file == NULL)
334 	return;
335     if (displayedFile && strcmp(file, displayedFile->pathname)) {
336 	LoadFile(file);
337 
338 	/* set dbx file variable to file */
339 #ifdef MIPS
340 	sprintf(command, "file %s\n", displayedFile->filename);
341 #else
342 	sprintf(command, "file %s\n", displayedFile->pathname);
343 #endif
344 	Parse = False;
345 	query_dbx(command);
346     }
347     updown.line = line;
348     strcpy(updown.func, func);
349     if (displayedFile)
350     	strcpy(updown.file, displayedFile->pathname);
351     AdjustText(line);
352     XtFree(func);
353 }
354 
355 /*
356  *  Delete handler remove the stop specified and undisplayed the stopsign
357  *  if it's visible.
358  *  It calls the dbx status command to find out what stops are left, and
359  *  then update the array of stops accordingly.
360  */
361 /* ARGSUSED */
delete_handler()362 void delete_handler()
363 {
364     char s[LINESIZ];
365     int  i;
366     int	 line;
367 
368     write_dbx("status\n");
369     while (fgets(s, LINESIZ, dbxfp) == NULL);
370     do {
371 	if (strcmp(s, dbxprompt) || strcmp(s, "")) {
372 	    sscanf(s, BRACKET, &i);
373 	    if (i > 0 && i <= nstops && stops[i].line > 0)
374 	    	stops[i].tag = 1;
375 	}
376     } while (fgets(s, LINESIZ, dbxfp));
377 
378     for (i=1; i<=nstops; i++)
379 	if (stops[i].line > 0) {
380 	    if (stops[i].tag)
381 		stops[i].tag = 0;
382 	    else {
383 		line = stops[i].line;
384 		stops[i].line = 0;
385 		stops[i].file = NULL;
386 		if (LineToStop_no(line) == 0)
387 		    RemoveStop(line);
388 	    }
389 	}
390 }
391 
392 /*
393  *  This handler displays the function routine on the source window.
394  *  It locates the function by sending the dbx command "list <func>",
395  *  and loads the appropriate file accordingly.
396  */
func_handler()397 void func_handler()
398 {
399     int	 line;
400     char command[LINESIZ];
401 
402     if (Token.func && !Skip_func_handler) {
403 #ifdef MIPS
404 	line = Token.line;
405 #else
406 	sprintf(command, "list %s\n", Token.func);
407 	query_dbx(command);
408 	line = Token.line + 5;
409 #endif
410 	LoadCurrentFile();
411 	AdjustText(line);
412     }
413     Skip_func_handler = False;
414 }
415 
416 
417 /*  File handler first queries the current file set by the user command,
418  *  and then loads the file.
419  */
420 /* ARGSUSED */
file_handler()421 void file_handler() 	/* Command was 'file' */
422 {
423     if (Token.file)
424 	strcpy(CurrentFile, Token.file);
425     else
426 	strcpy(CurrentFile, "");
427 }
428 
429 /* ARGSUSED */
debug_handler()430 void debug_handler()
431 {
432     query_dbx("use\n");
433     displayedFile = NULL;		/* force reloading of source file */
434     if (LoadCurrentFile() == 0) {
435 	arrow.line = 0;			/* clear arrow sign */
436 	updown.line = 0;		/* clear updown sign */
437 	bomb.line = 0;			/* clear bomb sign */
438 	UpdateArrow(displayedFile);
439 	UpdateUpdown(displayedFile);
440 	UpdateBomb(displayedFile);
441 	ClearStops();
442 	UpdateStops(displayedFile);
443         UpdateMessageWindow("Ready for execution",NULL);
444 	query_dbx("func main\n");
445 #ifndef BSD
446 	query_dbx("display\n");		/* clear display window */
447 #endif
448     }
449 }
450 
451 /* ARGSUSED */
cd_handler()452 void cd_handler()
453 {
454     query_dbx("pwd\n");
455 }
456 
457 /* ARGSUSED */
pwd_handler(s)458 void pwd_handler(s)
459 char *s;
460 {
461     strcpy(cwd, (char *)strtok(s, "\n"));
462 }
463 
464 /* ARGSUSED */
use_handler(output)465 void use_handler(output)
466 char *output;
467 {
468     if (strcmp(output, "") == 0)
469 	query_dbx("use\n");
470     else
471     	MakeDirList(output);
472 }
473 
474 /* ARGSUSED */
search_handler()475 void search_handler()
476 {
477     AdjustText(Token.line);
478 }
479 
480 /* ARGSUSED */
list_handler()481 void list_handler()
482 {
483     int	 line;
484 
485     if (Echo) {
486 	line = Token.line;
487 	LoadCurrentFile();
488     	AdjustText(line);
489     }
490 }
491 
492 /* ARGSUSED */
493 /*  Show output on the display window.
494  *  If output is null but the display window is managed, replace contents of
495  *  the display window with the null string.
496  */
display_handler()497 void display_handler()
498 {
499     Arg		args[MAXARGS];
500     Cardinal	n;
501 
502     if (!Token.display || strcmp(Token.display, "") == 0) {
503 #ifndef NEW_INTERFACE
504 	if (!XtIsManaged(displayWindow))
505 	    return;
506 	else {
507 #endif
508 	    XtFree(Token.display);
509 	    Token.display = XtNewString("");
510 #ifndef NEW_INTERFACE
511 	}
512 #endif
513     }
514 #ifndef NEW_INTERFACE
515     if (!XtIsManaged(displayWindow)) {
516 	XtManageChild(separator);
517 	XtManageChild(displayWindow);
518     }
519 #endif
520     n = 0;
521     XtSetArg(args[n], XtNstring, (XtArgVal) Token.display);		n++;
522     XtSetValues(displayWindow, args, n);
523     XtFree(Token.display);
524 }
525 
526 #endif /* NOT GDB */
527