From: pierre@tce.COM (Pierre Willard)
Subject: REPOST: v11i051: xxgdb - X front end for gdb, Part04/08
Newsgroups: comp.sources.x
Sender: argv@sun.com
Approved: argv@sun.com
References: <csx-11i048:xxgdb@uunet.UU.NET>

Submitted-by: pierre@tce.COM (Pierre Willard)
Posting-number: Volume 11, Issue 51
Archive-name: xxgdb/part04



#! /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 6 (of 8)."
# Contents:  gdb_regex.h source.c
# Wrapped by gilbert@phi on Tue Jan 15 13:12:49 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'gdb_regex.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'gdb_regex.h'\"
else
echo shar: Extracting \"'gdb_regex.h'\" \(16887 characters\)
sed "s/^X//" >'gdb_regex.h' <<'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/*  
X *  gdb_regex.h:
X *
X *  Regular expression pattern matching for GNU gdb.
X *  
X *  The reg_token array indicates the register no. for each token type.
X *      reg_token[0] : message
X *      reg_token[1] : stop number
X *      reg_token[2] : function name
X *      reg_token[3] : line number
X *      reg_token[4] : file name
X *      reg_token[5] : display command output
X */
X
X#define	TK_MESG 	0
X#define TK_STOP		1
X#define TK_FUNC 	2
X#define TK_LINE 	3
X#define TK_FILE 	4
X#define TK_DISP 	5
X
X#define	O_EXEC_MESS_AFTER	0
X#define	O_EXEC_MESS_BEFORE	1
X#define	O_EXEC				2
X#define O_DONE				3
X#define O_BREAK 			4			/* Instead of O_STOPAT & O_STOPIN */
X#define O_INFO_DIR  		5			/* NEW for GDB */
X#define O_FRAME_CURR		6			/* O_FRAME_CURR = O_UPDOWN */
X#define O_UPDOWN 			6
X#define O_BELL				7
X#define O_SEARCH			8
X#define O_INFO_LINE			9			/* Instead of O_FILE */
X#define O_PRINT				10
X#define O_DEBUG				11
X#define O_DIRECTORY			12			
X#define O_LIST				13			/* for dbx, O_LIST = O_SEARCH */
X#define O_DISPLAY			14
X#define O_DISPLAY_INFO		15
X#define O_PWD				16
X#define O_CD				16			/* O_PWD = O_CD */
X#define O_RECEIVED_SIGNAL	17			/* test program received signal */
X#define O_EXEC_DISPLAY		18			/* special for filter_display_info  */
X#define O_READING_SYMBOLS	19			/* special for filter_reading_symbols */
X
X
X#define	C_ANY			-1
X#define C_EXEC			0
X#define C_BREAK			1			/* Instead of C_STOPAT & C_STOPIN */
X#define C_INFO_DIR		2			/* NEW for GDB */
X#define C_FRAME_CURR	3
X#define C_UPDOWN		4
X#define C_DELETE		5
X#define C_FINISH		6			/* Instead of C_FUNC */
X#define C_INFO_LINE		7			/* Instead of C_FILE */
X#define C_SYMBOL_FILE	8
X#define C_CD			9
X#define C_DIRECTORY		10			/* Instead of C_USE */
X#define C_PWD			11
X#define C_LIST			12
X#define C_SEARCH		13
X#define C_DISPLAY_INFO	14			/* must be BEFORE C_DISPLAY ! */
X#define C_DISPLAY		15
X#define C_UNDISPLAY		16
X#define C_PRINT			17
X#define C_INFO_BREAK	18
X#define C_SOURCE		19
X#define C_EXEC_FILE		20
X
X/*--------------------------------------------------------------------------+
X|																			|
X|								DBX											|
X|																			|
X| Reading symbolic information...											|
X| Read 46 symbols															|
X| (dbx)																		|
X| (dbx)																		|
X| stopped in main at line 5 in file "pw.c"									|
X|	 5			 for (i=0; i<100; i++)										|
X| (dbx) use																	|
X| /usr1/gnu_sun4/xdbx/														|
X| (dbx) file																|
X| pw.c																		|
X| (dbx) file																|
X| No current source file													|
X|																			|
X+--------------------------------------------------------------------------*/
X/*--------------------------------------------------------------------------+
X|																			|
X|								GDB											|
X|																			|
X| Reading symbol data from /usr1/gnu_sun4/xdbx/pw...done.					|
X| Type "help" for a list of commands.										|
X| (gdb)																		|
X| (gdb)																		|
X| Bpt 1, main () (pw.c line 5)												|
X| 5				  for (i=0; i<100; i++)										|
X| (gdb) info directories													|
X| Source directories searched: /usr1/gnu_sun4/xdbx:/usr1/toto				|
X| (gdb) info line															|
X| Line 10 of "pw.c" starts at pc 0x22dc and ends at 0x22e4.					|
X| (gdb) info line															|
X| No source file specified.													|
X|																			|
X+--------------------------------------------------------------------------*/
X/*--------------------------------------------------------------------------+
X|																			|
X|								GDB -fullname								|
X|																			|
X|																			|
X|	We use option -fullname (see dbxoptions() in xdbx.c).					|
X|																			|
X| GDB prints (see source.c of gdb):											|
X|																			|
X|		"\032\032%s:%d:%d:%s:0x%x\n", s->fullname,							|
X|		line, s->line_charpos[line - 1],									|
X|		mid_statement ? "middle" : "beg",									|
X|		get_frame_pc (get_current_frame()));								|
X|																			|
X| (gdb) break main															|
X| Reading in symbols for pw.c...done.										|
X| Breakpoint 1 at 0x229c: file pw.c, line 5.								|
X| (gdb) run																	|
X| Starting program: /usr1/gnu_sun4/xdbx/pw									|
X|																			|
X| Bpt 1, main () (pw.c line 5)												|
X| /usr1/gnu_sun4/xdbx/pw.c:5:17:beg:0x229c									|
X| (gdb) step																|
X| /usr1/gnu_sun4/xdbx/pw.c:6:40:beg:0x22b0									|
X| (gdb)																		|
X|																			|
X| (gdb) info directories													|
X| Source directories searched: /usr1/gnu_sun4/xdbx							|
X| (gdb) info line															|
X| Line 10 of "pw.c" starts at pc 0x22dc and ends at 0x22e4.					|
X| (gdb) info line															|
X| No source file specified.													|
X| (gdb) info line															|
X| Line number 34 is out of range for "bug1.c".								|
X|																			|
X| (gdb) display i															|
X| 3: i = 0																	|
X| (gdb) display																|
X| 4: i + 1 = 1																|
X| 3: i = 0																	|
X| (gdb) undisplay 2															|
X| (gdb) display																|
X| (gdb) 																	|
X|																			|
X| (gdb) up																	|
X| #2  0x2314 in main () (pw.c line 35)										|
X| /usr1/gnu_sun4/xdbx/pw.c:35:158:beg:0x2360								|
X| (gdb) up																	|
X| Initial frame selected; you cannot go up.									|
X| (gdb)																		|
X|																			|
X| (gdb) down																|
X| #0  glop (number=1) (pw2.c line 5)										|
X| /usr1/gnu_sun4/xdbx/pw2.c:5:33:beg:0x2360									|
X| (gdb) down																|
X| Bottom (i.e., innermost) frame selected; you cannot go down.				|
X| (gdb)																		|
X|																			|
X| (gdb) pwd																	|
X| Working directory /usr1/gnu_sun4/xdbx.									|
X| (gdb) cd ..																|
X| Working directory /usr1/gnu_sun4.											|
X| (gdb) cd xdbx																|
X| Working directory /usr1/gnu_sun4/xdbx.									|
X| (gdb) cd toto																|
X| toto: No such file or directory.											|
X| (gdb)																		|
X|																			|
X| Program exited with code 01.												|
X| (gdb)																		|
X|																			|
X+--------------------------------------------------------------------------*/
X/*
X
X		.		--> any character but '\n'
X		*		--> any character 0 to n times
X		+		--> any character 1 to n times
X		?		--> any character 0 or 1 time
X		^		--> begin of line or NOT following character
X		$		--> end of line or '$'
X		\\w		--> character '0..9a..zA...Z'
X		\\W		--> character NOT '0..9a..zA...Z'
X		\\<		--> word begin (word is composed of 0..9a..zA...Z)
X		\\>		--> word end (word is composed of 0..9a..zA...Z)
X		\\b		--> word bound
X		\\B		--> not word bound
X		\\|		--> means OR
X		\\`		--> begin buffer
X		\\\'	--> end buffer
X		
X		
X>>	WARNING : be carefull with \\| (OR) : the re_match() function
X>>	will NOT correctly update the string for a pattern which is
X>>	optional !
X>>	--> The number SHOULD NOT point to a patterm which is optional ! 
X
X*/
X
X    /* (PW)5DEC90: I have a problem if we say \\(Bpt.*\n\\)? in exec pattern.
X    	That is why I have two cases : with or without Bpt...
X    	Note that 'exec without Message' includes 'exec with Message'.
X    	We display 'Bpt...' in the message window. */
X    	
X    /* (PW)14JAN91 (v1.01) : use 
X   		\\(\\([0-9]+:.*\n\\(\\( .*\n\\)*}\n\\)?\\)*\\)
X    instead of
X    	\\(\\([0-9]+:.*\n\\)*\\)
X    for display pattern.
X    */
X    
X
Xstatic PatternRec output_pattern[] = {
X    /* exec with Message after */
X    {"\\(.*\n\\)*\032\032\\([^ ]+\\):\\([0-9]+\\):\\([0-9]+\\):\\([^ ]+\\):0x.+\n\\([ ]*[^0-9].*\n\\)\\(\\([0-9]+:.*\n\\(\\( .*\n\\)*}\n\\)?\\)*\\)",
X     NULL,
X     {6, -1, -1, 3, 2, 7}
X    },
X    /* exec with Message before */
X    {"\\(.*\n\\)*\\([ ]*[^ ].*\n\\)\032\032\\([^ ]+\\):\\([0-9]+\\):\\([0-9]+\\):\\([^ ]+\\):0x.+\n\\(\\([0-9]+:.*\n\\(\\( .*\n\\)*}\n\\)?\\)*\\)",
X     NULL,
X     {2, -1, -1, 4, 3, 7}	
X    },
X    /* exec without Message */
X    {"\\(.*\n\\)*\032\032\\(\\([^ ]+\\):\\([0-9]+\\):\\([0-9]+\\):\\([^ ]+\\):0x.+\n\\)\\(\\([0-9]+:.*\n\\(\\( .*\n\\)*}\n\\)?\\)*\\)",
X     NULL,
X     {2, -1, -1, 4, 3, 7}
X    },
X    /* done */
X    {"\\(.*\n\\)*\n\\(Program terminated with signal \\|Program exited with code 0\\|Program exited normally\\).*\n\\(.*\n\\)*",
X     NULL,
X     {-1, -1, -1, -1, -1, -1}
X    },
X    /* break */
X    {"\\(.*\n\\)*Breakpoint \\([0-9]+\\) at [^ ]+: file \\([^ ]+\\), line \\([0-9]+\\).\n",
X     NULL,
X     {-1, 2, -1, 4, 3, -1}
X    },
X    /* info directories */
X    {"Source directories searched:[ ]*\\([^ ]+\\)[ ]*\n",
X     NULL,
X     { -1, -1, -1, -1, 1, -1}
X    },
X    /* up, down */
X    {"\\(.*\n\\)*\\(#[0-9]+[ ]+\\(0x[^ ]+[ ]+in[ ]+\\)?\\([^ ]+\\).*\n\\)\\(Source file is more recent than executable.\n\\)?\032\032\\([^ ]+\\):\\([0-9]+\\):\\([0-9]+\\):\\([^ ]+\\):0x.+\n",
X     NULL,
X     {2, -1, 4, 7, 6, -1}	
X    },
X    /* bell */
X    {"\\(Undefined command: .*\n\\|Already at the \\(top\\|bottom\\) call level\n\\|\
XNo active stack frames\n\\|no program to run\n\\|no process to run\n\\|\
Xprogram is not active\n\\|can't continue execution\n\\|\
X.*\ncan't write to process.*\n\\|\
X\\(Top\\|End\\)-of-file; did not find search string:.*\n\\)",
X     NULL,
X     {-1, -1, -1, -1, -1}
X    },
X    /* search */
X    {"\\([0-9]+\\).*\n",
X     NULL,
X     {-1, -1, -1, 1, -1, -1}
X    },
X    /* info line */
X    {"\\(Line \\(number \\)?[0-9]+ \\(of\\|is out of range for\\) \"\\([^ ]+\\)\".*\\)\n",
X     NULL,
X     {-1, -1, -1, -1, 4, -1}
X    },
X    /* print */
X    {"\\(warning: .*\n\\)?\\(\\(.*\\) = .*\n\\(.*\n\\)*\\)",
X     NULL,
X     { 3, -1, -1, -1, -1, 2}
X    },
X    /* start gdb (debug)  */
X    {"\\(.*\n\\)*Type \"help\" for a list of commands.\n",
X     NULL,
X     { -1, -1, -1, -1, -1, -1}
X    },
X    /* directory */
X    {"\\([^ ]+ is already in the source path.[ ]*\n\\)*Source directories searched:[ ]*\\([^ ]+\\)[ ]*\n",
X     NULL,
X     { -1, -1, -1, -1, 1, -1}
X    },
X    /* list */
X    {"\\(.*\n\\)*\\(\\([0-9]+\\).*\n\\)",
X     NULL,
X     { -1, -1, -1, 3, -1, -1}
X    },
X    /* display */
X    {"\\([0-9]+:.*\n\\)",
X     NULL,
X     { -1, -1, -1, -1, -1, 1}
X    },
X    /* info display */
X    {"\\(\\([0-9]+:.*\n\\(\\( .*\n\\)*}\n\\)?\\)*\\)",
X     NULL,
X     { -1, -1, -1, -1, -1, 1}
X    },
X    /* pwd or cd */
X    {"Working directory[ ]+\\([^ ]+\\).[ ]*\n\\([ ]*(canonically[ ]+\\([^ ]+\\)).\n\\)?",
X     NULL,
X     { 1, -1, -1, -1, -1, 3}
X    },
X    /* program received signal */
X    {"\\(.*\n\\)*\n\\(Program received signal \\([-]?[0-9]+\\), [^ ]+.*\n\\)\\(.*\n\\)*",
X	NULL,
X     {  2, 3, -1, -1, -1, -1}
X    },
X    /* special for test in filter_display_info() */
X    {"\\([^0-9].*\n\\)*\\([0-9]+:.*\n\\)\\(.*\n\\)*",
X     NULL,
X     { -1, -1, -1, -1, -1, 2}
X    },
X    /* special for test in filter_reading_symbols() */
X    {"\\(.*\n\\)*\\(Reading in symbols for .*done.\n\\)\\(.*\n\\)*",
X     NULL,
X     { 2, -1, -1, -1, -1, -1}
X    },
X    NULL 
X};
X
X/*
X
X	To simplify the patterns, I used for example :
X	
X		"fr[ame]*" instead of "frame\\|fram\\|fra||fr".
X		
X	This will cause 'frmeame' to be accepted. But this is
X	no problem because 'Undefined command' output is parsed
X	before parsing the command line (see parse() in parser.c).
X*/
X
Xstatic PatternRec command_pattern[] = {
X	/* run -r - cont - c - next - n - step - s - nexti - ni - stepi - si - return
X	jump - until - u */
X    {"[ ]*\\(run\\|r\\|cont\\|c\\|next\\|n\\|step\\|s\\|nexti\\|stepi\\|ni\\|si\\|ret[urn]*\\|j[ump]*\\|unt[il]*\\|u\\)\\( .*\\)?\n",
X											NULL, {-1, -1, -1, -1, -1, -1}},
X	/* break - tbreak */
X    {"[ ]*\\(t\\)?\\(b\\|br\\|bre\\|brea\\|break\\)\\( .*\\)?\n",
X    										NULL, {-1, -1, -1, -1, -1, -1}},
X    {"[ ]*info[ ]+directories[ ]*\n",		NULL, {-1, -1, -1, -1, -1, -1}},
X    
X    /* 'frame' is special case of 'frame n' since it does not change the
X    current frame. Else 'frame n' is like up or down. */
X    {"[ ]*fr[ame]*[ ]*\n",					NULL, {-1, -1, -1, -1, -1, -1}},
X    {"[ ]*\\(up\\|down\\|dow\\|do\\|fr[ame]*\\)\\( .*\\)?\n", 
X											NULL, {-1, -1, -1, -1, -1, -1}},
X											
X	/* delete - d - clear - enable - disable - dis - disa */
X	/* gdb commands 'delete display' 'enable display' and 'delete environment'
X	are also found here. This is superfluous, but no problem */
X	
X    {"[ ]*\\(del[ete]*\\|d\\|cl[ear]*\\|en[able]*\\|disab[le]*\\|dis\\|disa\\)\\( .*\\)?\n",
X    										NULL, {-1, -1, -1, -1, -1, -1}},
X    										
X	{"[ ]*fi[nish]*[ ]*\n",					NULL, {-1, -1, -1, -1, -1, -1}},
X    {"[ ]*info[ ]+line[ ]*\n",				NULL, {-1, -1, -1, -1, -1, -1}},
X    
X    /* symbol-file */
X    {"[ ]*sy.*\n", 							NULL, {-1, -1, -1, -1, -1, -1}},
X    {"[ ]*cd[ ]*[^ ]+[ ]*\n", 				NULL, {-1, -1, -1, -1, -1, -1}},
X    
X    /* directory */
X	{"[ ]*dir.*\n",							NULL, {-1, -1, -1, -1, -1, -1}},
X	
X	{"[ ]*pwd[ ]*\n",						NULL, {-1, -1, -1, -1, -1, -1}},
X	/* list */
X	{"[ ]*l.*\n", 							NULL, {-1, -1, -1, -1, -1, -1}},
X	
X	/* forward-search or reverse-search or search */
X	
X	{"[ ]*\\(fo[rward-search]*\\|rev[erse-search]*\\|sea[rch]*\\)[ ]*",
X											NULL, {-1, -1, -1, -1, -1, -1}},
X    
X    /* 'display' is a special case of 'display exp' since it does not
X    add any expression to be displayed */
X	{"[ ]*disp[lay]*[ ]*\n",							NULL, {-1, -1, -1, -1, -1, -1}},
X	{"[ ]*disp[lay]\\(/[^ ]+\\)?*[ ]*[^ ]+[ ]*.*\n",	NULL, {-1, -1, -1, -1, -1, -1}},
X	
X	/* undisplay */
X	{"[ ]*und.*\n",							NULL, {-1, -1, -1, -1, -1, -1}},
X	
X	/* Note that Token.mesg (if any) is updated with print command (see 1) */
X	
X    {"[ ]*print[ ]*\\([^ ]?\\([ ]+[^ ]+\\)*\\)[ ]*\n",	NULL, { 1, -1, -1, -1, -1, -1}},
X    {"[ ]*info[ ]+break[ ]*\n",				NULL, {-1, -1, -1, -1, -1, -1}},
X    
X    /* source (note that Token.TK_FILE is updated here) */
X	{"[ ]*so[urce]*[ ]*\\(.*\\)\n", 		NULL, {-1, -1, -1, -1,  1, -1}},
X	
X    /* exec-file (just used internally) */
X    {"[ ]*exec-file .*\n", 					NULL, {-1, -1, -1, -1, -1, -1}},
X    NULL
X};
END_OF_FILE
if test 16887 -ne `wc -c <'gdb_regex.h'`; then
    echo shar: \"'gdb_regex.h'\" unpacked with wrong size!
fi
# end of 'gdb_regex.h'
fi
if test -f 'source.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'source.c'\"
else
echo shar: Extracting \"'source.c'\" \(21173 characters\)
sed "s/^X//" >'source.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/*  source.c
X *
X *    Create the source window and handle display of file.
X *
X *    source_init(): 	Initialization routine.
X *    Update():		Action proc to update source window on scrollbar action.
X *    NotifyResize():	Action proc to update source window on resize.
X *    CreateSourceWindow(): Create the source window.
X *    BuildLinePos():	Build an array of starting text position of each line.
X *    LookUpFileTable():Check out source file info from a file table.
X *    SaveDisplayedFileInfo(): records displayed file info into file table.
X *    DisplayFile():	Display a file on the source window
X *    LoadFile():	Search for a file and open it for display.
X */
X
X#include <X11/Xos.h>
X#include <sys/stat.h>
X#include <pwd.h>
X#include "global.h"
X
X#define	MAXDIRS	256			/* max number of dirs in dirList */
X
Xchar		CurrentFile[MAXNAME];	/* current contents of file variable */
XWidget		sourceForm,		/* parent of sourceWindow */
X		sourceWindow;		/* text window for source file */
XFileRec  	*displayedFile;		/* pointer to table entry of currently
X					   displayed file */
X
Xstatic FileRec	**fileTable;		/* table of file records */
Xstatic int	fileTableSize;		/* size of file table */
Xstatic char 	*dirList[MAXDIRS];	/* list of dirs for searching files */
X
Xvoid source_init()
X{
X    dirList[0] = NULL;
X}
X
X/*
X *  Update topline, bottomline, arrow sign, updown sign, stop signs, and
X *  line label.
X */
X/* ARGSUSED */
Xvoid Update(w, event, params, num_params)
X    Widget w;
X    XEvent *event;
X    String *params;
X    Cardinal *num_params;
X{
X    XawTextPosition     pos;
X    int			topline;
X    FileRec 		*file;
X
X    if (displayedFile) {
X    	file = displayedFile;
X	pos = XawTextTopPosition(sourceWindow);
X	file->topPosition = pos;
X	topline = TextPositionToLine(pos);
X	/* Update the symbols only if the text scrolls */
X	if (file->topline != topline) {
X	    file->topline = topline;
X	    file->bottomline = MIN (file->topline + file->lines - 1, 
X				    file->lastline);
X	    XawTextSetInsertionPoint(sourceWindow, file->linepos[file->topline]);
X	    UpdateLineLabel(file->topline);
X    	    UpdateStops(file);
X    	    UpdateArrow(file);
X    	    UpdateUpdown(file);
X    	    UpdateBomb(file);
X	}
X	else {/* Update caret position only */
X	    pos = XawTextGetInsertionPoint(sourceWindow);
X	    UpdateLineLabel(TextPositionToLine(pos));
X	}
X    }
X}
X
X/*
X *  Update bottomline, arrow sign, updown sign and stop signs on resize.
X *  Invoked by ConfigureNotify event.
X */
X/* ARGSUSED */
Xstatic void NotifyResize(w, event, params, num_params)
X    Widget w;
X    XEvent *event;
X    String *params;
X    Cardinal *num_params;
X{
X    XawTextPosition pos;
X    TextWidget  ctx = (TextWidget) sourceWindow;
X    FileRec	*file;
X
X    if (file = displayedFile) {
X	file->lines = ctx->text.lt.lines;
X	pos = XawTextTopPosition(sourceWindow);
X	file->topline = TextPositionToLine(pos);
X        file->bottomline = MIN (file->topline + file->lines - 1, 
X				file->lastline);
X        UpdateStops(file);
X        UpdateArrow(file);
X        UpdateUpdown(file);
X        UpdateBomb(file);
X    }
X}
X
X/*  Update the position of the caret */
X/*  ARGSUSED */
X#ifdef notdef
Xvoid UpdateLine(w, event, params, num_params)
X    Widget w;
X    XEvent *event;
X    String *params;
X    Cardinal *num_params;
X{
X    XawTextPosition pos;
X    int	line;
X
X    pos = XawTextGetInsertionPoint(w);
X    line = TextPositionToLine(pos);
X    UpdateLineLabel(line);
X}
X#endif
X
X/*  My select-start routine that cancels the effect of automatic scrolling
X *  near the bottom of an Athena text widget window.
X */
X/*  ARGSUSED */
Xvoid SelectStart(w, event, params, num_params)
X    Widget w;
X    XEvent *event;
X    String *params;
X    Cardinal *num_params;
X{
X    XawTextPosition topPosition;
X
X    /* remember the top display position before automatic scrolling */
X    /* displayedFile->topPosition = XawTextTopPosition(w); */
X    topPosition = XawTextTopPosition(w);
X
X    XtCallActionProc(w, "select-start", event, params, num_params);
X
X    /* reset to remembered position if top position changed */
X    /* if (XawTextTopPosition(w) != displayedFile->topPosition)
X    	TextSetTopPosition(w, displayedFile->topPosition); */
X    if (XawTextTopPosition(w) != topPosition)
X    	TextSetTopPosition(w, topPosition);
X}
X
X/*  My select-end routine to store the text selection into both the PRIMARY
X *  selection and cut buffer 0. 
X */
X/*  ARGSUSED */
Xvoid SelectEnd(w, event, params, num_params)
X    Widget w;
X    XEvent *event;
X    String *params;
X    Cardinal *num_params;
X{
X    XawTextPosition begin, end, start;
X    Widget textsrc;
X    XawTextBlock buffer;
X    char s[10000];
X    int nchars;
X
X    XawTextGetSelectionPos(w, &begin, &end);
X    XawTextSetSelection(w, begin, end);
X    if (begin == end) return;
X    textsrc = XawTextGetSource(w);
X    strcpy(s, "");
X    for (start=begin, nchars=end-begin; nchars > 0; 
X	start=begin+buffer.length, nchars-=buffer.length) {
X    	XawTextSourceRead(textsrc, start, &buffer, nchars);
X	strncat(s, buffer.ptr, buffer.length);
X    }
X    XStoreBytes(display, s, strlen(s));
X}
X
X/*  This is my own select word routine to replace the standard action
X *  procedure provided by the Text widget.
X *  It selects a word delimited by DELIMITERS, not whitespace.
X */
X/* ARGSUSED */
Xvoid SelectWord(w, event, params, num_params)
X    Widget w;
X    XEvent *event;
X    String *params;
X    Cardinal *num_params;
X{
X    XawTextPosition pos, left, right, start;
X    XawTextBlock buffer;
X    Widget	textsrc;
X    char 	s[LINESIZ];
X    char 	*p, *ls, *rs;
X    int		nchars;
X
X    pos = XawTextGetInsertionPoint(w);
X    textsrc = XawTextGetSource(w);
X
X    XawTextSourceRead(textsrc, pos, &buffer, 1);
X    if (buffer.length == 0 || (buffer.length == 1 &&
X	strchr(app_resources.delimiters, (int)*(buffer.ptr)) != NULL)) {
X	XStoreBytes(display, NULL, 0);
X	return;
X    }
X
X    left = XawTextSourceScan(textsrc, pos+1, XawstWhiteSpace, XawsdLeft, 1,
X                             FALSE);
X    right = XawTextSourceScan(textsrc, left, XawstWhiteSpace, XawsdRight, 1,
X                              FALSE);
X    
X    strcpy(s, "");
X    for (start=left, nchars=right-left; nchars > 0; 
X	start=left+buffer.length, nchars-=buffer.length) {
X    	XawTextSourceRead(textsrc, start, &buffer, nchars);
X	strncat(s, buffer.ptr, buffer.length);
X    }
X
X    if (!strcmp(s, "")) return;
X    p = s+pos-left;
X    ls = (char *) strtok(s, app_resources.delimiters);
X    rs = (char *) strtok(NULL, app_resources.delimiters);
X    if (!ls) return;
X    while (rs<=p && rs!=NULL) {
X	ls = rs;
X	rs = (char *) strtok(NULL, app_resources.delimiters);
X    }
X    left = left + ls - s;
X    right = left + strlen(ls) - 1; 
X
X    XawTextUnsetSelection(w);
X    XStoreBytes(display, ls, strlen(ls));
X    XawTextSetSelection(w, left, right+1);
X}
X
X/*  Print the value of the expression  in cut buffer 0. */
X/*  ARGSUSED */
Xvoid PrintSelection(w, event, params, num_params)
X    Widget w;
X    XEvent *event;
X    String *params;
X    Cardinal *num_params;
X{
X    char command[LINESIZ];
X    char *string;
X    int nbytes;
X
X    string = XFetchBytes(display, &nbytes);
X    if (nbytes == 0) {
X        UpdateMessageWindow(PRINT_HELP, NULL);
X        bell(0);
X        return;
X    }
X    sprintf(command, "print %s\n", string);
X    send_command(command);
X    AppendDialogText(command);
X}
X
X/* 
X *  On top of a form widget, we have a text widget with scrollbar, label
X *  widgets for the stop sign, arrow sign, and updown signs.
X */
Xvoid CreateSourceWindow(parent)
XWidget parent;
X{
X    TextWidget ctx;
X    Arg args[MAXARGS];
X    Cardinal n;
X
X    static XtActionsRec sbar_actions[] = {
X        {"NotifyResize",   NotifyResize},
X        {"Update", 	   Update},
X        {NULL, NULL}
X    };
X
X    static String sbarTranslations = "\
X        <Configure>:    NotifyResize() \n\
X        <Btn2Down>:     StartScroll(Continuous) MoveThumb() NotifyThumb() \
X                        Update() \n\
X        <Btn2Motion>:   MoveThumb() NotifyThumb() Update() \n\
X        <BtnUp>:        NotifyScroll(Proportional) EndScroll() Update() \n\
X    ";
X
X    n = 0;
X    XtSetArg(args[n], XtNdefaultDistance, 0);                           n++;
X    sourceForm = XtCreateManagedWidget("sourceForm", formWidgetClass, 
X					 parent, args, n);
X
X    n = 0;
X    XtSetArg(args[n], XtNborderWidth, 0);				n++;
X    XtSetArg(args[n], XtNtype, (XtArgVal)XawAsciiFile);			n++;
X    XtSetArg(args[n], XtNstring, (XtArgVal)"/dev/null");		n++;
X    XtSetArg(args[n], XtNscrollVertical, (XtArgVal) XawtextScrollAlways);n++;
X    sourceWindow = XtCreateManagedWidget("sourceWindow", asciiTextWidgetClass,
X					  sourceForm, args, n);
X
X    ctx = (TextWidget) sourceWindow;
X    if (ctx->text.vbar)
X    	XtOverrideTranslations(ctx->text.vbar, 
X				XtParseTranslationTable(sbarTranslations));
X    XtAppAddActions(app_context, sbar_actions, XtNumber(sbar_actions));
X}
X
X
X/*
X *  Build the array which gives the starting text position of each line.
X *  > Estimate the number of lines in the file and allocate memory buffer.
X *  > Starting position of line #1 is 0, and is stored in linepos[1].
X *  > Search for '\n' till end of buffer.
X */
Xstatic void BuildLinePos(file)
XFileRec *file;
X{
X    char *p;
X    int	 line, nlines;
X
X    nlines = MAX(1, file->filesize/CHARS_PER_LINE);
X    file->linepos = (XawTextPosition *)
X		    XtMalloc ((nlines+2) * sizeof(XawTextPosition));
X    p = file->buf;
X    line = 0;
X    file->linepos[line++] = 0;
X    file->linepos[line++] = 0;
X    while (*p) {
X	if (*p++ == '\n') {
X	    if (line == nlines) { 	/* buffer full, need more memory */
X                file->linepos = (XawTextPosition *) XtRealloc (file->linepos, 
X			  (nlines + ADD_LINES) * sizeof(XawTextPosition));
X		nlines += ADD_LINES;
X            }
X            file->linepos[line++] = p - file->buf;
X	}
X    }
X    file->lastline = line - 2;
X    file->linepos = (XawTextPosition *) XtRealloc 	/* shrink to min size */
X			(file->linepos, line * sizeof(XawTextPosition));
X}
X
X
X/*
X * Look up the file table for an entry with "filename"
X * If not found, create an entry and initialize proper fields,
X * else, return pointer to entry found.
X */
Xstatic LookUpFileTable(pathname, filename, file)
Xchar *pathname, *filename;
XFileRec **file;
X{
X    struct stat fileinfo;
X    int  	fd;
X    int 	i, j, n;
X
X    for (i=0; fileTable && fileTable[i] && i<fileTableSize; i++) {
X	if (strcmp(fileTable[i]->pathname, pathname) == NULL) { /* file found */
X	    if (stat(pathname, &fileinfo) == -1) {
X		UpdateMessageWindow("Error: cannot stat file %s", pathname);
X	        *file = fileTable[i];
X		return 0;
X	    }
X	    if (fileinfo.st_mtime > fileTable[i]->mtime) { /* file modified */
X		XtFree((char *)fileTable[i]->buf);
X		XtFree((char *)fileTable[i]->linepos);
X		XtFree((char *)fileTable[i]);
X		displayedFile = NULL;
X		break;
X	    }
X	    else if (displayedFile && 		/* same as displayed file */
X		     strcmp(pathname, displayedFile->pathname) == 0) {
X		*file = NULL;
X		return 0;
X	    }
X	    else {
X	    	*file = fileTable[i];
X		return 0;
X	    }
X	}
X    }
X
X    /* Record file into file table */
X
X    if (i == fileTableSize) {		/* file table full, enlarge it */
X	fileTableSize += ADD_SIZE;
X	fileTable = (FileRec **) 
X		     XtRealloc (fileTable, fileTableSize * sizeof(FileRec *));
X	for (j=i; j<fileTableSize; j++)
X	    fileTable[j] = NULL;
X    }
X    if ((fd = open(pathname, O_RDONLY)) == -1) {
X	UpdateMessageWindow("Error: cannot open file %s", pathname);
X	return -1;
X    }
X    if (fstat(fd, &fileinfo) == -1) {
X	UpdateMessageWindow("Error: cannot fstat file %s", pathname);
X	close(fd);
X	return -1;
X    }
X    fileTable[i] = (FileRec *) XtMalloc (sizeof(FileRec));
X    fileTable[i]->filesize = fileinfo.st_size + 1;
X    fileTable[i]->mtime = fileinfo.st_mtime;
X    fileTable[i]->buf = XtMalloc((int)fileTable[i]->filesize);
X    if ((n = read(fd, fileTable[i]->buf, (int) fileTable[i]->filesize)) == -1) {
X	UpdateMessageWindow("Error: cannot read file %s", pathname);
X	XtFree(fileTable[i]->buf);
X	XtFree(fileTable[i]);
X	fileTable[i] = NULL;
X	close(fd);
X	return -1;
X    }
X    fileTable[i]->buf[n] = '\0';
X    fileTable[i]->pathname = XtNewString(pathname);
X    fileTable[i]->filename = XtNewString(filename);
X    fileTable[i]->currentline = 1;
X    fileTable[i]->topline = 1;
X    fileTable[i]->bottomline = 0;
X    fileTable[i]->topPosition = 0;
X    BuildLinePos(fileTable[i]);
X    close(fd);
X    *file = fileTable[i];
X    return 0;
X}
X
X/*  
X *  Remember file position and current line before closing.
X */
Xstatic void SaveDisplayedFileInfo()
X{
X    XawTextPosition pos;
X
X    if (displayedFile) {
X    	displayedFile->topPosition = XawTextTopPosition(sourceWindow);
X	pos = XawTextGetInsertionPoint(sourceWindow);
X	displayedFile->currentline = TextPositionToLine(pos);
X    }
X}
X
X
X/*   DisplayFile() displays the file onto the source window.  It
X *     uses topPosition to remember where it was last opened.  But it
X *     must recalculate bottomline because the window size might be
X *     different.
X */
Xstatic void DisplayFile(file)
XFileRec *file;
X{
X    Arg 	args[MAXARGS];
X    Cardinal 	n;
X    TextWidget 	ctx = (TextWidget) sourceWindow;
X
X    n = 0;
X    XtSetArg(args[n], XtNdisplayPosition, (XtArgVal)file->topPosition);	n++;
X    XtSetArg(args[n], XtNstring, (XtArgVal) file->pathname);		n++;
X    XtSetArg(args[n], XtNeditType, (XtArgVal) XawtextRead);		n++;
X    XtSetValues(sourceWindow, args, n);
X    file->lines = ctx->text.lt.lines;
X    file->bottomline = MIN (file->topline + file->lines - 1, file->lastline);
X}
X
X
X/*  Given a filename starting with a tilde (`~'), it expands ~[user] to
X *  the home directory of that user, or to the login home directory if user
X *  is not specified.
X */
Xstatic char *expand(filename)
Xchar *filename;
X{
X    struct passwd *pwd;
X    char 	  *string, *name, newfile[MAXNAME];
X
X    string = XtNewString(filename+1);
X    if (*string == '\0' || *string == '/')
X	name = (char *) getlogin();
X    else
X    	name = (char *) strtok(string, "/");
X    if (name == NULL)
X	return filename;
X    pwd = (struct passwd *) getpwnam(name);
X    if (pwd && pwd->pw_dir) {
X    	sprintf(newfile, "%s%s", pwd->pw_dir, filename+strlen(name)+1);
X    	return XtNewString(newfile);
X    }
X    else
X	return filename;
X}
X
X
X/*  Create a list of directories for searching source files.
X *  It reads the list of directories specified by the user, adding
X *  the current directory into the list if it is not already there.
X *
X *  With fix from Dave Gagne (daveg@fs1.ee.ubc.ca) 7/30/90
X */
Xvoid MakeDirList(output)
Xchar *output;
X{
X    char *s, list[BUFSIZ], command[LINESIZ];
X    int  i, use_cwd;
X
X    for (i=0; dirList[i]; i++)			/* remove old list */
X	XtFree(dirList[i]);
X    i = 0;
X    use_cwd = TRUE;
X    if (output) {                                        /* create list */
X#ifdef GDB	/* GDB uses ':' as separator character */
X        s = (char *) strtok(output, ": \n");
X#else
X        s = (char *) strtok(output, " \n");
X#endif /* GDB */
X        while (s) {
X            dirList[i] = XtNewString(s);
X
X            if (dirList[i][0] == '~')                   /* expand '~' */
X                dirList[i] = expand(dirList[i]);
X            if (LASTCH(dirList[i]) == '/')              /* remove last '/' */
X                LASTCH(dirList[i]) = '\0';
X            if (strcmp(dirList[i], ".") == NULL)        /* watch for "." */
X                use_cwd = FALSE;
X
X            ++i;
X            s = (char *) strtok(NULL, " \n");
X        }
X        dirList[i] = NULL;
X    }
X
X    if (use_cwd) {				/* include current dir */
X	dirList[i++] = XtNewString(".");		
X    	dirList[i] = NULL;
X    }
X    strcpy(list, "");				/* tell dbx our new list */
X    for (i=0; dirList[i]; i++) {
X	strcat(list, dirList[i]);
X	strcat(list, " ");
X    }
X#ifdef GDB
X    sprintf(command, "directory %s\n", list);
X#else
X    sprintf(command, "use %s\n", list);
X#endif /* GDB */
X    Parse = False;
X    query_dbx(command);
X}
X
X
X/*  Returns the full pathname of a given file.
X *  It searches for the file from a list of directories.
X */
Xchar *GetPathname(filename)
Xchar *filename;
X{
X    char	pathname[LINESIZ];
X    int 	i;
X
X    if (filename == NULL || strcmp(filename, "") == NULL)
X	return NULL;
X    for (i=0; dirList[i]; i++) {
X	if (*filename == '/' && access(filename, R_OK) == -1) { 
X	    /* this handles the exceptional case of sun4 dbx output */
X	    strcpy(filename, &filename[1]);
X	}
X	if (*filename == '/' || *filename == '~')
X	     strcpy(pathname, filename);
X	else if (strcmp(dirList[i], ".") == NULL)
X	     sprintf(pathname, "%s/%s", cwd, filename);
X	else if (*dirList[i] == '/' || *dirList[i] == '~')
X	     sprintf(pathname, "%s/%s", dirList[i], filename);
X	else
X	     sprintf(pathname, "%s/%s/%s", cwd, dirList[i], filename);
X	if (access(pathname, R_OK) == 0)
X	    return XtNewString(pathname);
X    }
X    UpdateMessageWindow("File not found: %s", filename);
X    return NULL;
X}
X
X/*
X * Given a file name, LoadFile attempts to open it and displays it onto
X * the source window:
X *   1. get the full pathname of the file
X *   2. LookUpFileTable() returns a pointer to the file's entry if it's
X *      already in the table; else, creates an entry and return a pointer.
X *   3. save the current displayedFile info
X *   4. display the file
X *   5. update the file label and the various signs on the source window.
X *  LoadFile returns 0 upon successful completion, -1 otherwise.
X */
Xint LoadFile(filename)
Xchar *filename;
X{
X    FileRec 	*file;
X    char	*pathname;
X
X    pathname = GetPathname(filename);
X    if (pathname == NULL) { 
X	return -1;
X    }
X    if (LookUpFileTable(pathname, filename, &file) != -1) {
X	if (file) {	/* load new file */
X	    SaveDisplayedFileInfo();
X	    DisplayFile(file);
X	    UpdateFileLabel(pathname);
X	    XawTextUnsetSelection(sourceWindow);
X	    XawTextSetInsertionPoint(sourceWindow, file->linepos[file->currentline]);
X	    UpdateLineLabel(file->currentline);
X	    UpdateStops(file);
X	    UpdateArrow(file);
X	    UpdateUpdown(file);
X	    UpdateBomb(file);
X	    displayedFile = file;
X	}
X    	return 0;
X    }
X    else {		/* LookUpFileTable() fails */
X    	return -1;
X    }
X}
X
Xint LoadCurrentFile()
X{
X#ifdef GDB
X    query_dbx("info line\n");
X#else
X    query_dbx("file\n");
X#endif /* GDB */
X    return LoadFile(CurrentFile);
X}
END_OF_FILE
if test 21173 -ne `wc -c <'source.c'`; then
    echo shar: \"'source.c'\" unpacked with wrong size!
fi
# end of 'source.c'
fi
echo shar: End of archive 6 \(of 8\).
cp /dev/null ark6isdone
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

