REPOST: v11i051: xxgdb - X front end for gdb, Part04/08
Pierre Willard
pierre at tce.COM
Wed Mar 27 14:13:18 AEST 1991
Submitted-by: pierre at 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 at 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 at 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
--
Dan Heller
------------------------------------------------
O'Reilly && Associates Z-Code Software
Senior Writer President
argv at ora.com argv at zipcode.com
------------------------------------------------
General Email: argv at sun.com
Comp-sources-x stuff: comp-sources.x at uunet.uu.net
More information about the Comp.sources.x
mailing list