Added GNU gdb to src/gnu

This commit is contained in:
Nate Williams 1993-06-29 09:48:26 +00:00
parent c579b1a9ed
commit 3edf564a32
82 changed files with 60574 additions and 0 deletions

249
gnu/usr.bin/gdb/COPYING Normal file
View file

@ -0,0 +1,249 @@
GNU GENERAL PUBLIC LICENSE
Version 1, February 1989
Copyright (C) 1989 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The license agreements of most software companies try to keep users
at the mercy of those companies. By contrast, our General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. The
General Public License applies to the Free Software Foundation's
software and to any other program whose authors commit to using it.
You can use it for your programs, too.
When we speak of free software, we are referring to freedom, not
price. Specifically, the General Public License is designed to make
sure that you have the freedom to give away or sell copies of free
software, that you receive source code or can get it if you want it,
that you can change the software or use pieces of it in new free
programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of a such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must tell them their rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any program or other work which
contains a notice placed by the copyright holder saying it may be
distributed under the terms of this General Public License. The
"Program", below, refers to any such program or work, and a "work based
on the Program" means either the Program or any work containing the
Program or a portion of it, either verbatim or with modifications. Each
licensee is addressed as "you".
1. You may copy and distribute verbatim copies of the Program's source
code as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this
General Public License and to the absence of any warranty; and give any
other recipients of the Program a copy of this General Public License
along with the Program. You may charge a fee for the physical act of
transferring a copy.
2. You may modify your copy or copies of the Program or any portion of
it, and copy and distribute such modifications under the terms of Paragraph
1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating that
you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish, that
in whole or in part contains the Program or any part thereof, either
with or without modifications, to be licensed at no charge to all
third parties under the terms of this General Public License (except
that you may choose to grant warranty protection to some or all
third parties, at your option).
c) If the modified program normally reads commands interactively when
run, you must cause it, when started running for such interactive use
in the simplest and most usual way, to print or display an
announcement including an appropriate copyright notice and a notice
that there is no warranty (or else, saying that you provide a
warranty) and that users may redistribute the program under these
conditions, and telling the user how to view a copy of this General
Public License.
d) You may charge a fee for the physical act of transferring a
copy, and you may at your option offer warranty protection in
exchange for a fee.
Mere aggregation of another independent work with the Program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other work under the scope of these terms.
3. You may copy and distribute the Program (or a portion or derivative of
it, under Paragraph 2) in object code or executable form under the terms of
Paragraphs 1 and 2 above provided that you also do one of the following:
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal charge
for the cost of distribution) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
Source code for a work means the preferred form of the work for making
modifications to it. For an executable file, complete source code means
all the source code for all modules it contains; but, as a special
exception, it need not include source code for modules which are standard
libraries that accompany the operating system on which the executable
file runs, or for standard header files or definitions files that
accompany that operating system.
4. You may not copy, modify, sublicense, distribute or transfer the
Program except as expressly provided under this General Public License.
Any attempt otherwise to copy, modify, sublicense, distribute or transfer
the Program is void, and will automatically terminate your rights to use
the Program under this License. However, parties who have received
copies, or rights to use copies, from you under this General Public
License will not have their licenses terminated so long as such parties
remain in full compliance.
5. By copying, distributing or modifying the Program (or any work based
on the Program) you indicate your acceptance of this license to do so,
and all its terms and conditions.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the original
licensor to copy, distribute or modify the Program subject to these
terms and conditions. You may not impose any further restrictions on the
recipients' exercise of the rights granted herein.
7. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of the license which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
the license, you may choose any version ever published by the Free Software
Foundation.
8. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to humanity, the best way to achieve this is to make it
free software which everyone can redistribute and change under these
terms.
To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively convey
the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19xx name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the
appropriate parts of the General Public License. Of course, the
commands you use may be called something other than `show w' and `show
c'; they could even be mouse-clicks or menu items--whatever suits your
program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
program `Gnomovision' (a program to direct compilers to make passes
at assemblers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
That's all there is to it!

4887
gnu/usr.bin/gdb/ChangeLog Normal file

File diff suppressed because it is too large Load diff

15
gnu/usr.bin/gdb/Gdbinit Normal file
View file

@ -0,0 +1,15 @@
echo Setting up the environment for debugging gdb.\n
b fatal
b info_command
commands
silent
return
end
define rr
run
end
set prompt (top-gdb)

38
gnu/usr.bin/gdb/Makefile Normal file
View file

@ -0,0 +1,38 @@
# @(#)Makefile 6.4 (Berkley) 5/6/91
PROG= gdb
GDBSRCS= blockframe.c breakpoint.c command.c copying.c core.c \
cplus-dem.c dbxread.c environ.c eval.c expprint.c \
expread.y findvar.c infcmd.c inflow.c infrun.c \
main.c obstack.c printcmd.c regex.c remote.c \
remote-sl.c source.c stack.c symmisc.c symtab.c \
utils.c valarith.c valops.c valprint.c values.c \
version.c
READLINESRCS= funmap.c history.c keymaps.c readline.c
SRCS= $(CONFIGSRCS) $(GDBSRCS) $(READLINESRCS) init.c
CFLAGS+= -I. -I$(.CURDIR) -I$(.CURDIR)/config -I$(.CURDIR)/readline \
-DHAVE_VPRINTF -DVI_MODE -DKERNELDEBUG -DNEWVM
LDADD= -ltermcap
YFLAGS=
.PATH: $(.CURDIR)/config $(.CURDIR)/readline
depend:
.include "config/Makefile.$(MACHINE)"
.include <bsd.prog.mk>
$(OBJS): param.h
#
# Generate the constructor
#
init.c: $(CONFIGSRCS) $(GDBSRCS) $(READLINESRCS)
-((cd $(.CURDIR)/config; \
egrep -h '^_initialize_[^ ]* *\(\)' $(CONFIGSRCS)); \
(cd $(.CURDIR); egrep -h '^_initialize_[^ ]* *\(\)' $(GDBSRCS)); \
(cd $(.CURDIR)/readline; \
egrep -h '^_initialize_[^ ]* *\(\)' $(READLINESRCS))) | \
(echo 'void initialize_all_files () {'; sed -e 's/$$/;/'; echo '}') \
> init.c
CLEANFILES+= init.c param.h

View file

@ -0,0 +1,371 @@
/* This file should be run through the C preprocessor by config.gdb
to produce the Makefile. */
/* Define this to xgdb if you want to compile xgdb as well as gdb. */
XGDB=
/* Place to install binaries. */
bindir=/usr/local/bin
/* Place to install X binaries. */
xbindir=$(bindir)
/* System V: If you compile gdb with a compiler which uses the coff
encapsulation feature (this is a function of the compiler used, NOT
of the m-?.h file selected by config.gdb), you must make sure that
the GNU nm is the one that is used by munch. */
/* If you are compiling with GCC, make sure that either 1) You use the
-traditional flag, or 2) You have the fixed include files where GCC
can reach them. Otherwise the ioctl calls in inflow.c and readline.c
will be incorrectly compiled. The "fixincludes" script in the gcc
distribution will fix your include files up. */
/* CC=gcc -traditional */
CC=cc
/* It is also possible that you will need to add -I/usr/include/sys to the
CFLAGS section if your system doesn't have fcntl.h in /usr/include (which
is where it should be according to Posix). */
YACC=bison -y -v
/* YACC=yacc */
SHELL=/bin/sh
MAKE=make
/* Set this up with gcc if you have gnu ld and the loader will print out
line numbers for undefinded refs. */
/* CC-LD=gcc -static */
CC-LD=${CC}
/* If you are using the GNU C library, uncomment the following line. */
/* HAVE_VPRINTF_DEFINE = -DHAVE_VPRINTF */
/* -I. for "#include <obstack.h>". Possibly regex.h also. */
/* M_CFLAGS, if defined, has system-dependent CFLAGS. */
#if !defined(M_CFLAGS)
#define M_CFLAGS
#endif
/* CFLAGS for both GDB and readline. */
GLOBAL_CFLAGS = -g M_CFLAGS
CFLAGS = -I. ${HAVE_VPRINTF_DEFINE} ${GLOBAL_CFLAGS}
/* None of the things in CFLAGS will do any harm, and on some systems
(e.g. SunOS4) it is important to use the M_CFLAGS. */
LDFLAGS = $(CFLAGS)
/*
define this to be "obstack.o" if you don't have the obstack library installed
you must at the same time define OBSTACK1 as "obstack.o"
so that the dependencies work right. Similarly with REGEX and "regex.o".
You must define REGEX and REGEX1 on USG machines.
If your sysyem is missing alloca(), or, more likely, it's there but
it doesn't work, define ALLOCA & ALLOCA1 */
OBSTACK = obstack.o
OBSTACK1 = obstack.o
#ifdef M_REGEX
REGEX = M_REGEX
REGEX1 = M_REGEX
#else
REGEX =
REGEX1 =
#endif
#ifdef M_ALLOCA
ALLOCA = M_ALLOCA
ALLOCA1 = M_ALLOCA
#else
ALLOCA =
ALLOCA1 =
#endif
/*
define this to be "malloc.o" if you want to use the gnu malloc routine
(useful for debugging memory allocation problems in gdb). Otherwise, leave
it blank. */
/* GNU_MALLOC = */
GNU_MALLOC = malloc.o
/* Flags to be used in compiling malloc.o
Specify range checking for storage allocation. */
/* MALLOC_FLAGS = ${CFLAGS} */
MALLOC_FLAGS = ${CFLAGS} -Drcheck -Dbotch=fatal_dump_core -DMSTATS
/* Define SYSV if compiling on a system V or HP machine. */
#ifdef M_SYSV
SYSV_DEFINE = -DSYSV
#else
SYSV_DEFINE =
#endif
/* MUNCH_DEFINE should be -DSYSV if have System V-style nm,
or null if have BSD-style nm. */
#ifdef M_BSD_NM
MUNCH_DEFINE =
#else
MUNCH_DEFINE = ${SYSV_DEFINE}
#endif
/* Flags that describe where you can find the termcap library.
You may need to make other arrangements for USG. */
TERMCAP = -ltermcap
/* M_CLIBS, if defined, has system-dependent libs
For example, -lPW for System V to get alloca(). */
#ifndef M_CLIBS
#define M_CLIBS
#endif
CLIBS = ${ADD_FILES} ${TERMCAP} M_CLIBS
ADD_FILES = ${OBSTACK} ${REGEX} ${ALLOCA} ${GNU_MALLOC}
ADD_DEPS = ${OBSTACK1} ${REGEX1} ${ALLOCA1} ${GNU_MALLOC}
SFILES = blockframe.c breakpoint.c dbxread.c coffread.c command.c core.c \
environ.c eval.c expprint.c findvar.c infcmd.c inflow.c infrun.c \
kdb-start.c main.c printcmd.c \
remote.c source.c stack.c standalone.c stuff.c symmisc.c symtab.c \
utils.c valarith.c valops.c valprint.c values.c version.c expread.y \
xgdb.c
DEPFILES = umax-dep.c gould-dep.c default-dep.c sun3-dep.c \
sparc-dep.c hp9k320-dep.c hp300bsd-dep.c news-dep.c i386-dep.c \
symmetry-dep.c convex-dep.c altos-dep.c isi-dep.c pyr-dep.c
PINSNS = gld-pinsn.c i386-pinsn.c sparc-pinsn.c vax-pinsn.c m68k-pinsn.c \
ns32k-pinsn.c convex-pinsn.c pyr-pinsn.c
HFILES = command.h defs.h environ.h expression.h frame.h getpagesize.h \
inferior.h symseg.h symtab.h value.h wait.h \
a.out.encap.h a.out.gnu.h stab.gnu.h
OPCODES = m68k-opcode.h pn-opcode.h sparc-opcode.h npl-opcode.h vax-opcode.h \
ns32k-opcode.h convex-opcode.h pyr-opcode.h
MFILES = m-hp9k320.h m-hp300bsd.h m-i386.h m-i386gas.h \
m-i386-sv32.h m-i386g-sv32.h m-isi.h m-merlin.h \
m-altos.h m-news.h m-newsos3.h m-npl.h m-pn.h \
m-sparc.h m-sun2.h m-sun3.h m-sun2os4.h \
m-sun3os4.h m-sun4os4.h m-umax.h m-vax.h m-symmetry.h m-convex.h \
m-pyr.h
/* This list of files really shouldn't be in this makefile, but I can't think
of any good way to get the readline makefile to tell us what files
to put in our tarfile. */
READLINE = readline.c history.c funmap.c \
emacs_keymap.c vi_keymap.c vi_mode.c keymaps.c \
readline.h history.h keymaps.h chardefs.h \
inc-readline.texinfo inc-history.texinfo \
readline.texinfo history.texinfo \
Makefile ChangeLog
REMOTE_EXAMPLES = remote-sa.m68k.shar remote-multi.shar
POSSLIBS = obstack.h obstack.c regex.c regex.h malloc.c alloca.c
TESTS = testbpt.c testfun.c testrec.c testreg.c testregs.c
OTHERS = Makefile.dist createtags munch config.gdb ChangeLog README TAGS \
gdb.texinfo .gdbinit COPYING expread.tab.c stab.def \
XGDB-README copying.c Projects Convex.notes copying.awk hp-include
TAGFILES = ${SFILES} ${DEPFILES} ${PINSNS} ${HFILES} ${OPCODES} ${MFILES} \
${POSSLIBS}
TARFILES = ${TAGFILES} ${OTHERS} ${REMOTE_EXAMPLES}
OBS = main.o blockframe.o breakpoint.o findvar.o stack.o source.o \
values.o eval.o valops.o valarith.o valprint.o printcmd.o \
symtab.o symmisc.o coffread.o dbxread.o infcmd.o infrun.o remote.o \
command.o utils.o expread.o expprint.o pinsn.o environ.o version.o \
copying.o ${READLINEOBS}
TSOBS = core.o inflow.o dep.o
NTSOBS = standalone.o
TSSTART = /lib/crt0.o
NTSSTART = kdb-start.o
RL_LIB = readline/libreadline.a
/* Do some fancy trickery to produce a line like
-DM_MAKEDEFINE="-DM_SYSV -DM_BSD_NM".
*/
MD=M_MAKEDEFINE
/* Avoid funny things that Sun's make throws in for us. */
/* TARGET_ARCH is supposed to get around it putting in the machine type.
If the "things" up there really is plural, we'll need to do something
else as well. */
/*.c.o:
${CC} -c ${CFLAGS} $< */
TARGET_ARCH=
all: gdb $(XGDB)
install: gdb $(XGDB)
cp gdb $(bindir)/gdb.new
mv $(bindir)/gdb.new $(bindir)/gdb
-if [ "$(XGDB)" = xgdb ]; then \
cp xgdb $(xbindir)/xgdb.new; \
mv $(xbindir)/xgdb.new $(xbindir)xgdb; \
fi
gdb : $(OBS) $(TSOBS) ${ADD_DEPS} ${RL_LIB}
rm -f init.c
./munch ${MUNCH_DEFINE} $(OBS) $(TSOBS) > init.c
${CC-LD} $(LDFLAGS) -o gdb init.c $(OBS) $(TSOBS) ${RL_LIB} $(CLIBS)
/* This is useful when debugging GDB, because Unix doesn't let you run GDB
on itself without copying the executable. So "make gdb1" will make
gdb and put a copy in gdb1, and you can run it with "gdb gdb1". */
gdb1 : gdb
cp gdb gdb1
Makefile : Makefile.dist
cp Makefile.dist tmp.c
$(CC) -E >Makefile tmp.c $(MD) "-DM_MAKEDEFINE=$(MD)"
-rm tmp.c
/* This did not work-- -Usparc became "-Usparc" became "-Usparc.
Or something like that. */
/* $(CC) -E >Makefile tmp.c $(MD) "-DM_MAKEDEFINE=\"$(MD)\"" */
xgdb : $(OBS) $(TSOBS) xgdb.o ${ADD_DEPS} ${RL_LIB}
rm -f init.c
./munch ${MUNCH_DEFINE} $(OBS) $(TSOBS) xgdb.o > init.c
$(CC-LD) $(LDFLAGS) -o xgdb init.c $(OBS) $(TSOBS) xgdb.o \
-lXaw -lXmu -lXt -lX11 ${RL_LIB} $(CLIBS)
/* Old (pre R3) xgdb comp.
$(CC-LD) $(LDFLAGS) -o xgdb init.c $(OBS) $(TSOBS) xgdb.o \
-lXaw -lXt -lX11 $(CLIBS) */
kdb : $(NTSSTART) $(OBS) $(NTSOBS) ${ADD_DEPS} ${RL_LIB}
rm -f init.c
./munch ${MUNCH_DEFINE} $(OBS) $(NTSOBS) > init.c
$(CC) $(LDFLAGS) -c init.c $(CLIBS)
ld -o kdb $(NTSSTART) $(OBS) $(NTSOBS) init.o ${RL_LIB} -lc $(CLIBS)
/* If it can figure out the appropriate order, createtags will make sure
that the proper m-*, *-dep, *-pinsn, and *-opcode files come first
in the tags list. It will attempt to do the same for dbxread.c and
coffread.c. This makes using M-. on machine dependent routines much
easier. */
TAGS: ${TAGFILES}
createtags ${TAGFILES}
tags: TAGS
gdb.tar: ${TARFILES}
rm -f gdb.tar
mkdir dist-gdb
cd dist-gdb ; for i in ${TARFILES} ; do ln -s ../$$i . ; done
mkdir dist-gdb/readline
cd dist-gdb/readline ; for i in ${READLINE} ; do ln -s ../../readline/$$i . ; done
tar chf gdb.tar dist-gdb
rm -rf dist-gdb
/* Remove gdb.tar.Z so stupid compress doesn't ask whether we want to
overwrite it. compress -f is not what we want, because we do want
to know if compress would not make it smaller. */
gdb.tar.Z: gdb.tar
if [ -f gdb.tar.Z ]; then rm -f gdb.tar.Z; else true; fi
compress gdb.tar
clean:
rm -f ${OBS} ${TSOBS} ${NTSOBS} ${OBSTACK} ${REGEX} ${GNU_MALLOC}
rm -f init.c init.o
rm -f xgdb.o xgdb
rm -f gdb core gdb.tar gdb.tar.Z make.log
rm -f gdb[0-9]
cd readline ; make clean
distclean: clean expread.tab.c TAGS
rm -f dep.c opcode.h param.h pinsn.c config.status
rm -f y.output yacc.acts yacc.tmp
rm -f ${TESTS} Makefile
realclean: clean
rm -f expread.tab.c TAGS
rm -f dep.c opcode.h param.h pinsn.c config.status
rm -f Makefile
xgdb.o : defs.h param.h symtab.h frame.h
/* Make copying.c from COPYING */
copying.c : COPYING copying.awk
awk -f copying.awk < COPYING > copying.c
expread.tab.c : expread.y
@echo 'Expect 4 shift/reduce conflict.'
${YACC} expread.y
mv y.tab.c expread.tab.c
expread.o : expread.tab.c defs.h param.h symtab.h frame.h expression.h
$(CC) -c ${CFLAGS} expread.tab.c
mv expread.tab.o expread.o
readline/libreadline.a : force_update
cd readline ; ${MAKE} "SYSV=${SYSV_DEFINE}" \
"DEBUG_FLAGS=${GLOBAL_CFLAGS}" "CC=${CC}" libreadline.a
force_update :
/* Only useful if you are using the gnu malloc routines. */
malloc.o : malloc.c
${CC} -c ${MALLOC_FLAGS} malloc.c
/* dep.o depends on config.status in case someone reconfigures gdb out
from under an already compiled gdb. */
dep.o : dep.c config.status defs.h param.h frame.h inferior.h obstack.h \
a.out.encap.h
/* pinsn.o depends on config.status in case someone reconfigures gdb out
from under an already compiled gdb. */
pinsn.o : pinsn.c config.status defs.h param.h symtab.h obstack.h symseg.h \
frame.h opcode.h
/* The rest of this is a standard dependencies list (hand edited output of
cpp -M). It does not include dependencies of .o files on .c files. */
/* All files which depend on config.status also depend on param.h in case
someone reconfigures gdb out from under an already compiled gdb. */
blockframe.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h
breakpoint.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h
coffread.o : defs.h param.h config.status
command.o : command.h defs.h
core.o : defs.h param.h config.status a.out.encap.h
dbxread.o : param.h config.status defs.h symtab.h obstack.h symseg.h a.out.encap.h \
stab.gnu.h
environ.o : environ.h
eval.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h expression.h
expprint.o : defs.h symtab.h obstack.h symseg.h param.h config.status expression.h
findvar.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h value.h
infcmd.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h inferior.h \
environ.h value.h
inflow.o : defs.h param.h config.status frame.h inferior.h
infrun.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h inferior.h \
wait.h
kdb-start.o : defs.h param.h config.status
main.o : defs.h command.h param.h config.status
malloc.o : getpagesize.h
obstack.o : obstack.h
printcmd.o : defs.h param.h config.status frame.h symtab.h obstack.h symseg.h value.h \
expression.h
regex.o : regex.h
remote.o : defs.h param.h config.status frame.h inferior.h wait.h
source.o : defs.h symtab.h obstack.h symseg.h param.h config.status
stack.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h
standalone.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h \
inferior.h wait.h
symmisc.o : defs.h symtab.h obstack.h symseg.h obstack.h
symtab.o : defs.h symtab.h obstack.h symseg.h param.h config.status obstack.h
utils.o : defs.h param.h config.status
valarith.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h expression.h
valops.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h frame.h \
inferior.h
valprint.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h
values.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h
robotussin.h : getpagesize.h
symtab.h : obstack.h symseg.h
a.out.encap.h : a.out.gnu.h

114
gnu/usr.bin/gdb/Projects Normal file
View file

@ -0,0 +1,114 @@
Suggested projects for aspiring or current GDB hackers
======================================================
(You should probably chat with kingdon@ai.mit.edu to make sure that
no one else is doing the project you chose).
Add watchpoints (break if a memory location changes). This would
usually have to involve constant single stepping, but occasionally
there is operating system support which gdb should be able to cleanly
use (e.g. on the 80386, there are 4 debug registers. By ptracing an
address into them, you can get a trap on writes or on reads and
writes).
Rewrite proceed, wait_for_inferior, and normal_stop to clean them up.
Suggestions:
1) Make each test in wait_for_inferior a seperate subroutine
call.
2) Combine wait_for_inferior and normal_stop to clean up
communication via global variables.
3) See if you can find some way to clean up the global
variables that are used; possibly group them by data flow
and information content?
Work out some kind of way to allow running the inferior to be done as
a sub-execution of, eg. breakpoint command lists. Currently running
the inferior interupts any command list execution. This would require
some rewriting of wait_for_inferior & friends, and hence should
probably be done in concert with the above.
Add function arguments to gdb user defined functions.
Add convenience variables that refer to exec file, symbol file,
selected frame source file, selected frame function, selected frame
line number, etc.
Add a "suspend" subcommand of the "continue" command to suspend gdb
while continuing execution of the subprocess. Useful when you are
debugging servers and you want to dodge out and initiate a connection
to a server running under gdb.
Make "handle" understand symbolic signal names.
Work out and implement a reasonably general mechanism for multi-threaded
processies. There are parts of one implemented in convex-dep.c, if
you want an example.
A standalone version of gdb on the i386 exists. Anyone who wants to
do some serious working cleaning it up and making it a general
standalone gdb should contact pace@wheaties.ai.mit.edu.
Add stab information to allow reasonable debugging of inline functions
(possibly they should show up on a stack backtrace? With a note
indicating that they weren't "real"?).
Implement support for specifying arbitrary locations of stack frames
(in practice, this usually requires specification of both the top and
bottom of the stack frame (fp and sp), since you *must* retrieve the
pc that was saved in the innermost frame).
Modify the naked "until" command to step until past the current source
line, rather than past the current pc value. This is tricky simply
because the low level routines have no way of specifying a multi-line
step range, and there is no way of saying "don't print stuff when we
stop" from above (otherwise could just call step many times).
Modify the handling of symbols grouped through BINCL/EINCL stabs to
allocate a partial symtab for each BINCL/EINCL grouping. This will
seriously decrease the size of inter-psymtab dependencies and hence
lessen the amount that needs to be read in when a new source file is
accessed.
Work out some method of saving breakpoints across the reloading of an
executable. Probably this should be by saving the commands by which
the breakpoints were set and re-executing them (as text locations may
change).
Do an "x/i $pc" after each stepi or nexti.
Modify all of the disassemblers to use printf_filtered to get correct
more filtering.
Modify gdb to work correctly with Pascal.
Rewrite macros that handle frame chaining and frameless functions.
They should be able to tell the difference between start, main, and a
frameless function called from main.
Work out what information would need to be included in an executable
by the compiler to allow gdb to debug functions which do not have a
frame pointer. Modify gdb and gcc to do this.
When `attached' to a program (via either OS support or remote
debugging), gdb should arrange to catch signals which the terminal
might send, as it is unlikely that the program will be able to notice
them. SIGINT and SIGTSTP are obvious examples.
Enhance the gdb manual with extra examples where needed.
Arrange for list_command not to use decode_line_1 and thus not require
symbols to be read in simply to read a source file.
Problem in xgdb; the readline library needs the terminal in CBREAK
mode for command line editing, but this makes it difficult to dispatch
on button presses. Possible solution: use a define to replace getc in
readline.c with a routine that does button dispatches. You should
probably see XGDB-README before you fiddle with XGDB. Also, someone
is implementing a new xgdb; it may not be worth while fiddling with
the old one.
# Local Variables:
# mode: text
# End:

142
gnu/usr.bin/gdb/README.gnu Normal file
View file

@ -0,0 +1,142 @@
This is GDB, the GNU source-level debugger, presently running under un*x.
Before compiling GDB, you must tell GDB what kind of machine you are
running on. To do this, type `config.gdb machine', where machine is
something like `vax' or `sun2'. For a list of valid machine types,
type `config.gdb'.
Normally config.gdb edits the makefile as necessary. If you have to
edit the makefile on a standard machine listed in config.gdb this
should be considered a bug and reported as such.
Once these files are set up, just `make' will do everything,
producing an executable `gdb' in this directory.
If you want a new (current to this release) version of the manual, you
will have to use the gdb.texinfo file provided with this distribution.
The gdb.texinfo file requires the texinfo-format-buffer command from
emacs 18.55 or later.
About languages other than C...
C++ support has been integrated into gdb. GDB should work with
FORTRAN programs (if you have problem, please send a bug report), but
I am not aware of anyone who is working on getting it to use the
syntax of any language other than C or C++. Pascal programs which use
sets, subranges, file variables, or nested functions will not
currently work.
About -gg format...
Currently GDB version 3.x does *not* support GCC's -gg format. This
is because it (in theory) has fast enough startup on dbx debugging
format object files that -gg format is unnecessary (and hence
undesirable, since it wastes space and processing power in gcc). I
would like to hear people's opinions on the amount of time currently
spent in startup; is it fast enough?
About remote debugging...
The two files remote-multi.shar and remote-sa.m68k.shar contain two
examples of a remote stub to be used with remote.c. The the -multi
file is a general stub that can probably be running on various
different flavors of unix to allow debugging over a serial line from
one machine to another. The remote-sa.m68k.shar is designed to run
standalone on a 68k type cpu and communicate properley with the
remote.c stub over a serial line.
About reporting bugs...
The correct address for reporting bugs found with gdb is
"bug-gdb@prep.ai.mit.edu". Please send all bugs to that address.
About xgdb...
xgdb.c was provided to us by the user community; it is not an integral
part of the gdb distribution. The problem of providing visual
debugging support on top of gdb is peripheral to the GNU project and
(at least right now) we can't afford to put time into it. So while we
will be happy to incorporate user fixes to xgdb.c, we do not guarantee
that it will work and we will not fix bugs reported in it. Someone is
working on writing a new XGDB, so improving (e.g. by fixing it so that
it will work, if it doesn't currently) the current one is not worth it.
For those intersted in auto display of source and the availability of
an editor while debugging I suggest trying gdb-mode in gnu-emacs.
Comments on this mode are welcome.
About the machine-dependent files...
m-<machine>.h (param.h is a link to this file).
This file contains macro definitions that express information
about the machine's registers, stack frame format and instructions.
<machine>-opcode.h (opcode.h is a link to this file).
<machine>-pinsn.c (pinsn.c is a link to this file).
These files contain the information necessary to print instructions
for your cpu type.
<machine>-dep.c (dep.c is a link to this file).
Those routines which provide a low level interface to ptrace and which
tend to be machine-dependent. (The machine-independent routines are in
`infrun.c' and `inflow.c')
About writing code for GDB...
We appreciate having users contribute code that is of general use, but
for it to be included in future GDB releases it must be cleanly
written. We do not want to include changes that will needlessly make future
maintainance difficult. It is not much harder to do things right, and
in the long term it is worth it to the GNU project, and probably to
you individually as well.
Please code according to the GNU coding standards. If you do not have
a copy, you can request one by sending mail to gnu@prep.ai.mit.edu.
Please try to avoid making machine-specific changes to
machine-independent files (i.e. all files except "param.h" and
"dep.c". "pinsn.c" and "opcode.h" are processor-specific but not
operating system-dependent). If this is unavoidable, put a hook in
the machine-independent file which calls a (possibly)
machine-dependent macro (for example, the IGNORE_SYMBOL macro can be
used for any symbols which need to be ignored on a specific machine.
Calling IGNORE_SYMBOL in dbxread.c is a lot cleaner than a maze of #if
defined's). The machine-independent code should do whatever "most"
machines want if the macro is not defined in param.h. Using #if
defined can sometimes be OK (e.g. SET_STACK_LIMIT_HUGE) but should be
conditionalized on a specific feature of an operating system (set in
param.h) rather than something like #if defined(vax) or #if
defined(SYSV).
It is better to replace entire routines which may be system-specific,
rather than put in a whole bunch of hooks which are probably not going
to be helpful for any purpose other than your changes. For example,
if you want to modify dbxread.c to deal with DBX debugging symbols
which are in COFF files rather than BSD a.out files, do something
along the lines of a macro GET_NEXT_SYMBOL, which could have
different definitions for COFF and a.out, rather than trying to put
the necessary changes throughout all the code in dbxread.c that
currently assumes BSD format.
Please avoid duplicating code. For example, if something needs to be
changed in read_inferior_memory, it is very painful because there is a
copy in every dep.c file. The correct way to do this is to put (in
this case) the standard ptrace interfaces in a separate file ptrace.c,
which is used by all systems which have ptrace. ptrace.c would deal
with variations between systems the same way any system-independent
file would (hooks, #if defined, etc.).
About debugging gdb with itself...
You probably want to do a "make TAGS" after you configure your
distribution; this will put the machine dependent routines for your
local machine where they will be accessed first by a M-period .
Also, make sure that you've compiled gdb with your local cc or taken
appropriate precautions regarding ansification of include files. See
the Makefile for more information.
The "info" command, when executed without a subcommand in a gdb being
debugged by gdb, will pop you back up to the top level gdb. See
.gdbinit for more details.

View file

@ -0,0 +1,15 @@
button "show" push-to-file %S
button "back" pop-file
button "break in" break %S
button "break at" break %l
button delete delete %b%e
button backtrace
button up
button down
button print print %E
button print* print *(%E)
button next
button step
button "do upto" until %l%e
button finish
button continue cont%e

8
gnu/usr.bin/gdb/Xgdb.ad Normal file
View file

@ -0,0 +1,8 @@
Xgdb*geometry: 580x874-0+28
Xgdb*src*scrollVertical: whenneeded
Xgdb*src*scrollHorizontal: whenneeded
Xgdb*src*wrap: never
Xgdb*src*editType: read
Xgdb*frame.buttons.allowResize: true
Xgdb*frame.buttons.skipAdjust: true
Xgdb*frame*showGrip: false

View file

@ -0,0 +1,622 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
* Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
*/
#ifndef lint
static char sccsid[] = "@(#)blockframe.c 6.4 (Berkeley) 5/11/91";
#endif /* not lint */
/* Get info from stack frames;
convert between frames, blocks, functions and pc values.
Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "param.h"
#include "symtab.h"
#include "frame.h"
#include <obstack.h>
#if defined(NEWVM) && defined(KERNELDEBUG)
#include <sys/param.h> /* XXX for FRAME_CHAIN_VALID */
#endif
/* Start and end of object file containing the entry point.
STARTUP_FILE_END is the first address of the next file.
This file is assumed to be a startup file
and frames with pc's inside it
are treated as nonexistent.
Setting these variables is necessary so that backtraces do not fly off
the bottom of the stack. */
CORE_ADDR startup_file_start;
CORE_ADDR startup_file_end;
/* Is ADDR outside the startup file? */
int
outside_startup_file (addr)
CORE_ADDR addr;
{
return !(addr >= startup_file_start && addr < startup_file_end);
}
/* Address of innermost stack frame (contents of FP register) */
static FRAME current_frame;
struct block *block_for_pc ();
CORE_ADDR get_pc_function_start ();
/*
* Cache for frame addresses already read by gdb. Valid only while
* inferior is stopped. Control variables for the frame cache should
* be local to this module.
*/
struct obstack frame_cache_obstack;
/* Return the innermost (currently executing) stack frame. */
FRAME
get_current_frame ()
{
/* We assume its address is kept in a general register;
param.h says which register. */
return current_frame;
}
void
set_current_frame (frame)
FRAME frame;
{
current_frame = frame;
}
FRAME
create_new_frame (addr, pc)
FRAME_ADDR addr;
CORE_ADDR pc;
{
struct frame_info *fci; /* Same type as FRAME */
fci = (struct frame_info *)
obstack_alloc (&frame_cache_obstack,
sizeof (struct frame_info));
/* Arbitrary frame */
fci->next = (struct frame_info *) 0;
fci->prev = (struct frame_info *) 0;
fci->frame = addr;
fci->next_frame = 0; /* Since arbitrary */
fci->pc = pc;
#ifdef INIT_EXTRA_FRAME_INFO
INIT_EXTRA_FRAME_INFO (fci);
#endif
return fci;
}
/* Return the frame that called FRAME.
If FRAME is the original frame (it has no caller), return 0. */
FRAME
get_prev_frame (frame)
FRAME frame;
{
/* We're allowed to know that FRAME and "struct frame_info *" are
the same */
return get_prev_frame_info (frame);
}
/* Return the frame that FRAME calls (0 if FRAME is the innermost
frame). */
FRAME
get_next_frame (frame)
FRAME frame;
{
/* We're allowed to know that FRAME and "struct frame_info *" are
the same */
return frame->next;
}
/*
* Flush the entire frame cache.
*/
void
flush_cached_frames ()
{
/* Since we can't really be sure what the first object allocated was */
obstack_free (&frame_cache_obstack, 0);
obstack_init (&frame_cache_obstack);
current_frame = (struct frame_info *) 0; /* Invalidate cache */
}
/* Return a structure containing various interesting information
about a specified stack frame. */
/* How do I justify including this function? Well, the FRAME
identifier format has gone through several changes recently, and
it's not completely inconceivable that it could happen again. If
it does, have this routine around will help */
struct frame_info *
get_frame_info (frame)
FRAME frame;
{
return frame;
}
/* If a machine allows frameless functions, it should define a macro
FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) in param.h. FI is the struct
frame_info for the frame, and FRAMELESS should be set to nonzero
if it represents a frameless function invocation. */
/* Many machines which allow frameless functions can detect them using
this macro. Such machines should define FRAMELESS_FUNCTION_INVOCATION
to just call this macro. */
#define FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS) \
{ \
CORE_ADDR func_start, after_prologue; \
func_start = (get_pc_function_start ((FI)->pc) + \
FUNCTION_START_OFFSET); \
if (func_start) \
{ \
after_prologue = func_start; \
SKIP_PROLOGUE (after_prologue); \
(FRAMELESS) = (after_prologue == func_start); \
} \
else \
/* If we can't find the start of the function, we don't really */ \
/* know whether the function is frameless, but we should be */ \
/* able to get a reasonable (i.e. best we can do under the */ \
/* circumstances) backtrace by saying that it isn't. */ \
(FRAMELESS) = 0; \
}
/* Return a structure containing various interesting information
about the frame that called NEXT_FRAME. Returns NULL
if there is no such frame. */
struct frame_info *
get_prev_frame_info (next_frame)
FRAME next_frame;
{
FRAME_ADDR address;
struct frame_info *prev;
int fromleaf = 0;
/* If the requested entry is in the cache, return it.
Otherwise, figure out what the address should be for the entry
we're about to add to the cache. */
if (!next_frame)
{
if (!current_frame)
{
if (!have_inferior_p () && !have_core_file_p ())
fatal ("get_prev_frame_info: Called before cache primed. \"Shouldn't happen.\"");
else
error ("No inferior or core file.");
}
return current_frame;
}
/* If we have the prev one, return it */
if (next_frame->prev)
return next_frame->prev;
/* On some machines it is possible to call a function without
setting up a stack frame for it. On these machines, we
define this macro to take two args; a frameinfo pointer
identifying a frame and a variable to set or clear if it is
or isn't leafless. */
#ifdef FRAMELESS_FUNCTION_INVOCATION
/* Still don't want to worry about this except on the innermost
frame. This macro will set FROMLEAF if NEXT_FRAME is a
frameless function invocation. */
if (!(next_frame->next))
{
FRAMELESS_FUNCTION_INVOCATION (next_frame, fromleaf);
if (fromleaf)
address = next_frame->frame;
}
#endif
if (!fromleaf)
{
/* Two macros defined in param.h specify the machine-dependent
actions to be performed here.
First, get the frame's chain-pointer.
If that is zero, the frame is the outermost frame or a leaf
called by the outermost frame. This means that if start
calls main without a frame, we'll return 0 (which is fine
anyway).
Nope; there's a problem. This also returns when the current
routine is a leaf of main. This is unacceptable. We move
this to after the ffi test; I'd rather have backtraces from
start go curfluy than have an abort called from main not show
main. */
address = FRAME_CHAIN (next_frame);
if (!FRAME_CHAIN_VALID (address, next_frame))
return 0;
/* If this frame is a leaf, this will be superceeded by the
code below. */
address = FRAME_CHAIN_COMBINE (address, next_frame);
}
if (address == 0)
return 0;
prev = (struct frame_info *)
obstack_alloc (&frame_cache_obstack,
sizeof (struct frame_info));
if (next_frame)
next_frame->prev = prev;
prev->next = next_frame;
prev->prev = (struct frame_info *) 0;
prev->frame = address;
prev->next_frame = prev->next ? prev->next->frame : 0;
#ifdef INIT_EXTRA_FRAME_INFO
INIT_EXTRA_FRAME_INFO(prev);
#endif
/* This entry is in the frame queue now, which is good since
FRAME_SAVED_PC may use that queue to figure out it's value
(see m-sparc.h). We want the pc saved in the inferior frame. */
prev->pc = (fromleaf ? SAVED_PC_AFTER_CALL (next_frame) :
next_frame ? FRAME_SAVED_PC (next_frame) : read_pc ());
return prev;
}
CORE_ADDR
get_frame_pc (frame)
FRAME frame;
{
struct frame_info *fi;
fi = get_frame_info (frame);
return fi->pc;
}
/* Find the addresses in which registers are saved in FRAME. */
void
get_frame_saved_regs (frame_info_addr, saved_regs_addr)
struct frame_info *frame_info_addr;
struct frame_saved_regs *saved_regs_addr;
{
FRAME_FIND_SAVED_REGS (frame_info_addr, *saved_regs_addr);
}
/* Return the innermost lexical block in execution
in a specified stack frame. The frame address is assumed valid. */
struct block *
get_frame_block (frame)
FRAME frame;
{
struct frame_info *fi;
CORE_ADDR pc;
fi = get_frame_info (frame);
pc = fi->pc;
if (fi->next_frame != 0)
/* We are not in the innermost frame. We need to subtract one to
get the correct block, in case the call instruction was the
last instruction of the block. If there are any machines on
which the saved pc does not point to after the call insn, we
probably want to make fi->pc point after the call insn anyway. */
--pc;
return block_for_pc (pc);
}
struct block *
get_current_block ()
{
return block_for_pc (read_pc ());
}
CORE_ADDR
get_pc_function_start (pc)
CORE_ADDR pc;
{
register struct block *bl = block_for_pc (pc);
register struct symbol *symbol;
if (bl == 0 || (symbol = block_function (bl)) == 0)
{
register int misc_index = find_pc_misc_function (pc);
if (misc_index >= 0)
return misc_function_vector[misc_index].address;
return 0;
}
bl = SYMBOL_BLOCK_VALUE (symbol);
return BLOCK_START (bl);
}
/* Return the symbol for the function executing in frame FRAME. */
struct symbol *
get_frame_function (frame)
FRAME frame;
{
register struct block *bl = get_frame_block (frame);
if (bl == 0)
return 0;
return block_function (bl);
}
/* Return the innermost lexical block containing the specified pc value,
or 0 if there is none. */
extern struct symtab *psymtab_to_symtab ();
struct block *
block_for_pc (pc)
register CORE_ADDR pc;
{
register struct block *b;
register int bot, top, half;
register struct symtab *s;
register struct partial_symtab *ps;
struct blockvector *bl;
/* First search all symtabs for one whose file contains our pc */
for (s = symtab_list; s; s = s->next)
{
bl = BLOCKVECTOR (s);
b = BLOCKVECTOR_BLOCK (bl, 0);
if (BLOCK_START (b) <= pc
&& BLOCK_END (b) > pc)
break;
}
if (s == 0)
for (ps = partial_symtab_list; ps; ps = ps->next)
{
if (ps->textlow <= pc
&& ps->texthigh > pc)
{
if (ps->readin)
fatal ("Internal error: pc found in readin psymtab and not in any symtab.");
s = psymtab_to_symtab (ps);
bl = BLOCKVECTOR (s);
b = BLOCKVECTOR_BLOCK (bl, 0);
break;
}
}
if (s == 0)
return 0;
/* Then search that symtab for the smallest block that wins. */
/* Use binary search to find the last block that starts before PC. */
bot = 0;
top = BLOCKVECTOR_NBLOCKS (bl);
while (top - bot > 1)
{
half = (top - bot + 1) >> 1;
b = BLOCKVECTOR_BLOCK (bl, bot + half);
if (BLOCK_START (b) <= pc)
bot += half;
else
top = bot + half;
}
/* Now search backward for a block that ends after PC. */
while (bot >= 0)
{
b = BLOCKVECTOR_BLOCK (bl, bot);
if (BLOCK_END (b) > pc)
return b;
bot--;
}
return 0;
}
/* Return the function containing pc value PC.
Returns 0 if function is not known. */
struct symbol *
find_pc_function (pc)
CORE_ADDR pc;
{
register struct block *b = block_for_pc (pc);
if (b == 0)
return 0;
return block_function (b);
}
/* Finds the "function" (text symbol) that is smaller than PC
but greatest of all of the potential text symbols. Sets
*NAME and/or *ADDRESS conditionally if that pointer is non-zero.
Returns 0 if it couldn't find anything, 1 if it did. On a zero
return, *NAME and *ADDRESS are always set to zero. On a 1 return,
*NAME and *ADDRESS contain real information. */
int
find_pc_partial_function (pc, name, address)
CORE_ADDR pc;
char **name;
CORE_ADDR *address;
{
struct partial_symtab *pst = find_pc_psymtab (pc);
struct symbol *f;
int miscfunc;
struct partial_symbol *psb;
if (pst)
{
if (pst->readin)
{
/* The information we want has already been read in.
We can go to the already readin symbols and we'll get
the best possible answer. */
f = find_pc_function (pc);
if (!f)
{
return_error:
/* No availible symbol. */
if (name != 0)
*name = 0;
if (address != 0)
*address = 0;
return 0;
}
if (name)
*name = SYMBOL_NAME (f);
if (address)
*address = BLOCK_START (SYMBOL_BLOCK_VALUE (f));
return 1;
}
/* Get the information from a combination of the pst
(static symbols), and the misc function vector (extern
symbols). */
miscfunc = find_pc_misc_function (pc);
psb = find_pc_psymbol (pst, pc);
if (!psb && miscfunc == -1)
{
goto return_error;
}
if (!psb
|| (miscfunc != -1
&& (SYMBOL_VALUE(psb)
< misc_function_vector[miscfunc].address)))
{
if (address)
*address = misc_function_vector[miscfunc].address;
if (name)
*name = misc_function_vector[miscfunc].name;
return 1;
}
else
{
if (address)
*address = SYMBOL_VALUE (psb);
if (name)
*name = SYMBOL_NAME (psb);
return 1;
}
}
else
/* Must be in the misc function stuff. */
{
miscfunc = find_pc_misc_function (pc);
if (miscfunc == -1)
goto return_error;
if (address)
*address = misc_function_vector[miscfunc].address;
if (name)
*name = misc_function_vector[miscfunc].name;
return 1;
}
}
/* Find the misc function whose address is the largest
while being less than PC. Return its index in misc_function_vector.
Returns -1 if PC is not in suitable range. */
int
find_pc_misc_function (pc)
register CORE_ADDR pc;
{
register int lo = 0;
register int hi = misc_function_count-1;
register int new;
register int distance;
/* Note that the last thing in the vector is always _etext. */
/* Actually, "end", now that non-functions
go on the misc_function_vector. */
/* Above statement is not *always* true - fix for case where there are */
/* no misc functions at all (ie no symbol table has been read). */
if (hi < 0) return -1; /* no misc functions recorded */
/* trivial reject range test */
if (pc < misc_function_vector[0].address ||
pc > misc_function_vector[hi].address)
return -1;
/* Note that the following search will not return hi if
pc == misc_function_vector[hi].address. If "end" points to the
first unused location, this is correct and the above test
simply needs to be changed to
"pc >= misc_function_vector[hi].address". */
do {
new = (lo + hi) >> 1;
distance = misc_function_vector[new].address - pc;
if (distance == 0)
return new; /* an exact match */
else if (distance > 0)
hi = new;
else
lo = new;
} while (hi-lo != 1);
/* if here, we had no exact match, so return the lower choice */
return lo;
}
/* Return the innermost stack frame executing inside of the specified block,
or zero if there is no such frame. */
FRAME
block_innermost_frame (block)
struct block *block;
{
struct frame_info *fi;
register FRAME frame;
register CORE_ADDR start = BLOCK_START (block);
register CORE_ADDR end = BLOCK_END (block);
frame = 0;
while (1)
{
frame = get_prev_frame (frame);
if (frame == 0)
return 0;
fi = get_frame_info (frame);
if (fi->pc >= start && fi->pc < end)
return frame;
}
}
void
_initialize_blockframe ()
{
obstack_init (&frame_cache_obstack);
}

1383
gnu/usr.bin/gdb/breakpoint.c Normal file

File diff suppressed because it is too large Load diff

856
gnu/usr.bin/gdb/command.c Normal file
View file

@ -0,0 +1,856 @@
/* Library for reading command lines and decoding commands.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "command.h"
#include "defs.h"
#include <stdio.h>
#include <ctype.h>
extern char *xmalloc ();
/* Add element named NAME to command list *LIST.
FUN should be the function to execute the command;
it will get a character string as argument, with leading
and trailing blanks already eliminated.
DOC is a documentation string for the command.
Its first line should be a complete sentence.
It should start with ? for a command that is an abbreviation
or with * for a command that most users don't need to know about. */
struct cmd_list_element *
add_cmd (name, class, fun, doc, list)
char *name;
int class;
void (*fun) ();
char *doc;
struct cmd_list_element **list;
{
register struct cmd_list_element *c
= (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
delete_cmd (name, list);
c->next = *list;
c->name = savestring (name, strlen (name));
c->class = class;
c->function = fun;
c->doc = doc;
c->prefixlist = 0;
c->allow_unknown = 0;
c->abbrev_flag = 0;
c->aux = 0;
*list = c;
return c;
}
/* Same as above, except that the abbrev_flag is set. */
struct cmd_list_element *
add_abbrev_cmd (name, class, fun, doc, list)
char *name;
int class;
void (*fun) ();
char *doc;
struct cmd_list_element **list;
{
register struct cmd_list_element *c
= (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
delete_cmd (name, list);
c->next = *list;
c->name = savestring (name, strlen (name));
c->class = class;
c->function = fun;
c->doc = doc;
c->prefixlist = 0;
c->allow_unknown = 0;
c->abbrev_flag = 1;
c->aux = 0;
*list = c;
return c;
}
struct cmd_list_element *
add_alias_cmd (name, oldname, class, abbrev_flag, list)
char *name;
char *oldname;
int class;
int abbrev_flag;
struct cmd_list_element **list;
{
/* Must do this since lookup_cmd tries to side-effect its first arg */
char *copied_name;
register struct cmd_list_element *old;
register struct cmd_list_element *c;
copied_name = (char *) alloca (strlen (oldname) + 1);
strcpy (copied_name, oldname);
old = lookup_cmd (&copied_name, *list, 0, 1, 1);
if (old == 0)
{
delete_cmd (name, list);
return 0;
}
c = add_cmd (name, class, old->function, old->doc, list);
c->prefixlist = old->prefixlist;
c->prefixname = old->prefixname;
c->allow_unknown = old->allow_unknown;
c->abbrev_flag = abbrev_flag;
c->aux = old->aux;
return c;
}
/* Like add_cmd but adds an element for a command prefix:
a name that should be followed by a subcommand to be looked up
in another command list. PREFIXLIST should be the address
of the variable containing that list. */
struct cmd_list_element *
add_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
allow_unknown, list)
char *name;
int class;
void (*fun) ();
char *doc;
struct cmd_list_element **prefixlist;
char *prefixname;
int allow_unknown;
struct cmd_list_element **list;
{
register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
c->prefixlist = prefixlist;
c->prefixname = prefixname;
c->allow_unknown = allow_unknown;
return c;
}
/* Like add_prefix_cmd butsets the abbrev_flag on the new command. */
struct cmd_list_element *
add_abbrev_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
allow_unknown, list)
char *name;
int class;
void (*fun) ();
char *doc;
struct cmd_list_element **prefixlist;
char *prefixname;
int allow_unknown;
struct cmd_list_element **list;
{
register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
c->prefixlist = prefixlist;
c->prefixname = prefixname;
c->allow_unknown = allow_unknown;
c->abbrev_flag = 1;
return c;
}
/* Remove the command named NAME from the command list. */
void
delete_cmd (name, list)
char *name;
struct cmd_list_element **list;
{
register struct cmd_list_element *c;
while (*list && !strcmp ((*list)->name, name))
{
*list = (*list)->next;
}
if (*list)
for (c = *list; c->next;)
{
if (!strcmp (c->next->name, name))
c->next = c->next->next;
else
c = c->next;
}
}
void help_cmd (), help_list (), help_cmd_list ();
/* This command really has to deal with two things:
* 1) I want documentation on *this string* (usually called by
* "help commandname").
* 2) I want documentation on *this list* (usually called by
* giving a command that requires subcommands. Also called by saying
* just "help".)
*
* I am going to split this into two seperate comamnds, help_cmd and
* help_list.
*/
void
help_cmd (command, stream)
char *command;
FILE *stream;
{
struct cmd_list_element *c;
extern struct cmd_list_element *cmdlist;
if (!command)
{
help_list (cmdlist, "", -2, stream);
return;
}
c = lookup_cmd (&command, cmdlist, "", 0, 0);
if (c == 0)
return;
/* There are three cases here.
If c->prefixlist is nonzer, we have a prefix command.
Print its documentation, then list its subcommands.
If c->function is nonzero, we really have a command.
Print its documentation and return.
If c->function is zero, we have a class name.
Print its documentation (as if it were a command)
and then set class to he number of this class
so that the commands in the class will be listed. */
fputs_filtered (c->doc, stream);
fputs_filtered ("\n", stream);
if (c->prefixlist == 0 && c->function != 0)
return;
fprintf_filtered (stream, "\n");
/* If this is a prefix command, print it's subcommands */
if (c->prefixlist)
help_list (*c->prefixlist, c->prefixname, -1, stream);
/* If this is a class name, print all of the commands in the class */
if (c->function == 0)
help_list (cmdlist, "", c->class, stream);
}
/*
* Get a specific kind of help on a command list.
*
* LIST is the list.
* CMDTYPE is the prefix to use in the title string.
* CLASS is the class with which to list the nodes of this list (see
* documentation for help_cmd_list below), As usual, -1 for
* everything, -2 for just classes, and non-negative for only things
* in a specific class.
* and STREAM is the output stream on which to print things.
* If you call this routine with a class >= 0, it recurses.
*/
void
help_list (list, cmdtype, class, stream)
struct cmd_list_element *list;
char *cmdtype;
int class;
FILE *stream;
{
int len;
char *cmdtype1, *cmdtype2;
/* If CMDTYPE is "foo ", CMDTYPE1 gets " foo" and CMDTYPE2 gets "foo sub" */
len = strlen (cmdtype);
cmdtype1 = (char *) alloca (len + 1);
cmdtype1[0] = 0;
cmdtype2 = (char *) alloca (len + 4);
cmdtype2[0] = 0;
if (len)
{
cmdtype1[0] = ' ';
strncpy (cmdtype1 + 1, cmdtype, len - 1);
cmdtype1[len] = 0;
strncpy (cmdtype2, cmdtype, len - 1);
strcpy (cmdtype2 + len - 1, " sub");
}
if (class == -2)
fprintf_filtered (stream, "List of classes of %scommands:\n\n", cmdtype2);
else
fprintf_filtered (stream, "List of %scommands:\n\n", cmdtype2);
help_cmd_list (list, class, cmdtype, (class >= 0), stream);
if (class == -2)
fprintf_filtered (stream, "\n\
Type \"help%s\" followed by a class name for a list of commands in that class.",
cmdtype1);
fprintf_filtered (stream, "\n\
Type \"help%s\" followed by %scommand name for full documentation.\n\
Command name abbreviations are allowed if unambiguous.\n",
cmdtype1, cmdtype2);
}
/*
* Implement a help command on command list LIST.
* RECURSE should be non-zero if this should be done recursively on
* all sublists of LIST.
* PREFIX is the prefix to print before each command name.
* STREAM is the stream upon which the output should be written.
* CLASS should be:
* A non-negative class number to list only commands in that
* class.
* -1 to list all commands in list.
* -2 to list all classes in list.
*
* Note that RECURSE will be active on *all* sublists, not just the
* ones seclected by the criteria above (ie. the selection mechanism
* is at the low level, not the high-level).
*/
void
help_cmd_list (list, class, prefix, recurse, stream)
struct cmd_list_element *list;
int class;
char *prefix;
int recurse;
FILE *stream;
{
register struct cmd_list_element *c;
register char *p;
static char *line_buffer = 0;
static int line_size;
if (!line_buffer)
{
line_size = 80;
line_buffer = (char *) xmalloc (line_size);
}
for (c = list; c; c = c->next)
{
if (c->abbrev_flag == 0 &&
(class == -1
|| (class == -2 && c->function == 0)
|| (class == c->class && c->function != 0)))
{
fprintf_filtered (stream, "%s%s -- ", prefix, c->name);
/* Print just the first line */
p = c->doc;
while (*p && *p != '\n') p++;
if (p - c->doc > line_size - 1)
{
line_size = p - c->doc + 1;
free (line_buffer);
line_buffer = (char *) xmalloc (line_size);
}
strncpy (line_buffer, c->doc, p - c->doc);
line_buffer[p - c->doc] = '\0';
fputs_filtered (line_buffer, stream);
fputs_filtered ("\n", stream);
}
if (recurse
&& c->prefixlist != 0
&& c->abbrev_flag == 0)
help_cmd_list (*c->prefixlist, class, c->prefixname, 1, stream);
}
}
/* This routine takes a line of TEXT and a CLIST in which to
start the lookup. When it returns it will have incremented the text
pointer past the section of text it matched, set *RESULT_LIST to
the list in which the last word was matched, and will return the
cmd list element which the text matches. It will return 0 if no
match at all was possible. It will return -1 if ambigous matches are
possible; in this case *RESULT_LIST will be set to the list in which
there are ambiguous choices (and text will be set to the ambiguous
text string).
It does no error reporting whatsoever; control will always return
to the superior routine.
In the case of an ambiguous return (-1), *RESULT_LIST will be set to
point at the prefix_command (ie. the best match) *or* (special
case) will be 0 if no prefix command was ever found. For example,
in the case of "info a", "info" matches without ambiguity, but "a"
could be "args" or "address", so *RESULT_LIST is set to
the cmd_list_element for "info". So in this case
result list should not be interpeted as a pointer to the beginning
of a list; it simply points to a specific command.
This routine does *not* modify the text pointed to by TEXT.
If INGNORE_HELP_CLASSES is nonzero, ignore any command list
elements which are actually help classes rather than commands (i.e.
the function field of the struct cmd_list_element is 0). */
struct cmd_list_element *
lookup_cmd_1 (text, clist, result_list, ignore_help_classes)
char **text;
struct cmd_list_element *clist, **result_list;
int ignore_help_classes;
{
char *p, *command;
int len, tmp, nfound;
struct cmd_list_element *found, *c;
while (**text == ' ' || **text == '\t')
(*text)++;
/* Treating underscores as part of command words is important
so that "set args_foo()" doesn't get interpreted as
"set args _foo()". */
for (p = *text;
*p && (isalnum(*p) || *p == '-' || *p == '_');
p++)
;
/* If nothing but whitespace, return 0. */
if (p == *text)
return 0;
len = p - *text;
/* *text and p now bracket the first command word to lookup (and
it's length is len). We copy this into a local temporary,
converting to lower case as we go. */
command = (char *) alloca (len + 1);
for (tmp = 0; tmp < len; tmp++)
{
char x = (*text)[tmp];
command[tmp] = (x >= 'A' && x <= 'Z') ? x - 'A' + 'a' : x;
}
command[len] = '\0';
/* Look it up. */
found = 0;
nfound = 0;
for (c = clist; c; c = c->next)
if (!strncmp (command, c->name, len)
&& (!ignore_help_classes || c->function))
{
found = c;
nfound++;
if (c->name[len] == '\0')
{
nfound = 1;
break;
}
}
/* If nothing matches, we have a simple failure. */
if (nfound == 0)
return 0;
if (nfound > 1)
{
*result_list = 0; /* Will be modified in calling routine
if we know what the prefix command is.
*/
return (struct cmd_list_element *) -1; /* Ambiguous. */
}
/* We've matched something on this list. Move text pointer forward. */
*text = p;
if (found->prefixlist)
{
c = lookup_cmd_1 (text, *found->prefixlist, result_list,
ignore_help_classes);
if (!c)
{
/* Didn't find anything; this is as far as we got. */
*result_list = clist;
return found;
}
else if (c == (struct cmd_list_element *) -1)
{
/* We've gotten this far properley, but the next step
is ambiguous. We need to set the result list to the best
we've found (if an inferior hasn't already set it). */
if (!*result_list)
/* This used to say *result_list = *found->prefixlist
If that was correct, need to modify the documentation
at the top of this function to clarify what is supposed
to be going on. */
*result_list = found;
return c;
}
else
{
/* We matched! */
return c;
}
}
else
{
*result_list = clist;
return found;
}
}
/* Look up the contents of *LINE as a command in the command list LIST.
LIST is a chain of struct cmd_list_element's.
If it is found, return the struct cmd_list_element for that command
and update *LINE to point after the command name, at the first argument.
If not found, call error if ALLOW_UNKNOWN is zero
otherwise (or if error returns) return zero.
Call error if specified command is ambiguous,
unless ALLOW_UNKNOWN is negative.
CMDTYPE precedes the word "command" in the error message.
If INGNORE_HELP_CLASSES is nonzero, ignore any command list
elements which are actually help classes rather than commands (i.e.
the function field of the struct cmd_list_element is 0). */
struct cmd_list_element *
lookup_cmd (line, list, cmdtype, allow_unknown, ignore_help_classes)
char **line;
struct cmd_list_element *list;
char *cmdtype;
int allow_unknown;
int ignore_help_classes;
{
struct cmd_list_element *last_list = 0;
struct cmd_list_element *c =
lookup_cmd_1 (line, list, &last_list, ignore_help_classes);
char *ptr = (*line) + strlen (*line) - 1;
/* Clear off trailing whitespace. */
while (ptr >= *line && (*ptr == ' ' || *ptr == '\t'))
ptr--;
*(ptr + 1) = '\0';
if (!c)
{
if (!allow_unknown)
{
if (!*line)
error ("Lack of needed %scommand", cmdtype);
else
{
char *p = *line, *q;
while (isalnum(*p) || *p == '-')
p++;
q = (char *) alloca (p - *line + 1);
strncpy (q, *line, p - *line);
q[p-*line] = '\0';
error ("Undefined %scommand: \"%s\".", cmdtype, q);
}
}
else
return 0;
}
else if (c == (struct cmd_list_element *) -1)
{
/* Ambigous. Local values should be off prefixlist or called
values. */
int local_allow_unknown = (last_list ? last_list->allow_unknown :
allow_unknown);
char *local_cmdtype = last_list ? last_list->prefixname : cmdtype;
struct cmd_list_element *local_list =
(last_list ? *(last_list->prefixlist) : list);
if (local_allow_unknown < 0)
{
if (last_list)
return last_list; /* Found something. */
else
return 0; /* Found nothing. */
}
else
{
/* Report as error. */
int amb_len;
char ambbuf[100];
for (amb_len = 0;
((*line)[amb_len] && (*line)[amb_len] != ' '
&& (*line)[amb_len] != '\t');
amb_len++)
;
ambbuf[0] = 0;
for (c = local_list; c; c = c->next)
if (!strncmp (*line, c->name, amb_len))
{
if (strlen (ambbuf) + strlen (c->name) + 6 < sizeof ambbuf)
{
if (strlen (ambbuf))
strcat (ambbuf, ", ");
strcat (ambbuf, c->name);
}
else
{
strcat (ambbuf, "..");
break;
}
}
error ("Ambiguous %scommand \"%s\": %s.", local_cmdtype,
*line, ambbuf);
}
}
else
{
/* We've got something. It may still not be what the caller
wants (if this command *needs* a subcommand). */
while (**line == ' ' || **line == '\t')
(*line)++;
if (c->prefixlist && **line && !c->allow_unknown)
error ("Undefined %scommand: \"%s\".", c->prefixname, *line);
/* Seems to be what he wants. Return it. */
return c;
}
}
#if 0
/* Look up the contents of *LINE as a command in the command list LIST.
LIST is a chain of struct cmd_list_element's.
If it is found, return the struct cmd_list_element for that command
and update *LINE to point after the command name, at the first argument.
If not found, call error if ALLOW_UNKNOWN is zero
otherwise (or if error returns) return zero.
Call error if specified command is ambiguous,
unless ALLOW_UNKNOWN is negative.
CMDTYPE precedes the word "command" in the error message. */
struct cmd_list_element *
lookup_cmd (line, list, cmdtype, allow_unknown)
char **line;
struct cmd_list_element *list;
char *cmdtype;
int allow_unknown;
{
register char *p;
register struct cmd_list_element *c, *found;
int nfound;
char ambbuf[100];
char *processed_cmd;
int i, cmd_len;
/* Skip leading whitespace. */
while (**line == ' ' || **line == '\t')
(*line)++;
/* Clear out trailing whitespace. */
p = *line + strlen (*line);
while (p != *line && (p[-1] == ' ' || p[-1] == '\t'))
p--;
*p = 0;
/* Find end of command name. */
p = *line;
while (*p == '-'
|| (*p >= 'a' && *p <= 'z')
|| (*p >= 'A' && *p <= 'Z')
|| (*p >= '0' && *p <= '9'))
p++;
/* Look up the command name.
If exact match, keep that.
Otherwise, take command abbreviated, if unique. Note that (in my
opinion) a null string does *not* indicate ambiguity; simply the
end of the argument. */
if (p == *line)
{
if (!allow_unknown)
error ("Lack of needed %scommand", cmdtype);
return 0;
}
/* Copy over to a local buffer, converting to lowercase on the way.
This is in case the command being parsed is a subcommand which
doesn't match anything, and that's ok. We want the original
untouched for the routine of the original command. */
processed_cmd = (char *) alloca (p - *line + 1);
for (cmd_len = 0; cmd_len < p - *line; cmd_len++)
{
char x = (*line)[cmd_len];
if (x >= 'A' && x <= 'Z')
processed_cmd[cmd_len] = x - 'A' + 'a';
else
processed_cmd[cmd_len] = x;
}
processed_cmd[cmd_len] = '\0';
/* Check all possibilities in the current command list. */
found = 0;
nfound = 0;
for (c = list; c; c = c->next)
{
if (!strncmp (processed_cmd, c->name, cmd_len))
{
found = c;
nfound++;
if (c->name[cmd_len] == 0)
{
nfound = 1;
break;
}
}
}
/* Report error for undefined command name. */
if (nfound != 1)
{
if (nfound > 1 && allow_unknown >= 0)
{
ambbuf[0] = 0;
for (c = list; c; c = c->next)
if (!strncmp (processed_cmd, c->name, cmd_len))
{
if (strlen (ambbuf) + strlen (c->name) + 6 < sizeof ambbuf)
{
if (strlen (ambbuf))
strcat (ambbuf, ", ");
strcat (ambbuf, c->name);
}
else
{
strcat (ambbuf, "..");
break;
}
}
error ("Ambiguous %scommand \"%s\": %s.", cmdtype,
processed_cmd, ambbuf);
}
else if (!allow_unknown)
error ("Undefined %scommand: \"%s\".", cmdtype, processed_cmd);
return 0;
}
/* Skip whitespace before the argument. */
while (*p == ' ' || *p == '\t') p++;
*line = p;
if (found->prefixlist && *p)
{
c = lookup_cmd (line, *found->prefixlist, found->prefixname,
found->allow_unknown);
if (c)
return c;
}
return found;
}
#endif
/* Helper function for SYMBOL_COMPLETION_FUNCTION. */
/* Return a vector of char pointers which point to the different
possible completions in LIST of TEXT. */
char **
complete_on_cmdlist (list, text)
struct cmd_list_element *list;
char *text;
{
struct cmd_list_element *ptr;
char **matchlist;
int sizeof_matchlist;
int matches;
int textlen = strlen (text);
sizeof_matchlist = 10;
matchlist = (char **) xmalloc (sizeof_matchlist * sizeof (char *));
matches = 0;
for (ptr = list; ptr; ptr = ptr->next)
if (!strncmp (ptr->name, text, textlen)
&& !ptr->abbrev_flag
&& (ptr->function
|| ptr->prefixlist))
{
if (matches == sizeof_matchlist)
{
sizeof_matchlist *= 2;
matchlist = (char **) xrealloc (matchlist,
(sizeof_matchlist
* sizeof (char *)));
}
matchlist[matches] = (char *)
xmalloc (strlen (ptr->name) + 1);
strcpy (matchlist[matches++], ptr->name);
}
if (matches == 0)
{
free (matchlist);
matchlist = 0;
}
else
{
matchlist = (char **) xrealloc (matchlist, ((matches + 1)
* sizeof (char *)));
matchlist[matches] = (char *) 0;
}
return matchlist;
}
static void
shell_escape (arg, from_tty)
char *arg;
int from_tty;
{
int rc, status, pid;
char *p, *user_shell;
extern char *rindex ();
if ((user_shell = (char *) getenv ("SHELL")) == NULL)
user_shell = "/bin/sh";
/* Get the name of the shell for arg0 */
if ((p = rindex (user_shell, '/')) == NULL)
p = user_shell;
else
p++; /* Get past '/' */
if ((pid = fork()) == 0)
{
if (!arg)
execl (user_shell, p, 0);
else
execl (user_shell, p, "-c", arg, 0);
fprintf (stderr, "Exec of shell failed\n");
exit (0);
}
if (pid != -1)
while ((rc = wait (&status)) != pid && rc != -1)
;
else
error ("Fork failed");
}
void
_initialize_command ()
{
add_com ("shell", class_support, shell_escape,
"Execute the rest of the line as a shell command. \n\
With no arguments, run an inferior shell.");
}

77
gnu/usr.bin/gdb/command.h Normal file
View file

@ -0,0 +1,77 @@
/* Header file for command-reading library command.c.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This structure records one command'd definition. */
struct cmd_list_element
{
/* Points to next command in this list. */
struct cmd_list_element *next;
/* Name of this command. */
char *name;
/* Command class; class values are chosen by application program. */
int class;
/* Function definition of this command.
Zero for command class names and for help topics that
are not really commands. */
void (*function) ();
/* Documentation of this command (or help topic).
First line is brief documentation; remaining lines form, with it,
the full documentation. First line should end with a period.
Entire string should also end with a period, not a newline. */
char *doc;
/* Auxiliary information.
It is up to the calling program to decide what this means. */
char *aux;
/* Nonzero identifies a prefix command. For them, the address
of the variable containing the list of subcommands. */
struct cmd_list_element **prefixlist;
/* For prefix commands only:
String containing prefix commands to get here: this one
plus any others needed to get to it. Should end in a space.
It is used before the word "command" in describing the
commands reached through this prefix. */
char *prefixname;
/* For prefix commands only:
nonzero means do not get an error if subcommand is not
recognized; call the prefix's own function in that case. */
char allow_unknown;
/* Nonzero says this is an abbreviation, and should not
be mentioned in lists of commands.
This allows "br<tab>" to complete to "break", which it
otherwise wouldn't. */
char abbrev_flag;
};
/* Forward-declarations of the entry-points of command.c. */
extern struct cmd_list_element *add_cmd ();
extern struct cmd_list_element *add_alias_cmd ();
extern struct cmd_list_element *add_prefix_cmd ();
extern struct cmd_list_element *lookup_cmd (), *lookup_cmd_1 ();
extern char **complete_on_cmdlist ();
extern void delete_cmd ();
extern void help_cmd ();

View file

@ -0,0 +1,6 @@
# @(#)Makefile.i386 6.2 (Berkeley) 3/21/91
CONFIGSRCS= i386bsd-dep.c i386-pinsn.c
param.h:
ln -s $(.CURDIR)/config/m-i386bsd.h param.h

View file

@ -0,0 +1,585 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
*/
#ifndef lint
static char sccsid[] = "@(#)default-dep.c 6.3 (Berkeley) 5/8/91";
#endif /* not lint */
/* Low level interface to ptrace, for GDB when running under Unix.
Copyright (C) 1988, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "defs.h"
#include "param.h"
#include "frame.h"
#include "inferior.h"
#ifdef USG
#include <sys/types.h>
#endif
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include <sys/ioctl.h>
/* #include <fcntl.h> Can we live without this? */
#ifdef COFF_ENCAPSULATE
#include "a.out.encap.h"
#else
#include <a.out.h>
#endif
#ifndef N_SET_MAGIC
#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val))
#endif
#include <sys/user.h> /* After a.out.h */
#include <sys/file.h>
#include <sys/stat.h>
extern int errno;
/* This function simply calls ptrace with the given arguments.
It exists so that all calls to ptrace are isolated in this
machine-dependent file. */
int
call_ptrace (request, pid, arg3, arg4)
int request, pid, arg3, arg4;
{
return ptrace (request, pid, arg3, arg4);
}
kill_inferior ()
{
if (remote_debugging)
return;
if (inferior_pid == 0)
return;
ptrace (8, inferior_pid, 0, 0);
wait (0);
inferior_died ();
}
/* This is used when GDB is exiting. It gives less chance of error.*/
kill_inferior_fast ()
{
if (remote_debugging)
return;
if (inferior_pid == 0)
return;
ptrace (8, inferior_pid, 0, 0);
wait (0);
}
/* Resume execution of the inferior process.
If STEP is nonzero, single-step it.
If SIGNAL is nonzero, give it that signal. */
void
resume (step, signal)
int step;
int signal;
{
errno = 0;
if (remote_debugging)
remote_resume (step, signal);
else
{
ptrace (step ? 9 : 7, inferior_pid, 1, signal);
if (errno)
perror_with_name ("ptrace");
}
}
void
fetch_inferior_registers ()
{
register int regno;
register unsigned int regaddr;
char buf[MAX_REGISTER_RAW_SIZE];
register int i;
struct user u;
unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
for (regno = 0; regno < NUM_REGS; regno++)
{
regaddr = register_addr (regno, offset);
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
{
*(int *) &buf[i] = ptrace (3, inferior_pid, regaddr, 0);
regaddr += sizeof (int);
}
supply_register (regno, buf);
}
}
/* Store our register values back into the inferior.
If REGNO is -1, do this for all registers.
Otherwise, REGNO specifies which register (so we can save time). */
store_inferior_registers (regno)
int regno;
{
register unsigned int regaddr;
char buf[80];
struct user u;
unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
if (regno >= 0)
{
regaddr = register_addr (regno, offset);
errno = 0;
ptrace (6, inferior_pid, regaddr, read_register (regno));
if (errno != 0)
{
sprintf (buf, "writing register number %d", regno);
perror_with_name (buf);
}
}
else for (regno = 0; regno < NUM_REGS; regno++)
{
regaddr = register_addr (regno, offset);
errno = 0;
ptrace (6, inferior_pid, regaddr, read_register (regno));
if (errno != 0)
{
sprintf (buf, "writing all regs, number %d", regno);
perror_with_name (buf);
}
}
}
/* Copy LEN bytes from inferior's memory starting at MEMADDR
to debugger memory starting at MYADDR.
On failure (cannot read from inferior, usually because address is out
of bounds) returns the value of errno. */
int
read_inferior_memory (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
register int i;
/* Round starting address down to longword boundary. */
register CORE_ADDR addr = memaddr & - sizeof (int);
/* Round ending address up; get number of longwords that makes. */
register int count
= (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
/* Allocate buffer of that many longwords. */
register int *buffer = (int *) alloca (count * sizeof (int));
extern int errno;
/* Read all the longwords */
for (i = 0; i < count; i++, addr += sizeof (int))
{
errno = 0;
#if 0
/* This is now done by read_memory, because when this function did it,
reading a byte or short int hardware port read whole longs, causing
serious side effects
such as bus errors and unexpected hardware operation. This would
also be a problem with ptrace if the inferior process could read
or write hardware registers, but that's not usually the case. */
if (remote_debugging)
buffer[i] = remote_fetch_word (addr);
else
#endif
buffer[i] = ptrace (1, inferior_pid, addr, 0);
if (errno)
return errno;
}
/* Copy appropriate bytes out of the buffer. */
bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
return 0;
}
/* Copy LEN bytes of data from debugger memory at MYADDR
to inferior's memory at MEMADDR.
On failure (cannot write the inferior)
returns the value of errno. */
int
write_inferior_memory (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
register int i;
/* Round starting address down to longword boundary. */
register CORE_ADDR addr = memaddr & - sizeof (int);
/* Round ending address up; get number of longwords that makes. */
register int count
= (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
/* Allocate buffer of that many longwords. */
register int *buffer = (int *) alloca (count * sizeof (int));
extern int errno;
/* Fill start and end extra bytes of buffer with existing memory data. */
if (remote_debugging)
return (remote_write_inferior_memory(memaddr, myaddr, len));
buffer[0] = ptrace (1, inferior_pid, addr, 0);
if (count > 1)
buffer[count - 1] = ptrace (1, inferior_pid,
addr + (count - 1) * sizeof (int), 0);
/* Copy data to be written over corresponding part of buffer */
bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
/* Write the entire buffer. */
for (i = 0; i < count; i++, addr += sizeof (int))
{
errno = 0;
ptrace (4, inferior_pid, addr, buffer[i]);
if (errno)
return errno;
}
return 0;
}
/* Work with core dump and executable files, for GDB.
This code would be in core.c if it weren't machine-dependent. */
#ifndef N_TXTADDR
#define N_TXTADDR(hdr) 0
#endif /* no N_TXTADDR */
#ifndef N_DATADDR
#define N_DATADDR(hdr) hdr.a_text
#endif /* no N_DATADDR */
/* Make COFF and non-COFF names for things a little more compatible
to reduce conditionals later. */
#ifdef COFF_FORMAT
#define a_magic magic
#endif
#ifndef COFF_FORMAT
#ifndef AOUTHDR
#define AOUTHDR struct exec
#endif
#endif
extern char *sys_siglist[];
/* Hook for `exec_file_command' command to call. */
extern void (*exec_file_display_hook) ();
/* File names of core file and executable file. */
extern char *corefile;
extern char *execfile;
/* Descriptors on which core file and executable file are open.
Note that the execchan is closed when an inferior is created
and reopened if the inferior dies or is killed. */
extern int corechan;
extern int execchan;
/* Last modification time of executable file.
Also used in source.c to compare against mtime of a source file. */
extern int exec_mtime;
/* Virtual addresses of bounds of the two areas of memory in the core file. */
extern CORE_ADDR data_start;
extern CORE_ADDR data_end;
extern CORE_ADDR stack_start;
extern CORE_ADDR stack_end;
/* Virtual addresses of bounds of two areas of memory in the exec file.
Note that the data area in the exec file is used only when there is no core file. */
extern CORE_ADDR text_start;
extern CORE_ADDR text_end;
extern CORE_ADDR exec_data_start;
extern CORE_ADDR exec_data_end;
/* Address in executable file of start of text area data. */
extern int text_offset;
/* Address in executable file of start of data area data. */
extern int exec_data_offset;
/* Address in core file of start of data area data. */
extern int data_offset;
/* Address in core file of start of stack area data. */
extern int stack_offset;
#ifdef COFF_FORMAT
/* various coff data structures */
extern FILHDR file_hdr;
extern SCNHDR text_hdr;
extern SCNHDR data_hdr;
#endif /* not COFF_FORMAT */
/* a.out header saved in core file. */
extern AOUTHDR core_aouthdr;
/* a.out header of exec file. */
extern AOUTHDR exec_aouthdr;
extern void validate_files ();
core_file_command (filename, from_tty)
char *filename;
int from_tty;
{
int val;
extern char registers[];
/* Discard all vestiges of any previous core file
and mark data and stack spaces as empty. */
if (corefile)
free (corefile);
corefile = 0;
if (corechan >= 0)
close (corechan);
corechan = -1;
data_start = 0;
data_end = 0;
stack_start = STACK_END_ADDR;
stack_end = STACK_END_ADDR;
/* Now, if a new core file was specified, open it and digest it. */
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
if (have_inferior_p ())
error ("To look at a core file, you must kill the inferior with \"kill\".");
corechan = open (filename, O_RDONLY, 0);
if (corechan < 0)
perror_with_name (filename);
/* 4.2-style (and perhaps also sysV-style) core dump file. */
{
struct user u;
unsigned int reg_offset;
val = myread (corechan, &u, sizeof u);
if (val < 0)
perror_with_name ("Not a core file: reading upage");
if (val != sizeof u)
error ("Not a core file: could only read %d bytes", val);
/* We are depending on exec_file_command having been called
previously to set exec_data_start. Since the executable
and the core file share the same text segment, the address
of the data segment will be the same in both. */
data_start = exec_data_start;
data_end = data_start + NBPG * u.u_dsize;
stack_start = stack_end - NBPG * u.u_ssize;
data_offset = NBPG * UPAGES;
stack_offset = NBPG * (UPAGES + u.u_dsize);
/* Some machines put an absolute address in here and some put
the offset in the upage of the regs. */
reg_offset = (int) u.u_ar0;
if (reg_offset > NBPG * UPAGES)
reg_offset -= KERNEL_U_ADDR;
/* I don't know where to find this info.
So, for now, mark it as not available. */
N_SET_MAGIC (core_aouthdr, 0);
/* Read the register values out of the core file and store
them where `read_register' will find them. */
{
register int regno;
for (regno = 0; regno < NUM_REGS; regno++)
{
char buf[MAX_REGISTER_RAW_SIZE];
val = lseek (corechan, register_addr (regno, reg_offset), 0);
if (val < 0
|| (val = myread (corechan, buf, sizeof buf)) < 0)
{
char * buffer = (char *) alloca (strlen (reg_names[regno])
+ 30);
strcpy (buffer, "Reading register ");
strcat (buffer, reg_names[regno]);
perror_with_name (buffer);
}
supply_register (regno, buf);
}
}
}
if (filename[0] == '/')
corefile = savestring (filename, strlen (filename));
else
{
corefile = concat (current_directory, "/", filename);
}
set_current_frame ( create_new_frame (read_register (FP_REGNUM),
read_pc ()));
select_frame (get_current_frame (), 0);
validate_files ();
}
else if (from_tty)
printf ("No core file now.\n");
}
exec_file_command (filename, from_tty)
char *filename;
int from_tty;
{
int val;
/* Eliminate all traces of old exec file.
Mark text segment as empty. */
if (execfile)
free (execfile);
execfile = 0;
data_start = 0;
data_end -= exec_data_start;
text_start = 0;
text_end = 0;
exec_data_start = 0;
exec_data_end = 0;
if (execchan >= 0)
close (execchan);
execchan = -1;
/* Now open and digest the file the user requested, if any. */
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
&execfile);
if (execchan < 0)
perror_with_name (filename);
#ifdef COFF_FORMAT
{
int aout_hdrsize;
int num_sections;
if (read_file_hdr (execchan, &file_hdr) < 0)
error ("\"%s\": not in executable format.", execfile);
aout_hdrsize = file_hdr.f_opthdr;
num_sections = file_hdr.f_nscns;
if (read_aout_hdr (execchan, &exec_aouthdr, aout_hdrsize) < 0)
error ("\"%s\": can't read optional aouthdr", execfile);
if (read_section_hdr (execchan, _TEXT, &text_hdr, num_sections,
aout_hdrsize) < 0)
error ("\"%s\": can't read text section header", execfile);
if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections,
aout_hdrsize) < 0)
error ("\"%s\": can't read data section header", execfile);
text_start = exec_aouthdr.text_start;
text_end = text_start + exec_aouthdr.tsize;
text_offset = text_hdr.s_scnptr;
exec_data_start = exec_aouthdr.data_start;
exec_data_end = exec_data_start + exec_aouthdr.dsize;
exec_data_offset = data_hdr.s_scnptr;
data_start = exec_data_start;
data_end += exec_data_start;
exec_mtime = file_hdr.f_timdat;
}
#else /* not COFF_FORMAT */
{
struct stat st_exec;
#ifdef HEADER_SEEK_FD
HEADER_SEEK_FD (execchan);
#endif
val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR));
if (val < 0)
perror_with_name (filename);
text_start = N_TXTADDR (exec_aouthdr);
exec_data_start = N_DATADDR (exec_aouthdr);
text_offset = N_TXTOFF (exec_aouthdr);
exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
text_end = text_start + exec_aouthdr.a_text;
exec_data_end = exec_data_start + exec_aouthdr.a_data;
data_start = exec_data_start;
data_end += exec_data_start;
if (fstat (execchan, &st_exec) < 0)
perror_with_name (filename);
exec_mtime = st_exec.st_mtime;
}
#endif /* not COFF_FORMAT */
validate_files ();
}
else if (from_tty)
printf ("No exec file now.\n");
/* Tell display code (if any) about the changed file name. */
if (exec_file_display_hook)
(*exec_file_display_hook) (filename);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,28 @@
/* Macro defintions for i386, running System V 3.2.
Copyright (C) 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "m-i386.h"
/* Apparently there is inconsistency among various System V's about what
the name of this field is. */
#define U_FPSTATE(u) u.u_fps.u_fpstate
/* TIOCGETC is defined in System V 3.2 termio.h, but struct tchars
is not. This makes problems for inflow.c. */
#define TIOCGETC_BROKEN

View file

@ -0,0 +1,394 @@
/* Macro defintions for i386.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Define the bit, byte, and word ordering of the machine. */
/* #define BITS_BIG_ENDIAN */
/* #define BYTES_BIG_ENDIAN */
/* #define WORDS_BIG_ENDIAN */
/*
* Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
* July 1988
*/
#ifndef i386
#define i386
#endif
/* I'm running gdb 3.4 under 386/ix 2.0.2, which is a derivative of AT&T's
Sys V/386 3.2.
On some machines, gdb crashes when it's starting up while calling the
vendor's termio tgetent() routine. It always works when run under
itself (actually, under 3.2, it's not an infinitely recursive bug.)
After some poking around, it appears that depending on the environment
size, or whether you're running YP, or the phase of the moon or something,
the stack is not always long-aligned when main() is called, and tgetent()
takes strong offense at that. On some machines this bug never appears, but
on those where it does, it occurs quite reliably. */
#define ALIGN_STACK_ON_STARTUP
/* define USG if you are using sys5 /usr/include's */
#define USG
/* USG systems need these */
#define vfork() fork()
#define MAXPATHLEN 500
/* define this if you don't have the extension to coff that allows
* file names to appear in the string table
* (aux.x_file.x_foff)
*/
#define COFF_NO_LONG_FILE_NAMES
/* turn this on when rest of gdb is ready */
/* #define IEEE_FLOAT */
#define NBPG NBPC
#define UPAGES USIZE
#define HAVE_TERMIO
/* Get rid of any system-imposed stack limit if possible. */
/* #define SET_STACK_LIMIT_HUGE not in sys5 */
/* Define this if the C compiler puts an underscore at the front
of external names before giving them to the linker. */
/* #define NAMES_HAVE_UNDERSCORE */
/* Specify debugger information format. */
/* #define READ_DBX_FORMAT */
#define COFF_FORMAT
/* number of traps that happen between exec'ing the shell
* to run an inferior, and when we finally get to
* the inferior code. This is 2 on most implementations.
*/
#define START_INFERIOR_TRAPS_EXPECTED 4
/* Offset from address of function to start of its code.
Zero on most machines. */
#define FUNCTION_START_OFFSET 0
/* Advance PC across any function entry prologue instructions
to reach some "real" code. */
#define SKIP_PROLOGUE(frompc) {(frompc) = i386_skip_prologue((frompc));}
/* Immediately after a function call, return the saved pc.
Can't always go through the frames for this because on some machines
the new frame is not set up until the new function executes
some instructions. */
#define SAVED_PC_AFTER_CALL(frame) \
(read_memory_integer (read_register (SP_REGNUM), 4))
/* This is the amount to subtract from u.u_ar0
to get the offset in the core file of the register values. */
#define KERNEL_U_ADDR 0xe0000000
/* Address of end of stack space. */
#define STACK_END_ADDR 0x80000000
/* Stack grows downward. */
#define INNER_THAN <
/* Sequence of bytes for breakpoint instruction. */
#define BREAKPOINT {0xcc}
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always. */
#define DECR_PC_AFTER_BREAK 1
/* Nonzero if instruction at PC is a return instruction. */
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0xc3)
/* Return 1 if P points to an invalid floating point value.
LEN is the length in bytes -- not relevant on the 386. */
#define INVALID_FLOAT(p, len) (0)
/* code to execute to print interesting information about the
* floating point processor (if any)
* No need to define if there is nothing to do.
*/
#define FLOAT_INFO { i386_float_info (); }
/* Largest integer type */
#define LONGEST long
/* Name of the builtin type for the LONGEST type above. */
#define BUILTIN_TYPE_LONGEST builtin_type_long
/* Say how long (ordinary) registers are. */
#define REGISTER_TYPE long
/* Number of machine registers */
#define NUM_REGS 16
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer. */
/* the order of the first 8 registers must match the compiler's
* numbering scheme (which is the same as the 386 scheme)
* also, this table must match regmap in i386-pinsn.c.
*/
#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
"esp", "ebp", "esi", "edi", \
"eip", "ps", "cs", "ss", \
"ds", "es", "fs", "gs", \
}
/* Register numbers of various important registers.
Note that some of these values are "real" register numbers,
and correspond to the general registers of the machine,
and some are "phony" register numbers which are too large
to be actual register numbers as far as the user is concerned
but do serve to get the desired values when passed to read_register. */
#define FP_REGNUM 5 /* Contains address of executing stack frame */
#define SP_REGNUM 4 /* Contains address of top of stack */
#define PC_REGNUM 8
#define PS_REGNUM 9
#define REGISTER_U_ADDR(addr, blockend, regno) \
(addr) = i386_register_u_addr ((blockend),(regno));
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES (NUM_REGS * 4)
/* Index within `registers' of the first byte of the space for
register N. */
#define REGISTER_BYTE(N) ((N)*4)
/* Number of bytes of storage in the actual machine representation
for register N. */
#define REGISTER_RAW_SIZE(N) (4)
/* Number of bytes of storage in the program's representation
for register N. */
#define REGISTER_VIRTUAL_SIZE(N) (4)
/* Largest value REGISTER_RAW_SIZE can have. */
#define MAX_REGISTER_RAW_SIZE 4
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
#define MAX_REGISTER_VIRTUAL_SIZE 4
/* Nonzero if register N requires conversion
from raw format to virtual format. */
#define REGISTER_CONVERTIBLE(N) (0)
/* Convert data from raw format for register REGNUM
to virtual format for register REGNUM. */
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) {bcopy ((FROM), (TO), 4);}
/* Convert data from virtual format for register REGNUM
to raw format for register REGNUM. */
#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) {bcopy ((FROM), (TO), 4);}
/* Return the GDB type object for the "standard" data type
of data in register N. */
#define REGISTER_VIRTUAL_TYPE(N) (builtin_type_int)
/* Store the address of the place in which to copy the structure the
subroutine will return. This is called from call_function. */
#define STORE_STRUCT_RETURN(ADDR, SP) \
{ (SP) -= sizeof (ADDR); \
write_memory ((SP), &(ADDR), sizeof (ADDR)); }
/* Extract from an array REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
into VALBUF. */
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format. */
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
/* Extract from an array REGBUF containing the (raw) register state
the address in which a function should return its structure value,
as a CORE_ADDR (or an expression that can be used as one). */
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
/* FRAME_CHAIN takes a frame's nominal address
and produces the frame's chain-pointer.
FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
and produces the nominal address of the caller frame.
However, if FRAME_CHAIN_VALID returns zero,
it means the given frame is the outermost one and has no caller.
In that case, FRAME_CHAIN_COMBINE is not used. */
#define FRAME_CHAIN(thisframe) \
(outside_startup_file ((thisframe)->pc) ? \
read_memory_integer ((thisframe)->frame, 4) :\
0)
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
/* A macro that tells us whether the function invocation represented
by FI does not have a frame on the stack associated with it. If it
does not, FRAMELESS is set to 1, else 0. */
#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS)
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
/* Return number of args passed to a frame.
Can return -1, meaning no way to tell. */
#define FRAME_NUM_ARGS(numargs, fi) (numargs) = i386_frame_num_args(fi)
/* Return number of bytes at start of arglist that are not really args. */
#define FRAME_ARGS_SKIP 8
/* Put here the code to store, into a struct frame_saved_regs,
the addresses of the saved registers of frame described by FRAME_INFO.
This includes special registers such as pc and fp saved in special
ways in the stack frame. sp is even more special:
the address we return for it IS the sp for the next frame. */
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
{ i386_frame_find_saved_regs ((frame_info), &(frame_saved_regs)); }
/* Things needed for making the inferior call functions. */
/* Push an empty stack frame, to record the current PC, etc. */
#define PUSH_DUMMY_FRAME { i386_push_dummy_frame (); }
/* Discard from the stack the innermost frame, restoring all registers. */
#define POP_FRAME { i386_pop_frame (); }
/* this is
* call 11223344 (32 bit relative)
* int3
*/
#define CALL_DUMMY { 0x223344e8, 0xcc11 }
#define CALL_DUMMY_LENGTH 8
#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
/* Insert the specified number of args and function address
into a call sequence of the above form stored at DUMMYNAME. */
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \
{ \
int from, to, delta, loc; \
loc = (int)(read_register (SP_REGNUM) - CALL_DUMMY_LENGTH); \
from = loc + 5; \
to = (int)(fun); \
delta = to - from; \
*(int *)((char *)(dummyname) + 1) = delta; \
}
#if 0
/* Interface definitions for kernel debugger KDB. */
/* Map machine fault codes into signal numbers.
First subtract 0, divide by 4, then index in a table.
Faults for which the entry in this table is 0
are not handled by KDB; the program's own trap handler
gets to handle then. */
#define FAULT_CODE_ORIGIN 0
#define FAULT_CODE_UNITS 4
#define FAULT_TABLE \
{ 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0}
/* Start running with a stack stretching from BEG to END.
BEG and END should be symbols meaningful to the assembler.
This is used only for kdb. */
#define INIT_STACK(beg, end) {}
/* Push the frame pointer register on the stack. */
#define PUSH_FRAME_PTR {}
/* Copy the top-of-stack to the frame pointer register. */
#define POP_FRAME_PTR {}
/* After KDB is entered by a fault, push all registers
that GDB thinks about (all NUM_REGS of them),
so that they appear in order of ascending GDB register number.
The fault code will be on the stack beyond the last register. */
#define PUSH_REGISTERS {}
/* Assuming the registers (including processor status) have been
pushed on the stack in order of ascending GDB register number,
restore them and return to the address in the saved PC register. */
#define POP_REGISTERS {}
#endif

View file

@ -0,0 +1,374 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
* Modified 1991 by William Jolitz at UUNET Technologies, Inc.
*
* @(#)m-i386bsd.h 6.7 (Berkeley) 5/8/91
*/
/* Macro definitions for i386.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Define the bit, byte, and word ordering of the machine. */
/* #define BITS_BIG_ENDIAN */
/* #define BYTES_BIG_ENDIAN */
/* #define WORDS_BIG_ENDIAN */
/*
* Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
* July 1988
* [ MODIFIED FOR 386BSD W. Jolitz ]
*/
#ifndef i386
#define i386 1
#define i386b 1
#endif
#define IEEE_FLOAT
/* Library stuff: POSIX tty (not supported yet), V7 tty (sigh), vprintf. */
#define HAVE_TERMIOS 1
#define USE_OLD_TTY 1
#define HAVE_VPRINTF 1
/* We support local and remote kernel debugging. */
#define KERNELDEBUG 1
/* Get rid of any system-imposed stack limit if possible. */
#define SET_STACK_LIMIT_HUGE
/* Define this if the C compiler puts an underscore at the front
of external names before giving them to the linker. */
#define NAMES_HAVE_UNDERSCORE
/* Specify debugger information format. */
#define READ_DBX_FORMAT
/* number of traps that happen between exec'ing the shell
* to run an inferior, and when we finally get to
* the inferior code. This is 2 on most implementations.
*/
#define START_INFERIOR_TRAPS_EXPECTED 2
/* Offset from address of function to start of its code.
Zero on most machines. */
#define FUNCTION_START_OFFSET 0
/* Advance PC across any function entry prologue instructions
to reach some "real" code. */
#define SKIP_PROLOGUE(frompc) {(frompc) = i386_skip_prologue((frompc));}
/* Immediately after a function call, return the saved pc.
Can't always go through the frames for this because on some machines
the new frame is not set up until the new function executes
some instructions. */
#define SAVED_PC_AFTER_CALL(frame) \
(read_memory_integer (read_register (SP_REGNUM), 4))
/* This is the amount to subtract from u.u_ar0
to get the offset in the core file of the register values. */
#ifdef NEWVM
#include <machine/vmparam.h>
#define KERNEL_U_ADDR USRSTACK
#else
#define KERNEL_U_ADDR 0xfdffd000
#endif
/* Address of end of stack space. */
#define STACK_END_ADDR KERNEL_U_ADDR
/* Stack grows downward. */
#define INNER_THAN <
/* Sequence of bytes for breakpoint instruction. */
#define BREAKPOINT {0xcc}
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always. */
#define DECR_PC_AFTER_BREAK 1
/* Nonzero if instruction at PC is a return instruction. */
#define ABOUT_TO_RETURN(pc) \
strchr("\302\303\312\313\317", read_memory_integer(pc, 1))
/* Return 1 if P points to an invalid floating point value.
LEN is the length in bytes -- not relevant on the 386. */
#define INVALID_FLOAT(p, len) (0)
/* code to execute to print interesting information about the
* floating point processor (if any)
* No need to define if there is nothing to do.
*/
#define FLOAT_INFO { i386_float_info (); }
/* Largest integer type */
#define LONGEST long
/* Name of the builtin type for the LONGEST type above. */
#define BUILTIN_TYPE_LONGEST builtin_type_long
/* Say how long (ordinary) registers are. */
#define REGISTER_TYPE long
/* Number of machine registers */
#define NUM_REGS 16
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer. */
/* the order of the first 8 registers must match the compiler's
* numbering scheme (which is the same as the 386 scheme)
* also, this table must match regmap in i386-pinsn.c.
*/
#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
"esp", "ebp", "esi", "edi", \
"eip", "ps", "cs", "ss", \
"ds", "es", "fs", "gs", \
}
/* Register numbers of various important registers.
Note that some of these values are "real" register numbers,
and correspond to the general registers of the machine,
and some are "phony" register numbers which are too large
to be actual register numbers as far as the user is concerned
but do serve to get the desired values when passed to read_register. */
#define FP_REGNUM 5 /* Contains address of executing stack frame */
#define SP_REGNUM 4 /* Contains address of top of stack */
#define PC_REGNUM 8
#define PS_REGNUM 9
#define REGISTER_U_ADDR(addr, blockend, regno) \
(addr) = i386_register_u_addr ((blockend),(regno));
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES (NUM_REGS * 4)
/* Index within `registers' of the first byte of the space for
register N. */
#define REGISTER_BYTE(N) ((N)*4)
/* Number of bytes of storage in the actual machine representation
for register N. */
#define REGISTER_RAW_SIZE(N) (4)
/* Number of bytes of storage in the program's representation
for register N. */
#define REGISTER_VIRTUAL_SIZE(N) (4)
/* Largest value REGISTER_RAW_SIZE can have. */
#define MAX_REGISTER_RAW_SIZE 4
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
#define MAX_REGISTER_VIRTUAL_SIZE 4
/* Nonzero if register N requires conversion
from raw format to virtual format. */
#define REGISTER_CONVERTIBLE(N) (0)
/* Convert data from raw format for register REGNUM
to virtual format for register REGNUM. */
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) {bcopy ((FROM), (TO), 4);}
/* Convert data from virtual format for register REGNUM
to raw format for register REGNUM. */
#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) {bcopy ((FROM), (TO), 4);}
/* Return the GDB type object for the "standard" data type
of data in register N. */
#define REGISTER_VIRTUAL_TYPE(N) (builtin_type_int)
/* Store the address of the place in which to copy the structure the
subroutine will return. This is called from call_function. */
#define STORE_STRUCT_RETURN(ADDR, SP) \
{ (SP) -= sizeof (ADDR); \
write_memory ((SP), &(ADDR), sizeof (ADDR)); }
/* Extract from an array REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
into VALBUF. */
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format. */
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
/* Extract from an array REGBUF containing the (raw) register state
the address in which a function should return its structure value,
as a CORE_ADDR (or an expression that can be used as one). */
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
/* FRAME_CHAIN takes a frame's nominal address
and produces the frame's chain-pointer.
FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
and produces the nominal address of the caller frame.
However, if FRAME_CHAIN_VALID returns zero,
it means the given frame is the outermost one and has no caller.
In that case, FRAME_CHAIN_COMBINE is not used. */
#define FRAME_CHAIN(thisframe) \
(outside_startup_file ((thisframe)->pc) ? \
read_memory_integer ((thisframe)->frame, 4) :\
0)
#ifdef KERNELDEBUG
#define KERNTEXT_BASE 0xfe000000
#ifdef NEWVM
#define KERNSTACK_TOP (read_register(SP_REGNUM) + 0x2000) /* approximate */
#else
/* #define KERNSTACK_TOP (P1PAGES << PGSHIFT) */
#define KERNSTACK_TOP 0xfe000000
#endif
extern int kernel_debugging;
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && \
!kernel_debugging ? outside_startup_file(FRAME_SAVED_PC(thisframe)) :\
(chain >= read_register(SP_REGNUM) && chain < KERNSTACK_TOP))
#else
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
#endif
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
/* A macro that tells us whether the function invocation represented
by FI does not have a frame on the stack associated with it. If it
does not, FRAMELESS is set to 1, else 0. */
#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS)
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
/* Return number of args passed to a frame.
Can return -1, meaning no way to tell. */
#define FRAME_NUM_ARGS(numargs, fi) (numargs) = i386_frame_num_args(fi)
/* Return number of bytes at start of arglist that are not really args. */
#define FRAME_ARGS_SKIP 8
/* Put here the code to store, into a struct frame_saved_regs,
the addresses of the saved registers of frame described by FRAME_INFO.
This includes special registers such as pc and fp saved in special
ways in the stack frame. sp is even more special:
the address we return for it IS the sp for the next frame. */
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
{ i386_frame_find_saved_regs ((frame_info), &(frame_saved_regs)); }
/* Discard from the stack the innermost frame, restoring all registers. */
#define POP_FRAME { i386_pop_frame (); }
#define NEW_CALL_FUNCTION
#if 0
/* Interface definitions for kernel debugger KDB. */
/* Map machine fault codes into signal numbers.
First subtract 0, divide by 4, then index in a table.
Faults for which the entry in this table is 0
are not handled by KDB; the program's own trap handler
gets to handle then. */
#define FAULT_CODE_ORIGIN 0
#define FAULT_CODE_UNITS 4
#define FAULT_TABLE \
{ 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0}
/* Start running with a stack stretching from BEG to END.
BEG and END should be symbols meaningful to the assembler.
This is used only for kdb. */
#define INIT_STACK(beg, end) {}
/* Push the frame pointer register on the stack. */
#define PUSH_FRAME_PTR {}
/* Copy the top-of-stack to the frame pointer register. */
#define POP_FRAME_PTR {}
/* After KDB is entered by a fault, push all registers
that GDB thinks about (all NUM_REGS of them),
so that they appear in order of ascending GDB register number.
The fault code will be on the stack beyond the last register. */
#define PUSH_REGISTERS {}
/* Assuming the registers (including processor status) have been
pushed on the stack in order of ascending GDB register number,
restore them and return to the address in the saved PC register. */
#define POP_REGISTERS {}
#endif

View file

@ -0,0 +1,28 @@
/* Macro defintions for i386, running System V 3.2.
Copyright (C) 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "m-i386gas.h"
/* Apparently there is inconsistency among various System V's about what
the name of this field is. */
#define U_FPSTATE(u) u.u_fps.u_fpstate
/* TIOCGETC is defined in System V 3.2 termio.h, but struct tchars
is not. This makes problems for inflow.c. */
#define TIOCGETC_BROKEN

View file

@ -0,0 +1,37 @@
/* Macro definitions for i386 using the GNU object file format.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
* July 1988
*
* i386gnu: COFF_ENCAPSULATE
*/
#define COFF_ENCAPSULATE
#include "m-i386.h"
#define NAMES_HAVE_UNDERSCORE
#undef COFF_FORMAT
#define READ_DBX_FORMAT

215
gnu/usr.bin/gdb/copying.c Normal file
View file

@ -0,0 +1,215 @@
/* Do not modify this file; it is created automatically
by copying.awk. */
extern int immediate_quit;
static void
copying_info ()
{
immediate_quit++;
printf_filtered ("\n");
printf_filtered (" GNU GENERAL PUBLIC LICENSE\n");
printf_filtered (" Version 1, February 1989\n");
printf_filtered ("\n");
printf_filtered (" Copyright (C) 1989 Free Software Foundation, Inc.\n");
printf_filtered (" 675 Mass Ave, Cambridge, MA 02139, USA\n");
printf_filtered (" Everyone is permitted to copy and distribute verbatim copies\n");
printf_filtered (" of this license document, but changing it is not allowed.\n");
printf_filtered ("\n");
printf_filtered (" Preamble\n");
printf_filtered ("\n");
printf_filtered (" The license agreements of most software companies try to keep users\n");
printf_filtered ("at the mercy of those companies. By contrast, our General Public\n");
printf_filtered ("License is intended to guarantee your freedom to share and change free\n");
printf_filtered ("software--to make sure the software is free for all its users. The\n");
printf_filtered ("General Public License applies to the Free Software Foundation's\n");
printf_filtered ("software and to any other program whose authors commit to using it.\n");
printf_filtered ("You can use it for your programs, too.\n");
printf_filtered ("\n");
printf_filtered (" When we speak of free software, we are referring to freedom, not\n");
printf_filtered ("price. Specifically, the General Public License is designed to make\n");
printf_filtered ("sure that you have the freedom to give away or sell copies of free\n");
printf_filtered ("software, that you receive source code or can get it if you want it,\n");
printf_filtered ("that you can change the software or use pieces of it in new free\n");
printf_filtered ("programs; and that you know you can do these things.\n");
printf_filtered ("\n");
printf_filtered (" To protect your rights, we need to make restrictions that forbid\n");
printf_filtered ("anyone to deny you these rights or to ask you to surrender the rights.\n");
printf_filtered ("These restrictions translate to certain responsibilities for you if you\n");
printf_filtered ("distribute copies of the software, or if you modify it.\n");
printf_filtered ("\n");
printf_filtered (" For example, if you distribute copies of a such a program, whether\n");
printf_filtered ("gratis or for a fee, you must give the recipients all the rights that\n");
printf_filtered ("you have. You must make sure that they, too, receive or can get the\n");
printf_filtered ("source code. And you must tell them their rights.\n");
printf_filtered ("\n");
printf_filtered (" We protect your rights with two steps: (1) copyright the software, and\n");
printf_filtered ("(2) offer you this license which gives you legal permission to copy,\n");
printf_filtered ("distribute and/or modify the software.\n");
printf_filtered ("\n");
printf_filtered (" Also, for each author's protection and ours, we want to make certain\n");
printf_filtered ("that everyone understands that there is no warranty for this free\n");
printf_filtered ("software. If the software is modified by someone else and passed on, we\n");
printf_filtered ("want its recipients to know that what they have is not the original, so\n");
printf_filtered ("that any problems introduced by others will not reflect on the original\n");
printf_filtered ("authors' reputations.\n");
printf_filtered ("\n");
printf_filtered (" The precise terms and conditions for copying, distribution and\n");
printf_filtered ("modification follow.\n");
printf_filtered (" \n");
printf_filtered (" GNU GENERAL PUBLIC LICENSE\n");
printf_filtered (" TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n");
printf_filtered ("\n");
printf_filtered (" 0. This License Agreement applies to any program or other work which\n");
printf_filtered ("contains a notice placed by the copyright holder saying it may be\n");
printf_filtered ("distributed under the terms of this General Public License. The\n");
printf_filtered ("\"Program\", below, refers to any such program or work, and a \"work based\n");
printf_filtered ("on the Program\" means either the Program or any work containing the\n");
printf_filtered ("Program or a portion of it, either verbatim or with modifications. Each\n");
printf_filtered ("licensee is addressed as \"you\".\n");
printf_filtered ("\n");
printf_filtered (" 1. You may copy and distribute verbatim copies of the Program's source\n");
printf_filtered ("code as you receive it, in any medium, provided that you conspicuously and\n");
printf_filtered ("appropriately publish on each copy an appropriate copyright notice and\n");
printf_filtered ("disclaimer of warranty; keep intact all the notices that refer to this\n");
printf_filtered ("General Public License and to the absence of any warranty; and give any\n");
printf_filtered ("other recipients of the Program a copy of this General Public License\n");
printf_filtered ("along with the Program. You may charge a fee for the physical act of\n");
printf_filtered ("transferring a copy.\n");
printf_filtered ("\n");
printf_filtered (" 2. You may modify your copy or copies of the Program or any portion of\n");
printf_filtered ("it, and copy and distribute such modifications under the terms of Paragraph\n");
printf_filtered ("1 above, provided that you also do the following:\n");
printf_filtered ("\n");
printf_filtered (" a) cause the modified files to carry prominent notices stating that\n");
printf_filtered (" you changed the files and the date of any change; and\n");
printf_filtered ("\n");
printf_filtered (" b) cause the whole of any work that you distribute or publish, that\n");
printf_filtered (" in whole or in part contains the Program or any part thereof, either\n");
printf_filtered (" with or without modifications, to be licensed at no charge to all\n");
printf_filtered (" third parties under the terms of this General Public License (except\n");
printf_filtered (" that you may choose to grant warranty protection to some or all\n");
printf_filtered (" third parties, at your option).\n");
printf_filtered ("\n");
printf_filtered (" c) If the modified program normally reads commands interactively when\n");
printf_filtered (" run, you must cause it, when started running for such interactive use\n");
printf_filtered (" in the simplest and most usual way, to print or display an\n");
printf_filtered (" announcement including an appropriate copyright notice and a notice\n");
printf_filtered (" that there is no warranty (or else, saying that you provide a\n");
printf_filtered (" warranty) and that users may redistribute the program under these\n");
printf_filtered (" conditions, and telling the user how to view a copy of this General\n");
printf_filtered (" Public License.\n");
printf_filtered ("\n");
printf_filtered (" d) You may charge a fee for the physical act of transferring a\n");
printf_filtered (" copy, and you may at your option offer warranty protection in\n");
printf_filtered (" exchange for a fee.\n");
printf_filtered ("\n");
printf_filtered ("Mere aggregation of another independent work with the Program (or its\n");
printf_filtered ("derivative) on a volume of a storage or distribution medium does not bring\n");
printf_filtered ("the other work under the scope of these terms.\n");
printf_filtered (" \n");
printf_filtered (" 3. You may copy and distribute the Program (or a portion or derivative of\n");
printf_filtered ("it, under Paragraph 2) in object code or executable form under the terms of\n");
printf_filtered ("Paragraphs 1 and 2 above provided that you also do one of the following:\n");
printf_filtered ("\n");
printf_filtered (" a) accompany it with the complete corresponding machine-readable\n");
printf_filtered (" source code, which must be distributed under the terms of\n");
printf_filtered (" Paragraphs 1 and 2 above; or,\n");
printf_filtered ("\n");
printf_filtered (" b) accompany it with a written offer, valid for at least three\n");
printf_filtered (" years, to give any third party free (except for a nominal charge\n");
printf_filtered (" for the cost of distribution) a complete machine-readable copy of the\n");
printf_filtered (" corresponding source code, to be distributed under the terms of\n");
printf_filtered (" Paragraphs 1 and 2 above; or,\n");
printf_filtered ("\n");
printf_filtered (" c) accompany it with the information you received as to where the\n");
printf_filtered (" corresponding source code may be obtained. (This alternative is\n");
printf_filtered (" allowed only for noncommercial distribution and only if you\n");
printf_filtered (" received the program in object code or executable form alone.)\n");
printf_filtered ("\n");
printf_filtered ("Source code for a work means the preferred form of the work for making\n");
printf_filtered ("modifications to it. For an executable file, complete source code means\n");
printf_filtered ("all the source code for all modules it contains; but, as a special\n");
printf_filtered ("exception, it need not include source code for modules which are standard\n");
printf_filtered ("libraries that accompany the operating system on which the executable\n");
printf_filtered ("file runs, or for standard header files or definitions files that\n");
printf_filtered ("accompany that operating system.\n");
printf_filtered ("\n");
printf_filtered (" 4. You may not copy, modify, sublicense, distribute or transfer the\n");
printf_filtered ("Program except as expressly provided under this General Public License.\n");
printf_filtered ("Any attempt otherwise to copy, modify, sublicense, distribute or transfer\n");
printf_filtered ("the Program is void, and will automatically terminate your rights to use\n");
printf_filtered ("the Program under this License. However, parties who have received\n");
printf_filtered ("copies, or rights to use copies, from you under this General Public\n");
printf_filtered ("License will not have their licenses terminated so long as such parties\n");
printf_filtered ("remain in full compliance.\n");
printf_filtered ("\n");
printf_filtered (" 5. By copying, distributing or modifying the Program (or any work based\n");
printf_filtered ("on the Program) you indicate your acceptance of this license to do so,\n");
printf_filtered ("and all its terms and conditions.\n");
printf_filtered ("\n");
printf_filtered (" 6. Each time you redistribute the Program (or any work based on the\n");
printf_filtered ("Program), the recipient automatically receives a license from the original\n");
printf_filtered ("licensor to copy, distribute or modify the Program subject to these\n");
printf_filtered ("terms and conditions. You may not impose any further restrictions on the\n");
printf_filtered ("recipients' exercise of the rights granted herein.\n");
printf_filtered (" \n");
printf_filtered (" 7. The Free Software Foundation may publish revised and/or new versions\n");
printf_filtered ("of the General Public License from time to time. Such new versions will\n");
printf_filtered ("be similar in spirit to the present version, but may differ in detail to\n");
printf_filtered ("address new problems or concerns.\n");
printf_filtered ("\n");
printf_filtered ("Each version is given a distinguishing version number. If the Program\n");
printf_filtered ("specifies a version number of the license which applies to it and \"any\n");
printf_filtered ("later version\", you have the option of following the terms and conditions\n");
printf_filtered ("either of that version or of any later version published by the Free\n");
printf_filtered ("Software Foundation. If the Program does not specify a version number of\n");
printf_filtered ("the license, you may choose any version ever published by the Free Software\n");
printf_filtered ("Foundation.\n");
printf_filtered ("\n");
printf_filtered (" 8. If you wish to incorporate parts of the Program into other free\n");
printf_filtered ("programs whose distribution conditions are different, write to the author\n");
printf_filtered ("to ask for permission. For software which is copyrighted by the Free\n");
printf_filtered ("Software Foundation, write to the Free Software Foundation; we sometimes\n");
printf_filtered ("make exceptions for this. Our decision will be guided by the two goals\n");
printf_filtered ("of preserving the free status of all derivatives of our free software and\n");
printf_filtered ("of promoting the sharing and reuse of software generally.\n");
printf_filtered ("\n");
immediate_quit--;
}
static void
warranty_info ()
{
immediate_quit++;
printf_filtered (" NO WARRANTY\n");
printf_filtered ("\n");
printf_filtered (" 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n");
printf_filtered ("FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n");
printf_filtered ("OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n");
printf_filtered ("PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n");
printf_filtered ("OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n");
printf_filtered ("MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n");
printf_filtered ("TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n");
printf_filtered ("PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n");
printf_filtered ("REPAIR OR CORRECTION.\n");
printf_filtered ("\n");
printf_filtered (" 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n");
printf_filtered ("WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n");
printf_filtered ("REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n");
printf_filtered ("INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n");
printf_filtered ("OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n");
printf_filtered ("TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n");
printf_filtered ("YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n");
printf_filtered ("PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n");
printf_filtered ("POSSIBILITY OF SUCH DAMAGES.\n");
printf_filtered ("\n");
immediate_quit--;
}
void
_initialize_copying ()
{
add_info ("copying", copying_info,
"Conditions for redistributing copies of GDB.");
add_info ("warranty", warranty_info,
"Various kinds of warranty you do not have.");
}

581
gnu/usr.bin/gdb/core.c Normal file
View file

@ -0,0 +1,581 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
* Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
*/
#ifndef lint
static char sccsid[] = "@(#)core.c 6.3 (Berkeley) 5/8/91";
#endif /* not lint */
/* Work with core dump and executable files, for GDB.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "defs.h"
#include "param.h"
#include "frame.h" /* required by inferior.h */
#include "inferior.h"
#ifdef USG
#include <sys/types.h>
#include <fcntl.h>
#endif
#ifdef COFF_ENCAPSULATE
#include "a.out.encap.h"
#else
#include <a.out.h>
#endif
#ifndef N_MAGIC
#ifdef COFF_FORMAT
#define N_MAGIC(exec) ((exec).magic)
#else
#define N_MAGIC(exec) ((exec).a_magic)
#endif
#endif
#include <signal.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/file.h>
#include <sys/stat.h>
#ifdef UMAX_CORE
#include <sys/ptrace.h>
#else
#include <sys/user.h>
#endif
#ifndef N_TXTADDR
#define N_TXTADDR(hdr) 0
#endif /* no N_TXTADDR */
#ifndef N_DATADDR
#define N_DATADDR(hdr) hdr.a_text
#endif /* no N_DATADDR */
#ifndef COFF_FORMAT
#ifndef AOUTHDR
#define AOUTHDR struct exec
#endif
#endif
extern char *sys_siglist[];
extern core_file_command (), exec_file_command ();
/* Hook for `exec_file_command' command to call. */
void (*exec_file_display_hook) ();
/* File names of core file and executable file. */
char *corefile;
char *execfile;
/* Descriptors on which core file and executable file are open.
Note that the execchan is closed when an inferior is created
and reopened if the inferior dies or is killed. */
int corechan;
int execchan;
/* Last modification time of executable file.
Also used in source.c to compare against mtime of a source file. */
int exec_mtime;
/* Virtual addresses of bounds of the two areas of memory in the core file. */
CORE_ADDR data_start;
CORE_ADDR data_end;
CORE_ADDR stack_start;
CORE_ADDR stack_end;
#if defined (REG_STACK_SEGMENT)
/* Start and end of the register stack segment. */
CORE_ADDR reg_stack_start;
CORE_ADDR reg_stack_end;
#endif /* REG_STACK_SEGMENT */
/* Virtual addresses of bounds of two areas of memory in the exec file.
Note that the data area in the exec file is used only when there is no core file. */
CORE_ADDR text_start;
CORE_ADDR text_end;
CORE_ADDR exec_data_start;
CORE_ADDR exec_data_end;
/* Offset within executable file of start of text area data. */
int text_offset;
/* Offset within executable file of start of data area data. */
int exec_data_offset;
/* Offset within core file of start of data area data. */
int data_offset;
/* Offset within core file of start of stack area data. */
int stack_offset;
#ifdef COFF_FORMAT
/* various coff data structures */
FILHDR file_hdr;
SCNHDR text_hdr;
SCNHDR data_hdr;
#endif /* not COFF_FORMAT */
/* a.out header saved in core file. */
AOUTHDR core_aouthdr;
/* a.out header of exec file. */
AOUTHDR exec_aouthdr;
void validate_files ();
unsigned int register_addr ();
/* Call this to specify the hook for exec_file_command to call back.
This is called from the x-window display code. */
void
specify_exec_file_hook (hook)
void (*hook) ();
{
exec_file_display_hook = hook;
}
/* The exec file must be closed before running an inferior.
If it is needed again after the inferior dies, it must
be reopened. */
void
close_exec_file ()
{
if (execchan >= 0)
close (execchan);
execchan = -1;
}
void
reopen_exec_file ()
{
if (execchan < 0 && execfile != 0)
{
char *filename = concat (execfile, "", "");
exec_file_command (filename, 0);
free (filename);
}
}
/* If we have both a core file and an exec file,
print a warning if they don't go together.
This should really check that the core file came
from that exec file, but I don't know how to do it. */
void
validate_files ()
{
if (execfile != 0 && corefile != 0)
{
struct stat st_core;
if (fstat (corechan, &st_core) < 0)
/* It might be a good idea to print an error message.
On the other hand, if the user tries to *do* anything with
the core file, (s)he'll find out soon enough. */
return;
if (N_MAGIC (core_aouthdr) != 0
&& bcmp (&core_aouthdr, &exec_aouthdr, sizeof core_aouthdr))
printf ("Warning: core file does not match specified executable file.\n");
else if (exec_mtime > st_core.st_mtime) {
#ifdef KERNELDEBUG
extern int kernel_debugging;
if (!kernel_debugging)
#endif
printf ("Warning: exec file is newer than core file.\n");
}
}
}
/* Return the name of the executable file as a string.
ERR nonzero means get error if there is none specified;
otherwise return 0 in that case. */
char *
get_exec_file (err)
int err;
{
if (err && execfile == 0)
error ("No executable file specified.\n\
Use the \"exec-file\" and \"symbol-file\" commands.");
return execfile;
}
int
have_core_file_p ()
{
return corefile != 0;
}
static void
files_info ()
{
char *symfile;
extern char *get_sym_file ();
if (execfile)
printf ("Executable file \"%s\".\n", execfile);
else
printf ("No executable file\n");
if (corefile == 0)
printf ("No core dump file\n");
else
printf ("Core dump file \"%s\".\n", corefile);
if (have_inferior_p ())
printf ("Using the running image of the program, rather than these files.\n");
symfile = get_sym_file ();
if (symfile != 0)
printf ("Symbols from \"%s\".\n", symfile);
#ifdef FILES_INFO_HOOK
if (FILES_INFO_HOOK ())
return;
#endif
if (! have_inferior_p ())
{
if (execfile)
{
printf ("Text segment in executable from 0x%x to 0x%x.\n",
text_start, text_end);
printf ("Data segment in executable from 0x%x to 0x%x.\n",
exec_data_start, exec_data_end);
if (corefile)
printf ("(But since we have a core file, we're using...)\n");
}
if (corefile)
{
printf ("Data segment in core file from 0x%x to 0x%x.\n",
data_start, data_end);
printf ("Stack segment in core file from 0x%x to 0x%x.\n",
stack_start, stack_end);
}
}
}
/* Read "memory data" from core file and/or executable file.
Returns zero if successful, 1 if xfer_core_file failed, errno value if
ptrace failed. */
int
read_memory (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
if (len == 0)
return 0;
if (have_inferior_p ())
{
if (remote_debugging)
return remote_read_inferior_memory (memaddr, myaddr, len);
else
return read_inferior_memory (memaddr, myaddr, len);
}
else
return xfer_core_file (memaddr, myaddr, len);
}
/* Write LEN bytes of data starting at address MYADDR
into debugged program memory at address MEMADDR.
Returns zero if successful, or an errno value if ptrace failed. */
int
write_memory (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
if (have_inferior_p ())
{
if (remote_debugging)
return remote_write_inferior_memory (memaddr, myaddr, len);
else
return write_inferior_memory (memaddr, myaddr, len);
}
else
error ("Can write memory only when program being debugged is running.");
}
#ifndef XFER_CORE_FILE
int (*core_file_hook)(); /* hook to handle special core files like
like /dev/mem and crash dumps */
/* Read from the program's memory (except for inferior processes).
This function is misnamed, since it only reads, never writes; and
since it will use the core file and/or executable file as necessary.
It should be extended to write as well as read, FIXME, for patching files.
Return 0 if address could be read, 1 if not. */
int
xfer_core_file (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
register int i;
register int val;
int xferchan;
char **xferfile;
int fileptr;
int returnval = 0;
if (core_file_hook)
return ((*core_file_hook)(memaddr, myaddr, len));
while (len > 0)
{
xferfile = 0;
xferchan = 0;
/* Determine which file the next bunch of addresses reside in,
and where in the file. Set the file's read/write pointer
to point at the proper place for the desired address
and set xferfile and xferchan for the correct file.
If desired address is nonexistent, leave them zero.
i is set to the number of bytes that can be handled
along with the next address.
We put the most likely tests first for efficiency. */
/* Note that if there is no core file
data_start and data_end are equal. */
if (memaddr >= data_start && memaddr < data_end)
{
i = min (len, data_end - memaddr);
fileptr = memaddr - data_start + data_offset;
xferfile = &corefile;
xferchan = corechan;
}
/* Note that if there is no core file
stack_start and stack_end are equal. */
else if (memaddr >= stack_start && memaddr < stack_end)
{
i = min (len, stack_end - memaddr);
fileptr = memaddr - stack_start + stack_offset;
xferfile = &corefile;
xferchan = corechan;
}
#ifdef REG_STACK_SEGMENT
/* Pyramids have an extra segment in the virtual address space
for the (control) stack of register-window frames */
else if (memaddr >= reg_stack_start && memaddr < reg_stack_end)
{
i = min (len, reg_stack_end - memaddr);
fileptr = memaddr - reg_stack_start + reg_stack_offset;
xferfile = &corefile;
xferchan = corechan;
}
#endif /* REG_STACK_SEGMENT */
else if (corechan < 0
&& memaddr >= exec_data_start && memaddr < exec_data_end)
{
i = min (len, exec_data_end - memaddr);
fileptr = memaddr - exec_data_start + exec_data_offset;
xferfile = &execfile;
xferchan = execchan;
}
else if (memaddr >= text_start && memaddr < text_end)
{
i = min (len, text_end - memaddr);
fileptr = memaddr - text_start + text_offset;
xferfile = &execfile;
xferchan = execchan;
}
else if (memaddr < text_start)
{
i = min (len, text_start - memaddr);
}
else if (memaddr >= text_end
&& memaddr < (corechan >= 0? data_start : exec_data_start))
{
i = min (len, data_start - memaddr);
}
else if (corechan >= 0
&& memaddr >= data_end && memaddr < stack_start)
{
i = min (len, stack_start - memaddr);
}
else if (corechan < 0 && memaddr >= exec_data_end)
{
/* Since there is nothing at higher addresses than data
(without a core file or an inferior, there is no
stack, set i to do the rest of the operation now. */
i = len;
}
#ifdef REG_STACK_SEGMENT
else if (memaddr >= reg_stack_end && reg_stack_end != 0)
{
i = min (len, reg_stack_start - memaddr);
}
else if (memaddr >= stack_end && memaddr < reg_stack_start)
#else /* no REG_STACK_SEGMENT. */
else if (memaddr >= stack_end && stack_end != 0)
#endif /* no REG_STACK_SEGMENT. */
{
/* Since there is nothing at higher addresses than
the stack, set i to do the rest of the operation now. */
i = len;
}
else
{
/* Address did not classify into one of the known ranges.
This shouldn't happen; we catch the endpoints. */
fatal ("Internal: Bad case logic in xfer_core_file.");
}
/* Now we know which file to use.
Set up its pointer and transfer the data. */
if (xferfile)
{
if (*xferfile == 0)
if (xferfile == &execfile)
error ("No program file to examine.");
else
error ("No core dump file or running program to examine.");
val = lseek (xferchan, fileptr, 0);
if (val == -1)
perror_with_name (*xferfile);
val = myread (xferchan, myaddr, i);
if (val < 0)
perror_with_name (*xferfile);
}
/* If this address is for nonexistent memory,
read zeros if reading, or do nothing if writing.
Actually, we never right. */
else
{
bzero (myaddr, i);
returnval = 1;
}
memaddr += i;
myaddr += i;
len -= i;
}
return returnval;
}
#endif /* XFER_CORE_FILE */
/* My replacement for the read system call.
Used like `read' but keeps going if `read' returns too soon. */
int
myread (desc, addr, len)
int desc;
char *addr;
int len;
{
register int val;
int orglen = len;
while (len > 0)
{
val = read (desc, addr, len);
if (val < 0)
return val;
if (val == 0)
return orglen - len;
len -= val;
addr += val;
}
return orglen;
}
#ifdef REGISTER_U_ADDR
/* Return the address in the core dump or inferior of register REGNO.
BLOCKEND is the address of the end of the user structure. */
unsigned int
register_addr (regno, blockend)
int regno;
int blockend;
{
int addr;
if (regno < 0 || regno >= NUM_REGS)
error ("Invalid register number %d.", regno);
REGISTER_U_ADDR (addr, blockend, regno);
return addr;
}
#endif /* REGISTER_U_ADDR */
void
_initialize_core()
{
corechan = -1;
execchan = -1;
corefile = 0;
execfile = 0;
exec_file_display_hook = 0;
text_start = 0;
text_end = 0;
data_start = 0;
data_end = 0;
exec_data_start = 0;
exec_data_end = 0;
stack_start = STACK_END_ADDR;
stack_end = STACK_END_ADDR;
add_com ("core-file", class_files, core_file_command,
"Use FILE as core dump for examining memory and registers.\n\
No arg means have no core file.");
add_com ("exec-file", class_files, exec_file_command,
"Use FILE as program for getting contents of pure memory.\n\
If FILE cannot be found as specified, your execution directory path\n\
is searched for a command of that name.\n\
No arg means have no executable file.");
add_info ("files", files_info, "Names of files being debugged.");
}

996
gnu/usr.bin/gdb/cplus-dem.c Normal file
View file

@ -0,0 +1,996 @@
/* Demangler for GNU C++
Copyright (C) 1989 Free Software Foundation, Inc.
written by James Clark (jjc@jclark.uucp)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This is for g++ 1.36.1 (November 6 version). It will probably
require changes for any other version.
Modified for g++ 1.36.2 (November 18 version). */
/* This file exports one function
char *cplus_demangle (const char *name, int mode)
If NAME is a mangled function name produced by GNU C++, then
a pointer to a malloced string giving a C++ representation
of the name will be returned; otherwise NULL will be returned.
It is the caller's responsibility to free the string which
is returned.
If MODE > 0, then ANSI qualifiers such as `const' and `void' are output.
Otherwise they are not.
If MODE >= 0, parameters are emitted; otherwise not.
For example,
cplus_demangle ("foo__1Ai", 0) => "A::foo(int)"
cplus_demangle ("foo__1Ai", 1) => "A::foo(int)"
cplus_demangle ("foo__1Ai", -1) => "A::foo"
cplus_demangle ("foo__1Afe", 0) => "A::foo(float,...)"
cplus_demangle ("foo__1Afe", 1) => "A::foo(float,...)"
cplus_demangle ("foo__1Afe", -1) => "A::foo"
This file imports xmalloc and xrealloc, which are like malloc and
realloc except that they generate a fatal error if there is no
available memory. */
/* #define nounderscore 1 /* define this is names don't start with _ */
#include <stdio.h>
#include <ctype.h>
#ifdef USG
#include <memory.h>
#include <string.h>
#else
#include <strings.h>
#define memcpy(s1, s2, n) bcopy ((s2), (s1), (n))
#define memcmp(s1, s2, n) bcmp ((s2), (s1), (n))
#define strchr index
#define strrchr rindex
#endif
#ifndef __STDC__
#define const
#endif
#ifdef __STDC__
extern char *cplus_demangle (const char *type, int mode);
#else
extern char *cplus_demangle ();
#endif
#ifdef __STDC__
extern char *xmalloc (int);
extern char *xrealloc (char *, int);
#else
extern char *xmalloc ();
extern char *xrealloc ();
#endif
static char **typevec = 0;
static int ntypes = 0;
static int typevec_size = 0;
static struct {
const char *in;
const char *out;
} optable[] = {
"new", " new",
"delete", " delete",
"ne", "!=",
"eq", "==",
"ge", ">=",
"gt", ">",
"le", "<=",
"lt", "<",
"plus", "+",
"minus", "-",
"mult", "*",
"convert", "+", /* unary + */
"negate", "-", /* unary - */
"trunc_mod", "%",
"trunc_div", "/",
"truth_andif", "&&",
"truth_orif", "||",
"truth_not", "!",
"postincrement", "++",
"postdecrement", "--",
"bit_ior", "|",
"bit_xor", "^",
"bit_and", "&",
"bit_not", "~",
"call", "()",
"cond", "?:",
"alshift", "<<",
"arshift", ">>",
"component", "->",
"indirect", "*",
"method_call", "->()",
"addr", "&", /* unary & */
"array", "[]",
"nop", "", /* for operator= */
};
/* Beware: these aren't '\0' terminated. */
typedef struct {
char *b; /* pointer to start of string */
char *p; /* pointer after last character */
char *e; /* pointer after end of allocated space */
} string;
#ifdef __STDC__
static void string_need (string *s, int n);
static void string_delete (string *s);
static void string_init (string *s);
static void string_clear (string *s);
static int string_empty (string *s);
static void string_append (string *p, const char *s);
static void string_appends (string *p, string *s);
static void string_appendn (string *p, const char *s, int n);
static void string_prepend (string *p, const char *s);
#if 0
static void string_prepends (string *p, string *s);
#endif
static void string_prependn (string *p, const char *s, int n);
static int get_count (const char **type, int *count);
static int do_args (const char **type, string *decl, int arg_mode);
static int do_type (const char **type, string *result, int arg_mode);
static int do_arg (const char **type, string *result, int arg_mode);
static void munge_function_name (string *name, int arg_mode);
static void remember_type (const char *type, int len);
#else
static void string_need ();
static void string_delete ();
static void string_init ();
static void string_clear ();
static int string_empty ();
static void string_append ();
static void string_appends ();
static void string_appendn ();
static void string_prepend ();
static void string_prepends ();
static void string_prependn ();
static int get_count ();
static int do_args ();
static int do_type ();
static int do_arg ();
static int do_args ();
static void munge_function_name ();
static void remember_type ();
#endif
char *
cplus_demangle (type, arg_mode)
const char *type;
int arg_mode;
{
string decl;
int n;
int success = 0;
int constructor = 0;
int const_flag = 0;
int i;
const char *p;
#ifndef LONGERNAMES
const char *premangle;
#endif
# define print_ansi_qualifiers (arg_mode > 0)
# define print_arg_types (arg_mode >= 0)
if (type == NULL || *type == '\0')
return NULL;
#ifndef nounderscore
if (*type++ != '_')
return NULL;
#endif
p = type;
while (*p != '\0' && !(*p == '_' && p[1] == '_'))
p++;
if (*p == '\0')
{
/* destructor */
if (type[0] == '_' && type[1] == '$' && type[2] == '_')
{
int n = (strlen (type) - 3)*2 + 3 + 2 + 1;
char *tem = (char *) xmalloc (n);
strcpy (tem, type + 3);
strcat (tem, "::~");
strcat (tem, type + 3);
strcat (tem, "()");
return tem;
}
/* static data member */
if (*type != '_' && (p = strchr (type, '$')) != NULL)
{
int n = strlen (type) + 2;
char *tem = (char *) xmalloc (n);
memcpy (tem, type, p - type);
strcpy (tem + (p - type), "::");
strcpy (tem + (p - type) + 2, p + 1);
return tem;
}
/* virtual table "_vt$" */
if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == '$')
{
int n = strlen (type + 4) + 14 + 1;
char *tem = (char *) xmalloc (n);
strcpy (tem, type + 4);
strcat (tem, " virtual table");
return tem;
}
return NULL;
}
string_init (&decl);
if (p == type)
{
if (!isdigit (p[2]))
{
string_delete (&decl);
return NULL;
}
constructor = 1;
}
else
{
string_appendn (&decl, type, p - type);
munge_function_name (&decl, arg_mode);
}
p += 2;
#ifndef LONGERNAMES
premangle = p;
#endif
switch (*p)
{
case 'C':
/* a const member function */
if (!isdigit (p[1]))
{
string_delete (&decl);
return NULL;
}
p += 1;
const_flag = 1;
/* fall through */
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
n = 0;
do
{
n *= 10;
n += *p - '0';
p += 1;
}
while (isdigit (*p));
if (strlen (p) < n)
{
string_delete (&decl);
return NULL;
}
if (constructor)
{
string_appendn (&decl, p, n);
string_append (&decl, "::");
string_appendn (&decl, p, n);
}
else
{
string_prepend (&decl, "::");
string_prependn (&decl, p, n);
}
p += n;
#ifndef LONGERNAMES
remember_type (premangle, p - premangle);
#endif
success = do_args (&p, &decl, arg_mode);
if (const_flag && print_arg_types)
string_append (&decl, " const");
break;
case 'F':
p += 1;
success = do_args (&p, &decl, arg_mode);
break;
}
for (i = 0; i < ntypes; i++)
if (typevec[i] != NULL)
free (typevec[i]);
ntypes = 0;
if (typevec != NULL)
{
free ((char *)typevec);
typevec = NULL;
typevec_size = 0;
}
if (success)
{
string_appendn (&decl, "", 1);
return decl.b;
}
else
{
string_delete (&decl);
return NULL;
}
}
static int
get_count (type, count)
const char **type;
int *count;
{
if (!isdigit (**type))
return 0;
*count = **type - '0';
*type += 1;
/* see flush_repeats in cplus-method.c */
if (isdigit (**type))
{
const char *p = *type;
int n = *count;
do
{
n *= 10;
n += *p - '0';
p += 1;
}
while (isdigit (*p));
if (*p == '_')
{
*type = p + 1;
*count = n;
}
}
return 1;
}
/* result will be initialised here; it will be freed on failure */
static int
do_type (type, result, arg_mode)
const char **type;
string *result;
int arg_mode;
{
int n;
int done;
int non_empty = 0;
int success;
string decl;
const char *remembered_type;
string_init (&decl);
string_init (result);
done = 0;
success = 1;
while (success && !done)
{
int member;
switch (**type)
{
case 'P':
*type += 1;
string_prepend (&decl, "*");
break;
case 'R':
*type += 1;
string_prepend (&decl, "&");
break;
case 'T':
*type += 1;
if (!get_count (type, &n) || n >= ntypes)
success = 0;
else
{
remembered_type = typevec[n];
type = &remembered_type;
}
break;
case 'F':
*type += 1;
if (!string_empty (&decl) && decl.b[0] == '*')
{
string_prepend (&decl, "(");
string_append (&decl, ")");
}
if (!do_args (type, &decl, arg_mode) || **type != '_')
success = 0;
else
*type += 1;
break;
case 'M':
case 'O':
{
int constp = 0;
int volatilep = 0;
member = **type == 'M';
*type += 1;
if (!isdigit (**type))
{
success = 0;
break;
}
n = 0;
do
{
n *= 10;
n += **type - '0';
*type += 1;
}
while (isdigit (**type));
if (strlen (*type) < n)
{
success = 0;
break;
}
string_append (&decl, ")");
string_prepend (&decl, "::");
string_prependn (&decl, *type, n);
string_prepend (&decl, "(");
*type += n;
if (member)
{
if (**type == 'C')
{
*type += 1;
constp = 1;
}
if (**type == 'V')
{
*type += 1;
volatilep = 1;
}
if (*(*type)++ != 'F')
{
success = 0;
break;
}
}
if ((member && !do_args (type, &decl, arg_mode)) || **type != '_')
{
success = 0;
break;
}
*type += 1;
if (! print_ansi_qualifiers)
break;
if (constp)
{
if (non_empty)
string_append (&decl, " ");
else
non_empty = 1;
string_append (&decl, "const");
}
if (volatilep)
{
if (non_empty)
string_append (&decl, " ");
else
non_empty = 1;
string_append (&decl, "volatile");
}
break;
}
case 'C':
if ((*type)[1] == 'P')
{
*type += 1;
if (print_ansi_qualifiers)
{
if (!string_empty (&decl))
string_prepend (&decl, " ");
string_prepend (&decl, "const");
}
break;
}
/* fall through */
default:
done = 1;
break;
}
}
done = 0;
non_empty = 0;
while (success && !done)
{
switch (**type)
{
case 'C':
*type += 1;
if (print_ansi_qualifiers)
{
if (non_empty)
string_append (result, " ");
else
non_empty = 1;
string_append (result, "const");
}
break;
case 'U':
*type += 1;
if (non_empty)
string_append (result, " ");
else
non_empty = 1;
string_append (result, "unsigned");
break;
case 'V':
*type += 1;
if (print_ansi_qualifiers)
{
if (non_empty)
string_append (result, " ");
else
non_empty = 1;
string_append (result, "volatile");
}
break;
default:
done = 1;
break;
}
}
if (success)
switch (**type)
{
case '\0':
case '_':
break;
case 'v':
*type += 1;
if (non_empty)
string_append (result, " ");
string_append (result, "void");
break;
case 'x':
*type += 1;
if (non_empty)
string_append (result, " ");
string_append (result, "long long");
break;
case 'l':
*type += 1;
if (non_empty)
string_append (result, " ");
string_append (result, "long");
break;
case 'i':
*type += 1;
if (non_empty)
string_append (result, " ");
string_append (result, "int");
break;
case 's':
*type += 1;
if (non_empty)
string_append (result, " ");
string_append (result, "short");
break;
case 'c':
*type += 1;
if (non_empty)
string_append (result, " ");
string_append (result, "char");
break;
case 'r':
*type += 1;
if (non_empty)
string_append (result, " ");
string_append (result, "long double");
break;
case 'd':
*type += 1;
if (non_empty)
string_append (result, " ");
string_append (result, "double");
break;
case 'f':
*type += 1;
if (non_empty)
string_append (result, " ");
string_append (result, "float");
break;
case 'G':
*type += 1;
if (!isdigit (**type))
{
success = 0;
break;
}
/* fall through */
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
n = 0;
do
{
n *= 10;
n += **type - '0';
*type += 1;
}
while (isdigit (**type));
if (strlen (*type) < n)
{
success = 0;
break;
}
if (non_empty)
string_append (result, " ");
string_appendn (result, *type, n);
*type += n;
break;
default:
success = 0;
break;
}
if (success)
{
if (!string_empty (&decl))
{
string_append (result, " ");
string_appends (result, &decl);
}
string_delete (&decl);
return 1;
}
else
{
string_delete (&decl);
string_delete (result);
return 0;
}
}
/* `result' will be initialised in do_type; it will be freed on failure */
static int
do_arg (type, result, arg_mode)
const char **type;
string *result;
int arg_mode;
{
const char *start = *type;
if (!do_type (type, result, arg_mode))
return 0;
remember_type (start, *type - start);
return 1;
}
static void
remember_type (start, len)
const char *start;
int len;
{
char *tem;
if (ntypes >= typevec_size)
{
if (typevec_size == 0)
{
typevec_size = 3;
typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
}
else
{
typevec_size *= 2;
typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
}
}
tem = (char *) xmalloc (len + 1);
memcpy (tem, start, len);
tem[len] = '\0';
typevec[ntypes++] = tem;
}
/* `decl' must be already initialised, usually non-empty;
it won't be freed on failure */
static int
do_args (type, decl, arg_mode)
const char **type;
string *decl;
int arg_mode;
{
string arg;
int need_comma = 0;
if (print_arg_types)
string_append (decl, "(");
while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
{
if (**type == 'N')
{
int r;
int t;
*type += 1;
if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
return 0;
while (--r >= 0)
{
const char *tem = typevec[t];
if (need_comma && print_arg_types)
string_append (decl, ", ");
if (!do_arg (&tem, &arg, arg_mode))
return 0;
if (print_arg_types)
string_appends (decl, &arg);
string_delete (&arg);
need_comma = 1;
}
}
else
{
if (need_comma & print_arg_types)
string_append (decl, ", ");
if (!do_arg (type, &arg, arg_mode))
return 0;
if (print_arg_types)
string_appends (decl, &arg);
string_delete (&arg);
need_comma = 1;
}
}
if (**type == 'v')
*type += 1;
else if (**type == 'e')
{
*type += 1;
if (print_arg_types)
{
if (need_comma)
string_append (decl, ",");
string_append (decl, "...");
}
}
if (print_arg_types)
string_append (decl, ")");
return 1;
}
static void
munge_function_name (name, arg_mode)
string *name;
int arg_mode;
{
if (!string_empty (name) && name->p - name->b >= 3
&& name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$')
{
int i;
/* see if it's an assignment expression */
if (name->p - name->b >= 10 /* op$assign_ */
&& memcmp (name->b + 3, "assign_", 7) == 0)
{
for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
{
int len = name->p - name->b - 10;
if (strlen (optable[i].in) == len
&& memcmp (optable[i].in, name->b + 10, len) == 0)
{
string_clear (name);
string_append (name, "operator");
string_append (name, optable[i].out);
string_append (name, "=");
return;
}
}
}
else
{
for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
{
int len = name->p - name->b - 3;
if (strlen (optable[i].in) == len
&& memcmp (optable[i].in, name->b + 3, len) == 0)
{
string_clear (name);
string_append (name, "operator");
string_append (name, optable[i].out);
return;
}
}
}
return;
}
else if (!string_empty (name) && name->p - name->b >= 5
&& memcmp (name->b, "type$", 5) == 0)
{
/* type conversion operator */
string type;
const char *tem = name->b + 5;
if (do_type (&tem, &type, arg_mode))
{
string_clear (name);
string_append (name, "operator ");
string_appends (name, &type);
string_delete (&type);
return;
}
}
}
/* a mini string-handling package */
static void
string_need (s, n)
string *s;
int n;
{
if (s->b == NULL)
{
if (n < 32)
n = 32;
s->p = s->b = (char *) xmalloc (n);
s->e = s->b + n;
}
else if (s->e - s->p < n)
{
int tem = s->p - s->b;
n += tem;
n *= 2;
s->b = (char *) xrealloc (s->b, n);
s->p = s->b + tem;
s->e = s->b + n;
}
}
static void
string_delete (s)
string *s;
{
if (s->b != NULL)
{
free (s->b);
s->b = s->e = s->p = NULL;
}
}
static void
string_init (s)
string *s;
{
s->b = s->p = s->e = NULL;
}
static void
string_clear (s)
string *s;
{
s->p = s->b;
}
static int
string_empty (s)
string *s;
{
return s->b == s->p;
}
static void
string_append (p, s)
string *p;
const char *s;
{
int n;
if (s == NULL || *s == '\0')
return;
n = strlen (s);
string_need (p, n);
memcpy (p->p, s, n);
p->p += n;
}
static void
string_appends (p, s)
string *p, *s;
{
int n;
if (s->b == s->p)
return;
n = s->p - s->b;
string_need (p, n);
memcpy (p->p, s->b, n);
p->p += n;
}
static void
string_appendn (p, s, n)
string *p;
const char *s;
int n;
{
if (n == 0)
return;
string_need (p, n);
memcpy (p->p, s, n);
p->p += n;
}
static void
string_prepend (p, s)
string *p;
const char *s;
{
if (s == NULL || *s == '\0')
return;
string_prependn (p, s, strlen (s));
}
#if 0
static void
string_prepends (p, s)
string *p, *s;
{
if (s->b == s->p)
return;
string_prependn (p, s->b, s->p - s->b);
}
#endif
static void
string_prependn (p, s, n)
string *p;
const char *s;
int n;
{
char *q;
if (n == 0)
return;
string_need (p, n);
for (q = p->p - 1; q >= p->b; q--)
q[n] = q[0];
memcpy (p->b, s, n);
p->p += n;
}

5587
gnu/usr.bin/gdb/dbxread.c Normal file

File diff suppressed because it is too large Load diff

122
gnu/usr.bin/gdb/defs.h Normal file
View file

@ -0,0 +1,122 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
* Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
*
* @(#)defs.h 6.3 (Berkeley) 5/8/91
*/
/* Basic definitions for GDB, the GNU debugger.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define CORE_ADDR unsigned int
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
extern char *savestring ();
extern char *concat ();
extern char *xmalloc (), *xrealloc ();
extern int parse_escape ();
extern char *reg_names[];
/* Various possibilities for alloca. */
#ifdef sparc
#include <alloca.h>
#else
#ifdef __GNUC__
#define alloca __builtin_alloca
#else
extern char *alloca ();
#endif
#endif
extern int quit_flag;
extern int immediate_quit;
#define QUIT { if (quit_flag) quit (); }
/* Notes on classes: class_alias is for alias commands which are not
abbreviations of the original command. */
enum command_class
{
no_class = -1, class_run = 0, class_vars, class_stack,
class_files, class_support, class_info, class_breakpoint,
class_alias, class_obscure, class_user,
};
/* the cleanup list records things that have to be undone
if an error happens (descriptors to be closed, memory to be freed, etc.)
Each link in the chain records a function to call and an
argument to give it.
Use make_cleanup to add an element to the cleanup chain.
Use do_cleanups to do all cleanup actions back to a given
point in the chain. Use discard_cleanups to remove cleanups
from the chain back to a given point, not doing them. */
struct cleanup
{
struct cleanup *next;
void (*function) ();
int arg;
};
extern void do_cleanups ();
extern void discard_cleanups ();
extern struct cleanup *make_cleanup ();
extern struct cleanup *save_cleanups ();
extern void restore_cleanups ();
extern void free_current_contents ();
extern void reinitialize_more_filter ();
extern void fputs_filtered ();
extern void fprintf_filtered ();
extern void printf_filtered ();
extern void print_spaces_filtered ();
extern char *tilde_expand ();
/* Structure for saved commands lines
(for breakpoints, defined commands, etc). */
struct command_line
{
struct command_line *next;
char *line;
int type; /* statement type */
#define CL_END 0
#define CL_NORMAL 1
#define CL_WHILE 2
#define CL_IF 3
#define CL_EXITLOOP 4
#define CL_NOP 5
struct command_line *body; /* body of loop for while, body of if */
struct command_line *elsebody; /* body of else part of if */
};
extern struct command_line *read_command_lines ();
extern void do_command_lines();
/* String containing the current directory (what getwd would return). */
char *current_directory;

185
gnu/usr.bin/gdb/environ.c Normal file
View file

@ -0,0 +1,185 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
* Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
*/
#ifndef lint
static char sccsid[] = "@(#)environ.c 6.3 (Berkeley) 5/8/91";
#endif /* not lint */
/* environ.c -- library for manipulating environments for GNU.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
#include "environ.h"
/* Return a new environment object. */
struct environ *
make_environ ()
{
register struct environ *e;
e = (struct environ *) xmalloc (sizeof (struct environ));
e->allocated = 10;
e->vector = (char **) xmalloc ((e->allocated + 1) * sizeof (char *));
e->vector[0] = 0;
return e;
}
/* Free an environment and all the strings in it. */
void
free_environ (e)
register struct environ *e;
{
register char **vector = e->vector;
while (*vector)
free (*vector++);
free (e);
}
/* Copy the environment given to this process into E.
Also copies all the strings in it, so we can be sure
that all strings in these environments are safe to free. */
void
init_environ (e)
register struct environ *e;
{
extern char **environ;
register int i;
for (i = 0; environ[i]; i++);
if (e->allocated < i)
{
e->allocated = max (i, e->allocated + 10);
e->vector = (char **) xrealloc (e->vector,
(e->allocated + 1) * sizeof (char *));
}
bcopy (environ, e->vector, (i + 1) * sizeof (char *));
while (--i >= 0)
{
register int len = strlen (e->vector[i]) + 1;
register char *new = (char *) xmalloc (len);
bcopy (e->vector[i], new, len);
e->vector[i] = new;
}
}
/* Return the vector of environment E.
This is used to get something to pass to execve. */
char **
environ_vector (e)
struct environ *e;
{
return e->vector;
}
/* Return the value in environment E of variable VAR. */
char *
get_in_environ (e, var)
struct environ *e;
char *var;
{
register int len = strlen (var);
register char **vector = e->vector;
register char *s;
for (; s = *vector; vector++)
if (!strncmp (s, var, len)
&& s[len] == '=')
return &s[len + 1];
return 0;
}
/* Store the value in E of VAR as VALUE. */
void
set_in_environ (e, var, value)
struct environ *e;
char *var;
char *value;
{
register int i;
register int len = strlen (var);
register char **vector = e->vector;
register char *s;
for (i = 0; s = vector[i]; i++)
if (!strncmp (s, var, len)
&& s[len] == '=')
break;
if (s == 0)
{
if (i == e->allocated)
{
e->allocated += 10;
vector = (char **) xrealloc (vector,
(e->allocated + 1) * sizeof (char *));
e->vector = vector;
}
vector[i + 1] = 0;
}
else
free (s);
s = (char *) xmalloc (len + strlen (value) + 2);
strcpy (s, var);
strcat (s, "=");
strcat (s, value);
vector[i] = s;
return;
}
/* Remove the setting for variable VAR from environment E. */
void
unset_in_environ (e, var)
struct environ *e;
char *var;
{
register int len = strlen (var);
register char **vector = e->vector;
register char *s;
for (; s = *vector; vector++)
if (!strncmp (s, var, len)
&& s[len] == '=')
{
free (s);
bcopy (vector + 1, vector,
(e->allocated - (vector - e->vector)) * sizeof (char *));
e->vector[e->allocated - 1] = 0;
return;
}
}

39
gnu/usr.bin/gdb/environ.h Normal file
View file

@ -0,0 +1,39 @@
/* Header for environment manipulation library.
Copyright (C) 1989, Free Software Foundation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* We manipulate environments represented as these structures. */
struct environ
{
/* Number of usable slots allocated in VECTOR.
VECTOR always has one slot not counted here,
to hold the terminating zero. */
int allocated;
/* A vector of slots, ALLOCATED + 1 of them.
The first few slots contain strings "VAR=VALUE"
and the next one contains zero.
Then come some unused slots. */
char **vector;
};
struct environ *make_environ ();
void free_environ ();
void init_environ ();
char *get_in_environ ();
void set_in_environ ();
void unset_in_environ ();
char **environ_vector ();

1065
gnu/usr.bin/gdb/eval.c Normal file

File diff suppressed because it is too large Load diff

324
gnu/usr.bin/gdb/expprint.c Normal file
View file

@ -0,0 +1,324 @@
/* Print in infix form a struct expression.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "defs.h"
#include "symtab.h"
#include "param.h"
#include "expression.h"
#include "value.h"
/* These codes indicate operator precedences, least tightly binding first. */
/* Adding 1 to a precedence value is done for binary operators,
on the operand which is more tightly bound, so that operators
of equal precedence within that operand will get parentheses. */
/* PREC_HYPER and PREC_ABOVE_COMMA are not the precedence of any operator;
they are used as the "surrounding precedence" to force
various kinds of things to be parenthesized. */
enum precedence
{ PREC_NULL, PREC_COMMA, PREC_ABOVE_COMMA, PREC_ASSIGN, PREC_OR, PREC_AND,
PREC_LOGIOR, PREC_LOGAND, PREC_LOGXOR, PREC_EQUAL, PREC_ORDER,
PREC_SHIFT, PREC_ADD, PREC_MUL, PREC_REPEAT,
PREC_HYPER, PREC_PREFIX, PREC_SUFFIX };
/* Table mapping opcodes into strings for printing operators
and precedences of the operators. */
struct op_print
{
char *string;
enum exp_opcode opcode;
/* Precedence of operator. These values are used only by comparisons. */
enum precedence precedence;
int right_assoc;
};
static struct op_print op_print_tab[] =
{
{",", BINOP_COMMA, PREC_COMMA, 0},
{"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
{"||", BINOP_OR, PREC_OR, 0},
{"&&", BINOP_AND, PREC_AND, 0},
{"|", BINOP_LOGIOR, PREC_LOGIOR, 0},
{"&", BINOP_LOGAND, PREC_LOGAND, 0},
{"^", BINOP_LOGXOR, PREC_LOGXOR, 0},
{"==", BINOP_EQUAL, PREC_EQUAL, 0},
{"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
{"<=", BINOP_LEQ, PREC_ORDER, 0},
{">=", BINOP_GEQ, PREC_ORDER, 0},
{">", BINOP_GTR, PREC_ORDER, 0},
{"<", BINOP_LESS, PREC_ORDER, 0},
{">>", BINOP_RSH, PREC_SHIFT, 0},
{"<<", BINOP_LSH, PREC_SHIFT, 0},
{"+", BINOP_ADD, PREC_ADD, 0},
{"-", BINOP_SUB, PREC_ADD, 0},
{"*", BINOP_MUL, PREC_MUL, 0},
{"/", BINOP_DIV, PREC_MUL, 0},
{"%", BINOP_REM, PREC_MUL, 0},
{"@", BINOP_REPEAT, PREC_REPEAT, 0},
{"-", UNOP_NEG, PREC_PREFIX, 0},
{"!", UNOP_ZEROP, PREC_PREFIX, 0},
{"~", UNOP_LOGNOT, PREC_PREFIX, 0},
{"*", UNOP_IND, PREC_PREFIX, 0},
{"&", UNOP_ADDR, PREC_PREFIX, 0},
{"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
{"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
{"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
/* C++ */
{"::", BINOP_SCOPE, PREC_PREFIX, 0},
};
static void print_subexp ();
void
print_expression (exp, stream)
struct expression *exp;
FILE *stream;
{
int pc = 0;
print_subexp (exp, &pc, stream, PREC_NULL);
}
/* Print the subexpression of EXP that starts in position POS, on STREAM.
PREC is the precedence of the surrounding operator;
if the precedence of the main operator of this subexpression is less,
parentheses are needed here. */
static void
print_subexp (exp, pos, stream, prec)
register struct expression *exp;
register int *pos;
FILE *stream;
enum precedence prec;
{
register int tem;
register int pc;
int nargs;
register char *op_str;
int assign_modify = 0;
enum exp_opcode opcode;
enum precedence myprec;
/* Set to 1 for a right-associative operator. */
int assoc;
pc = (*pos)++;
opcode = exp->elts[pc].opcode;
switch (opcode)
{
case OP_SCOPE:
myprec = PREC_PREFIX;
assoc = 0;
(*pos) += 2;
print_subexp (exp, pos, stream, (int) myprec + assoc);
fprintf (stream, " :: ");
nargs = strlen (&exp->elts[pc + 2].string);
(*pos) += 1 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
fprintf (stream, &exp->elts[pc + 2].string);
return;
case OP_LONG:
(*pos) += 3;
value_print (value_from_long (exp->elts[pc + 1].type,
exp->elts[pc + 2].longconst),
stream, 0, Val_no_prettyprint);
return;
case OP_DOUBLE:
(*pos) += 3;
value_print (value_from_double (exp->elts[pc + 1].type,
exp->elts[pc + 2].doubleconst),
stream, 0, Val_no_prettyprint);
return;
case OP_VAR_VALUE:
(*pos) += 2;
fprintf (stream, "%s", SYMBOL_NAME (exp->elts[pc + 1].symbol));
return;
case OP_LAST:
(*pos) += 2;
fprintf (stream, "$%d", (int) exp->elts[pc + 1].longconst);
return;
case OP_REGISTER:
(*pos) += 2;
fprintf (stream, "$%s", reg_names[exp->elts[pc + 1].longconst]);
return;
case OP_INTERNALVAR:
(*pos) += 2;
fprintf (stream, "$%s",
internalvar_name (exp->elts[pc + 1].internalvar));
return;
case OP_FUNCALL:
(*pos) += 2;
nargs = exp->elts[pc + 1].longconst;
print_subexp (exp, pos, stream, PREC_SUFFIX);
fprintf (stream, " (");
for (tem = 0; tem < nargs; tem++)
{
if (tem > 0)
fprintf (stream, ", ");
print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
}
fprintf (stream, ")");
return;
case OP_STRING:
nargs = strlen (&exp->elts[pc + 1].string);
(*pos) += 2 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
fprintf (stream, "\"");
for (tem = 0; tem < nargs; tem++)
printchar ((&exp->elts[pc + 1].string)[tem], stream, '"');
fprintf (stream, "\"");
return;
case TERNOP_COND:
if ((int) prec > (int) PREC_COMMA)
fprintf (stream, "(");
/* Print the subexpressions, forcing parentheses
around any binary operations within them.
This is more parentheses than are strictly necessary,
but it looks clearer. */
print_subexp (exp, pos, stream, PREC_HYPER);
fprintf (stream, " ? ");
print_subexp (exp, pos, stream, PREC_HYPER);
fprintf (stream, " : ");
print_subexp (exp, pos, stream, PREC_HYPER);
if ((int) prec > (int) PREC_COMMA)
fprintf (stream, ")");
return;
case STRUCTOP_STRUCT:
tem = strlen (&exp->elts[pc + 1].string);
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
print_subexp (exp, pos, stream, PREC_SUFFIX);
fprintf (stream, ".%s", &exp->elts[pc + 1].string);
return;
case STRUCTOP_PTR:
tem = strlen (&exp->elts[pc + 1].string);
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
print_subexp (exp, pos, stream, PREC_SUFFIX);
fprintf (stream, "->%s", &exp->elts[pc + 1].string);
return;
case BINOP_SUBSCRIPT:
print_subexp (exp, pos, stream, PREC_SUFFIX);
fprintf (stream, "[");
print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
fprintf (stream, "]");
return;
case UNOP_POSTINCREMENT:
print_subexp (exp, pos, stream, PREC_SUFFIX);
fprintf (stream, "++");
return;
case UNOP_POSTDECREMENT:
print_subexp (exp, pos, stream, PREC_SUFFIX);
fprintf (stream, "--");
return;
case UNOP_CAST:
(*pos) += 2;
if ((int) prec > (int) PREC_PREFIX)
fprintf (stream, "(");
fprintf (stream, "(");
type_print (exp->elts[pc + 1].type, "", stream, 0);
fprintf (stream, ") ");
print_subexp (exp, pos, stream, PREC_PREFIX);
if ((int) prec > (int) PREC_PREFIX)
fprintf (stream, ")");
return;
case UNOP_MEMVAL:
(*pos) += 2;
if ((int) prec > (int) PREC_PREFIX)
fprintf (stream, "(");
fprintf (stream, "{");
type_print (exp->elts[pc + 1].type, "", stream, 0);
fprintf (stream, "} ");
print_subexp (exp, pos, stream, PREC_PREFIX);
if ((int) prec > (int) PREC_PREFIX)
fprintf (stream, ")");
return;
case BINOP_ASSIGN_MODIFY:
opcode = exp->elts[pc + 1].opcode;
(*pos) += 2;
myprec = PREC_ASSIGN;
assoc = 1;
assign_modify = 1;
for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
if (op_print_tab[tem].opcode == opcode)
{
op_str = op_print_tab[tem].string;
break;
}
case OP_THIS:
++(*pos);
fprintf (stream, "this");
return;
default:
for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
if (op_print_tab[tem].opcode == opcode)
{
op_str = op_print_tab[tem].string;
myprec = op_print_tab[tem].precedence;
assoc = op_print_tab[tem].right_assoc;
break;
}
}
if ((int) myprec < (int) prec)
fprintf (stream, "(");
if ((int) opcode > (int) BINOP_END)
{
/* Unary prefix operator. */
fprintf (stream, "%s", op_str);
print_subexp (exp, pos, stream, PREC_PREFIX);
}
else
{
/* Binary operator. */
/* Print left operand.
If operator is right-associative,
increment precedence for this operand. */
print_subexp (exp, pos, stream, (int) myprec + assoc);
/* Print the operator itself. */
if (assign_modify)
fprintf (stream, " %s= ", op_str);
else if (op_str[0] == ',')
fprintf (stream, "%s ", op_str);
else
fprintf (stream, " %s ", op_str);
/* Print right operand.
If operator is left-associative,
increment precedence for this operand. */
print_subexp (exp, pos, stream, (int) myprec + !assoc);
}
if ((int) myprec < (int) prec)
fprintf (stream, ")");
}

1782
gnu/usr.bin/gdb/expread.y Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,191 @@
/* Definitions for expressions stored in reversed prefix form, for GDB.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Definitions for saved C expressions. */
/* An expression is represented as a vector of union exp_element's.
Each exp_element is an opcode, except that some opcodes cause
the following exp_element to be treated as a long or double constant
or as a variable. The opcodes are obeyed, using a stack for temporaries.
The value is left on the temporary stack at the end. */
/* When it is necessary to include a string,
it can occupy as many exp_elements as it needs.
We find the length of the string using strlen,
divide to find out how many exp_elements are used up,
and skip that many. Strings, like numbers, are indicated
by the preceding opcode. */
enum exp_opcode
{
/* BINOP_... operate on two values computed by following subexpressions,
replacing them by one result value. They take no immediate arguments. */
BINOP_ADD, /* + */
BINOP_SUB, /* - */
BINOP_MUL, /* * */
BINOP_DIV, /* / */
BINOP_REM, /* % */
BINOP_LSH, /* << */
BINOP_RSH, /* >> */
BINOP_AND, /* && */
BINOP_OR, /* || */
BINOP_LOGAND, /* & */
BINOP_LOGIOR, /* | */
BINOP_LOGXOR, /* ^ */
BINOP_EQUAL, /* == */
BINOP_NOTEQUAL, /* != */
BINOP_LESS, /* < */
BINOP_GTR, /* > */
BINOP_LEQ, /* <= */
BINOP_GEQ, /* >= */
BINOP_REPEAT, /* @ */
BINOP_ASSIGN, /* = */
BINOP_COMMA, /* , */
BINOP_SUBSCRIPT, /* x[y] */
BINOP_EXP, /* Exponentiation */
/* C++. */
BINOP_MIN, /* <? */
BINOP_MAX, /* >? */
BINOP_SCOPE, /* :: */
/* STRUCTOP_MEMBER is used for pointer-to-member constructs.
X . * Y translates into X STRUCTOP_MEMBER Y. */
STRUCTOP_MEMBER,
/* STRUCTOP_MPTR is used for pointer-to-member constructs
when X is a pointer instead of an aggregate. */
STRUCTOP_MPTR,
/* end of C++. */
BINOP_END,
BINOP_ASSIGN_MODIFY, /* +=, -=, *=, and so on.
The following exp_element is another opcode,
a BINOP_, saying how to modify.
Then comes another BINOP_ASSIGN_MODIFY,
making three exp_elements in total. */
/* Operates on three values computed by following subexpressions. */
TERNOP_COND, /* ?: */
/* The OP_... series take immediate following arguments.
After the arguments come another OP_... (the same one)
so that the grouping can be recognized from the end. */
/* OP_LONG is followed by a type pointer in the next exp_element
and the long constant value in the following exp_element.
Then comes another OP_LONG.
Thus, the operation occupies four exp_elements. */
OP_LONG,
/* OP_DOUBLE is similar but takes a double constant instead of a long one. */
OP_DOUBLE,
/* OP_VAR_VALUE takes one struct symbol * in the following exp_element,
followed by another OP_VAR_VALUE, making three exp_elements. */
OP_VAR_VALUE,
/* OP_LAST is followed by an integer in the next exp_element.
The integer is zero for the last value printed,
or it is the absolute number of a history element.
With another OP_LAST at the end, this makes three exp_elements. */
OP_LAST,
/* OP_REGISTER is followed by an integer in the next exp_element.
This is the number of a register to fetch (as an int).
With another OP_REGISTER at the end, this makes three exp_elements. */
OP_REGISTER,
/* OP_INTERNALVAR is followed by an internalvar ptr in the next exp_element.
With another OP_INTERNALVAR at the end, this makes three exp_elements. */
OP_INTERNALVAR,
/* OP_FUNCALL is followed by an integer in the next exp_element.
The integer is the number of args to the function call.
That many plus one values from following subexpressions
are used, the first one being the function.
The integer is followed by a repeat of OP_FUNCALL,
making three exp_elements. */
OP_FUNCALL,
/* OP_STRING represents a string constant.
Its format is the same as that of a STRUCTOP, but the string
data is just made into a string constant when the operation
is executed. */
OP_STRING,
/* UNOP_CAST is followed by a type pointer in the next exp_element.
With another UNOP_CAST at the end, this makes three exp_elements.
It casts the value of the following subexpression. */
UNOP_CAST,
/* UNOP_MEMVAL is followed by a type pointer in the next exp_element
With another UNOP_MEMVAL at the end, this makes three exp_elements.
It casts the contents of the word addressed by the value of the
following subexpression. */
UNOP_MEMVAL,
/* UNOP_... operate on one value from a following subexpression
and replace it with a result. They take no immediate arguments. */
UNOP_NEG, /* Unary - */
UNOP_ZEROP, /* Unary ! */
UNOP_LOGNOT, /* Unary ~ */
UNOP_IND, /* Unary * */
UNOP_ADDR, /* Unary & */
UNOP_PREINCREMENT, /* ++ before an expression */
UNOP_POSTINCREMENT, /* ++ after an expression */
UNOP_PREDECREMENT, /* -- before an expression */
UNOP_POSTDECREMENT, /* -- after an expression */
UNOP_SIZEOF, /* Unary sizeof (followed by expression) */
/* STRUCTOP_... operate on a value from a following subexpression
by extracting a structure component specified by a string
that appears in the following exp_elements (as many as needed).
STRUCTOP_STRUCT is used for "." and STRUCTOP_PTR for "->".
They differ only in the error message given in case the value is
not suitable or the structure component specified is not found.
The length of the string follows in the next exp_element,
(after the string), followed by another STRUCTOP_... code. */
STRUCTOP_STRUCT,
STRUCTOP_PTR,
/* C++ */
/* OP_THIS is just a placeholder for the class instance variable.
It just comes in a tight (OP_THIS, OP_THIS) pair. */
OP_THIS,
/* OP_SCOPE surrounds a type name and a field name. The type
name is encoded as one element, but the field name stays as
a string, which, of course, is variable length. */
OP_SCOPE,
};
union exp_element
{
enum exp_opcode opcode;
struct symbol *symbol;
LONGEST longconst;
double doubleconst;
char string;
struct type *type;
struct internalvar *internalvar;
};
struct expression
{
int nelts;
union exp_element elts[1];
};
struct expression *parse_c_expression ();
struct expression *parse_c_1 ();

579
gnu/usr.bin/gdb/findvar.c Normal file
View file

@ -0,0 +1,579 @@
/* Find a variable's value in memory, for GDB, the GNU debugger.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "param.h"
#include "symtab.h"
#include "frame.h"
#include "value.h"
CORE_ADDR read_register ();
/* Return the address in which frame FRAME's value of register REGNUM
has been saved in memory. Or return zero if it has not been saved.
If REGNUM specifies the SP, the value we return is actually
the SP value, not an address where it was saved. */
CORE_ADDR
find_saved_register (frame, regnum)
FRAME frame;
int regnum;
{
struct frame_info *fi;
struct frame_saved_regs saved_regs;
register FRAME frame1 = 0;
register CORE_ADDR addr = 0;
#ifdef HAVE_REGISTER_WINDOWS
/* We assume that a register in a register window will only be saved
in one place (since the name changes and disappears as you go
towards inner frames), so we only call get_frame_saved_regs on
the current frame. This is directly in contradiction to the
usage below, which assumes that registers used in a frame must be
saved in a lower (more interior) frame. This change is a result
of working on a register window machine; get_frame_saved_regs
always returns the registers saved within a frame, within the
context (register namespace) of that frame. */
/* However, note that we don't want this to return anything if
nothing is saved (if there's a frame inside of this one). Also,
callers to this routine asking for the stack pointer want the
stack pointer saved for *this* frame; this is returned from the
next frame. */
if (REGISTER_IN_WINDOW_P(regnum))
{
frame1 = get_next_frame (frame);
if (!frame1) return 0; /* Registers of this frame are
active. */
/* Get the SP from the next frame in; it will be this
current frame. */
if (regnum != SP_REGNUM)
frame1 = frame;
fi = get_frame_info (frame1);
get_frame_saved_regs (fi, &saved_regs);
return (saved_regs.regs[regnum] ?
saved_regs.regs[regnum] : 0);
}
#endif /* HAVE_REGISTER_WINDOWS */
/* Note that this next routine assumes that registers used in
frame x will be saved only in the frame that x calls and
frames interior to it. This is not true on the sparc, but the
above macro takes care of it, so we should be all right. */
while (1)
{
QUIT;
frame1 = get_prev_frame (frame1);
if (frame1 == 0 || frame1 == frame)
break;
fi = get_frame_info (frame1);
get_frame_saved_regs (fi, &saved_regs);
if (saved_regs.regs[regnum])
addr = saved_regs.regs[regnum];
}
return addr;
}
/* Copy the bytes of register REGNUM, relative to the current stack frame,
into our memory at MYADDR.
The number of bytes copied is REGISTER_RAW_SIZE (REGNUM). */
void
read_relative_register_raw_bytes (regnum, myaddr)
int regnum;
char *myaddr;
{
register CORE_ADDR addr;
if (regnum == FP_REGNUM)
{
bcopy (&FRAME_FP(selected_frame), myaddr, sizeof (CORE_ADDR));
return;
}
addr = find_saved_register (selected_frame, regnum);
if (addr)
{
if (regnum == SP_REGNUM)
{
CORE_ADDR buffer = addr;
bcopy (&buffer, myaddr, sizeof (CORE_ADDR));
}
else
read_memory (addr, myaddr, REGISTER_RAW_SIZE (regnum));
return;
}
read_register_bytes (REGISTER_BYTE (regnum),
myaddr, REGISTER_RAW_SIZE (regnum));
}
/* Return a `value' with the contents of register REGNUM
in its virtual format, with the type specified by
REGISTER_VIRTUAL_TYPE. */
value
value_of_register (regnum)
int regnum;
{
register CORE_ADDR addr;
register value val;
char raw_buffer[MAX_REGISTER_RAW_SIZE];
char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
if (! (have_inferior_p () || have_core_file_p ()))
error ("Can't get value of register without inferior or core file");
addr = find_saved_register (selected_frame, regnum);
if (addr)
{
if (regnum == SP_REGNUM)
return value_from_long (builtin_type_int, (LONGEST) addr);
read_memory (addr, raw_buffer, REGISTER_RAW_SIZE (regnum));
}
else
read_register_bytes (REGISTER_BYTE (regnum), raw_buffer,
REGISTER_RAW_SIZE (regnum));
REGISTER_CONVERT_TO_VIRTUAL (regnum, raw_buffer, virtual_buffer);
val = allocate_value (REGISTER_VIRTUAL_TYPE (regnum));
bcopy (virtual_buffer, VALUE_CONTENTS (val), REGISTER_VIRTUAL_SIZE (regnum));
VALUE_LVAL (val) = addr ? lval_memory : lval_register;
VALUE_ADDRESS (val) = addr ? addr : REGISTER_BYTE (regnum);
VALUE_REGNO (val) = regnum;
return val;
}
/* Low level examining and depositing of registers.
Note that you must call `fetch_registers' once
before examining or depositing any registers. */
char registers[REGISTER_BYTES];
/* Copy LEN bytes of consecutive data from registers
starting with the REGBYTE'th byte of register data
into memory at MYADDR. */
void
read_register_bytes (regbyte, myaddr, len)
int regbyte;
char *myaddr;
int len;
{
bcopy (&registers[regbyte], myaddr, len);
}
/* Copy LEN bytes of consecutive data from memory at MYADDR
into registers starting with the REGBYTE'th byte of register data. */
void
write_register_bytes (regbyte, myaddr, len)
int regbyte;
char *myaddr;
int len;
{
bcopy (myaddr, &registers[regbyte], len);
if (have_inferior_p ())
store_inferior_registers (-1);
}
/* Return the contents of register REGNO,
regarding it as an integer. */
CORE_ADDR
read_register (regno)
int regno;
{
/* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
return *(int *) &registers[REGISTER_BYTE (regno)];
}
/* Store VALUE in the register number REGNO, regarded as an integer. */
void
write_register (regno, val)
int regno, val;
{
/* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
#if defined(sun4)
/* This is a no-op on a Sun 4. */
if (regno == 0)
return;
#endif
*(int *) &registers[REGISTER_BYTE (regno)] = val;
if (have_inferior_p ())
store_inferior_registers (regno);
}
/* Record that register REGNO contains VAL.
This is used when the value is obtained from the inferior or core dump,
so there is no need to store the value there. */
void
supply_register (regno, val)
int regno;
char *val;
{
bcopy (val, &registers[REGISTER_BYTE (regno)], REGISTER_RAW_SIZE (regno));
}
/* Given a struct symbol for a variable,
and a stack frame id, read the value of the variable
and return a (pointer to a) struct value containing the value. */
value
read_var_value (var, frame)
register struct symbol *var;
FRAME frame;
{
register value v;
struct frame_info *fi;
struct type *type = SYMBOL_TYPE (var);
register CORE_ADDR addr = 0;
int val = SYMBOL_VALUE (var);
register int len;
v = allocate_value (type);
VALUE_LVAL (v) = lval_memory; /* The most likely possibility. */
len = TYPE_LENGTH (type);
if (frame == 0) frame = selected_frame;
switch (SYMBOL_CLASS (var))
{
case LOC_CONST:
case LOC_LABEL:
bcopy (&val, VALUE_CONTENTS (v), len);
VALUE_LVAL (v) = not_lval;
return v;
case LOC_CONST_BYTES:
bcopy (val, VALUE_CONTENTS (v), len);
VALUE_LVAL (v) = not_lval;
return v;
case LOC_STATIC:
addr = val;
break;
/* Nonzero if a struct which is located in a register or a LOC_ARG
really contains
the address of the struct, not the struct itself. GCC_P is nonzero
if the function was compiled with GCC. */
#if !defined (REG_STRUCT_HAS_ADDR)
#define REG_STRUCT_HAS_ADDR(gcc_p) 0
#endif
case LOC_ARG:
fi = get_frame_info (frame);
addr = val + FRAME_ARGS_ADDRESS (fi);
break;
case LOC_REF_ARG:
fi = get_frame_info (frame);
addr = val + FRAME_ARGS_ADDRESS (fi);
addr = read_memory_integer (addr, sizeof (CORE_ADDR));
break;
case LOC_LOCAL:
fi = get_frame_info (frame);
addr = val + FRAME_LOCALS_ADDRESS (fi);
break;
case LOC_TYPEDEF:
error ("Cannot look up value of a typedef");
case LOC_BLOCK:
VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
return v;
case LOC_REGISTER:
case LOC_REGPARM:
{
struct block *b = get_frame_block (frame);
v = value_from_register (type, val, frame);
if (REG_STRUCT_HAS_ADDR(b->gcc_compile_flag)
&& TYPE_CODE (type) == TYPE_CODE_STRUCT)
addr = *(CORE_ADDR *)VALUE_CONTENTS (v);
else
return v;
}
}
read_memory (addr, VALUE_CONTENTS (v), len);
VALUE_ADDRESS (v) = addr;
return v;
}
/* Return a value of type TYPE, stored in register REGNUM, in frame
FRAME. */
value
value_from_register (type, regnum, frame)
struct type *type;
int regnum;
FRAME frame;
{
char raw_buffer [MAX_REGISTER_RAW_SIZE];
char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
CORE_ADDR addr;
value v = allocate_value (type);
int len = TYPE_LENGTH (type);
char *value_bytes = 0;
int value_bytes_copied = 0;
int num_storage_locs;
VALUE_REGNO (v) = regnum;
num_storage_locs = (len > REGISTER_VIRTUAL_SIZE (regnum) ?
((len - 1) / REGISTER_RAW_SIZE (regnum)) + 1 :
1);
if (num_storage_locs > 1)
{
/* Value spread across multiple storage locations. */
int local_regnum;
int mem_stor = 0, reg_stor = 0;
int mem_tracking = 1;
CORE_ADDR last_addr = 0;
value_bytes = (char *) alloca (len + MAX_REGISTER_RAW_SIZE);
/* Copy all of the data out, whereever it may be. */
for (local_regnum = regnum;
value_bytes_copied < len;
(value_bytes_copied += REGISTER_RAW_SIZE (local_regnum),
++local_regnum))
{
int register_index = local_regnum - regnum;
addr = find_saved_register (frame, local_regnum);
if (addr == 0)
{
read_register_bytes (REGISTER_BYTE (local_regnum),
value_bytes + value_bytes_copied,
REGISTER_RAW_SIZE (local_regnum));
reg_stor++;
}
else
{
read_memory (addr, value_bytes + value_bytes_copied,
REGISTER_RAW_SIZE (local_regnum));
mem_stor++;
mem_tracking =
(mem_tracking
&& (regnum == local_regnum
|| addr == last_addr));
}
last_addr = addr;
}
if ((reg_stor && mem_stor)
|| (mem_stor && !mem_tracking))
/* Mixed storage; all of the hassle we just went through was
for some good purpose. */
{
VALUE_LVAL (v) = lval_reg_frame_relative;
VALUE_FRAME (v) = FRAME_FP (frame);
VALUE_FRAME_REGNUM (v) = regnum;
}
else if (mem_stor)
{
VALUE_LVAL (v) = lval_memory;
VALUE_ADDRESS (v) = find_saved_register (frame, regnum);
}
else if (reg_stor)
{
VALUE_LVAL (v) = lval_register;
VALUE_ADDRESS (v) = REGISTER_BYTE (regnum);
}
else
fatal ("value_from_register: Value not stored anywhere!");
/* Any structure stored in more than one register will always be
an inegral number of registers. Otherwise, you'd need to do
some fiddling with the last register copied here for little
endian machines. */
/* Copy into the contents section of the value. */
bcopy (value_bytes, VALUE_CONTENTS (v), len);
return v;
}
/* Data is completely contained within a single register. Locate the
register's contents in a real register or in core;
read the data in raw format. */
addr = find_saved_register (frame, regnum);
if (addr == 0)
{
/* Value is really in a register. */
VALUE_LVAL (v) = lval_register;
VALUE_ADDRESS (v) = REGISTER_BYTE (regnum);
read_register_bytes (REGISTER_BYTE (regnum),
raw_buffer, REGISTER_RAW_SIZE (regnum));
}
else
{
/* Value was in a register that has been saved in memory. */
read_memory (addr, raw_buffer, REGISTER_RAW_SIZE (regnum));
VALUE_LVAL (v) = lval_memory;
VALUE_ADDRESS (v) = addr;
}
/* Convert the raw contents to virtual contents.
(Just copy them if the formats are the same.) */
REGISTER_CONVERT_TO_VIRTUAL (regnum, raw_buffer, virtual_buffer);
if (REGISTER_CONVERTIBLE (regnum))
{
/* When the raw and virtual formats differ, the virtual format
corresponds to a specific data type. If we want that type,
copy the data into the value.
Otherwise, do a type-conversion. */
if (type != REGISTER_VIRTUAL_TYPE (regnum))
{
/* eg a variable of type `float' in a 68881 register
with raw type `extended' and virtual type `double'.
Fetch it as a `double' and then convert to `float'. */
v = allocate_value (REGISTER_VIRTUAL_TYPE (regnum));
bcopy (virtual_buffer, VALUE_CONTENTS (v), len);
v = value_cast (type, v);
}
else
bcopy (virtual_buffer, VALUE_CONTENTS (v), len);
}
else
{
/* Raw and virtual formats are the same for this register. */
#ifdef BYTES_BIG_ENDIAN
if (len < REGISTER_RAW_SIZE (regnum))
{
/* Big-endian, and we want less than full size. */
VALUE_OFFSET (v) = REGISTER_RAW_SIZE (regnum) - len;
}
#endif
bcopy (virtual_buffer + VALUE_OFFSET (v),
VALUE_CONTENTS (v), len);
}
return v;
}
/* Given a struct symbol for a variable,
and a stack frame id,
return a (pointer to a) struct value containing the variable's address. */
value
locate_var_value (var, frame)
register struct symbol *var;
FRAME frame;
{
register CORE_ADDR addr = 0;
int val = SYMBOL_VALUE (var);
struct frame_info *fi;
struct type *type = SYMBOL_TYPE (var);
struct type *result_type;
if (frame == 0) frame = selected_frame;
switch (SYMBOL_CLASS (var))
{
case LOC_CONST:
case LOC_CONST_BYTES:
error ("Address requested for identifier \"%s\" which is a constant.",
SYMBOL_NAME (var));
case LOC_REGISTER:
case LOC_REGPARM:
addr = find_saved_register (frame, val);
if (addr != 0)
{
int len = TYPE_LENGTH (type);
#ifdef BYTES_BIG_ENDIAN
if (len < REGISTER_RAW_SIZE (val))
/* Big-endian, and we want less than full size. */
addr += REGISTER_RAW_SIZE (val) - len;
#endif
break;
}
error ("Address requested for identifier \"%s\" which is in a register.",
SYMBOL_NAME (var));
case LOC_STATIC:
case LOC_LABEL:
addr = val;
break;
case LOC_ARG:
fi = get_frame_info (frame);
addr = val + FRAME_ARGS_ADDRESS (fi);
break;
case LOC_REF_ARG:
fi = get_frame_info (frame);
addr = val + FRAME_ARGS_ADDRESS (fi);
addr = read_memory_integer (addr, sizeof (CORE_ADDR));
break;
case LOC_LOCAL:
fi = get_frame_info (frame);
addr = val + FRAME_LOCALS_ADDRESS (fi);
break;
case LOC_TYPEDEF:
error ("Address requested for identifier \"%s\" which is a typedef.",
SYMBOL_NAME (var));
case LOC_BLOCK:
addr = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
break;
}
/* Address of an array is of the type of address of it's elements. */
result_type =
lookup_pointer_type (TYPE_CODE (type) == TYPE_CODE_ARRAY ?
TYPE_TARGET_TYPE (type) : type);
return value_cast (result_type,
value_from_long (builtin_type_long, (LONGEST) addr));
}

115
gnu/usr.bin/gdb/frame.h Normal file
View file

@ -0,0 +1,115 @@
/* Definitions for dealing with stack frames, for GDB, the GNU debugger.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Note that frame.h requires param.h! */
/*
* FRAME is the type of the identifier of a specific stack frame. It
* is a pointer to the frame cache item corresponding to this frame.
* Please note that frame id's are *not* constant over calls to the
* inferior. Use frame addresses, which are.
*
* FRAME_ADDR is the type of the address of a specific frame. I
* cannot imagine a case in which this would not be CORE_ADDR, so
* maybe it's silly to give it it's own type. Life's rough.
*
* FRAME_FP is a macro which converts from a frame identifier into a
* frame_address.
*
* FRAME_INFO_ID is a macro which "converts" from a frame info pointer
* to a frame id. This is here in case I or someone else decides to
* change the FRAME type again.
*
* This file and blockframe.c are the only places which are allowed to
* use the equivalence between FRAME and struct frame_info *. EXCEPTION:
* value.h uses CORE_ADDR instead of FRAME_ADDR because the compiler
* will accept that in the absense of this file.
*/
typedef struct frame_info *FRAME;
typedef CORE_ADDR FRAME_ADDR;
#define FRAME_FP(fr) ((fr)->frame)
#define FRAME_INFO_ID(f) (f)
/*
* Caching structure for stack frames. This is also the structure
* used for extended info about stack frames. May add more to this
* structure as it becomes necessary.
*
* Note that the first entry in the cache will always refer to the
* innermost executing frame. This value should be set (is it?
* Check) in something like normal_stop.
*/
struct frame_info
{
/* Nominal address of the frame described. */
FRAME_ADDR frame;
/* Address at which execution is occurring in this frame.
For the innermost frame, it's the current pc.
For other frames, it is a pc saved in the next frame. */
CORE_ADDR pc;
/* The frame called by the frame we are describing, or 0.
This may be set even if there isn't a frame called by the one
we are describing (.->next == 0); in that case it is simply the
bottom of this frame */
FRAME_ADDR next_frame;
/* Anything extra for this structure that may have been defined
in the machine depedent files. */
#ifdef EXTRA_FRAME_INFO
EXTRA_FRAME_INFO
#endif
/* Pointers to the next and previous frame_info's in this stack. */
FRAME next, prev;
};
/* Describe the saved registers of a frame. */
struct frame_saved_regs
{
/* For each register, address of where it was saved on entry to the frame,
or zero if it was not saved on entry to this frame. */
CORE_ADDR regs[NUM_REGS];
};
/* The stack frame that the user has specified for commands to act on.
Note that one cannot assume this is the address of valid data. */
extern FRAME selected_frame;
extern struct frame_info *get_frame_info ();
extern struct frame_info *get_prev_frame_info ();
extern FRAME create_new_frame ();
extern void get_frame_saved_regs ();
extern FRAME get_prev_frame ();
extern FRAME get_current_frame ();
extern FRAME get_next_frame ();
extern struct block *get_frame_block ();
extern struct block *get_current_block ();
extern struct block *get_selected_block ();
extern struct symbol *get_frame_function ();
extern struct symbol *get_pc_function ();
/* In stack.c */
extern FRAME find_relative_frame ();
/* Generic pointer value indicating "I don't know." */
#define Frame_unknown (CORE_ADDR)-1

3
gnu/usr.bin/gdb/gdb.1 Normal file
View file

@ -0,0 +1,3 @@
.\" %W% (Berkeley) %G%
.\"
.\" placeholder, until we can produce the manual page

View file

@ -0,0 +1,25 @@
#ifdef BSD
#ifndef BSD4_1
#define HAVE_GETPAGESIZE
#endif
#endif
#ifndef HAVE_GETPAGESIZE
#include <sys/param.h>
#ifdef EXEC_PAGESIZE
#define getpagesize() EXEC_PAGESIZE
#else
#ifdef NBPG
#define getpagesize() NBPG * CLSIZE
#ifndef CLSIZE
#define CLSIZE 1
#endif /* no CLSIZE */
#else /* no NBPG */
#define getpagesize() NBPC
#endif /* no NBPG */
#endif /* no EXEC_PAGESIZE */
#endif /* not HAVE_GETPAGESIZE */

1204
gnu/usr.bin/gdb/infcmd.c Normal file

File diff suppressed because it is too large Load diff

142
gnu/usr.bin/gdb/inferior.h Normal file
View file

@ -0,0 +1,142 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
* Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
*
* @(#)inferior.h 6.3 (Berkeley) 5/8/91
*/
/* Variables that describe the inferior process running under GDB:
Where it is, why it stopped, and how to step it.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* Structure in which to save the status of the inferior. Save
* through "save_inferior_status", restore through
* "restore_inferior_status".
* This pair of routines should be called around any transfer of
* control to the inferior which you don't want showing up in your
* control variables.
*/
struct inferior_status {
int pc_changed;
int stop_signal;
int stop_pc;
int stop_frame_address;
int stop_breakpoint;
int stop_step;
int stop_stack_dummy;
int stopped_by_random_signal;
int trap_expected;
CORE_ADDR step_range_start;
CORE_ADDR step_range_end;
FRAME_ADDR step_frame_address;
int step_over_calls;
CORE_ADDR step_resume_break_address;
int stop_after_trap;
int stop_after_attach;
FRAME_ADDR selected_frame_address;
int selected_level;
struct command_line *breakpoint_commands;
char register_context[REGISTER_BYTES];
int restore_stack_info;
};
void save_inferior_status (), restore_inferior_status ();
/* File name for default use for standard in/out in the inferior. */
extern char *inferior_io_terminal;
/* Pid of our debugged inferior, or 0 if no inferior now. */
extern int inferior_pid;
/* Nonzero if debugging a remote machine via a serial link or ethernet. */
extern int remote_debugging;
/* Routines for use in remote debugging. Documented in remote.c. */
int remote_read_inferior_memory ();
int remote_write_inferior_memory ();
/* Last signal that the inferior received (why it stopped). */
extern int stop_signal;
/* Address at which inferior stopped. */
extern CORE_ADDR stop_pc;
/* Stack frame when program stopped. */
extern FRAME_ADDR stop_frame_address;
/* Number of breakpoint it stopped at, or 0 if none. */
extern int stop_breakpoint;
/* Nonzero if stopped due to a step command. */
extern int stop_step;
/* Nonzero if stopped due to completion of a stack dummy routine. */
extern int stop_stack_dummy;
/* Nonzero if program stopped due to a random (unexpected) signal in
inferior process. */
extern int stopped_by_random_signal;
/* Range to single step within.
If this is nonzero, respond to a single-step signal
by continuing to step if the pc is in this range. */
extern CORE_ADDR step_range_start; /* Inclusive */
extern CORE_ADDR step_range_end; /* Exclusive */
/* Stack frame address as of when stepping command was issued.
This is how we know when we step into a subroutine call,
and how to set the frame for the breakpoint used to step out. */
extern FRAME_ADDR step_frame_address;
/* 1 means step over all subroutine calls.
-1 means step over calls to undebuggable functions. */
extern int step_over_calls;
/* If stepping, nonzero means step count is > 1
so don't print frame next time inferior stops
if it stops due to stepping. */
extern int step_multi;
/* Save register contents here when about to pop a stack dummy frame. */
extern char stop_registers[REGISTER_BYTES];
/* Nonzero if pc has been changed by the debugger
since the inferior stopped. */
extern int pc_changed;
long read_memory_integer ();

569
gnu/usr.bin/gdb/inflow.c Normal file
View file

@ -0,0 +1,569 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
* Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
*/
#ifndef lint
static char sccsid[] = "@(#)inflow.c 6.5 (Berkeley) 5/8/91";
#endif /* not lint */
/* Low level interface to ptrace, for GDB when running under Unix.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "defs.h"
#include "param.h"
#include "frame.h"
#include "inferior.h"
#ifdef USG
#include <sys/types.h>
#endif
/* Some USG-esque systems (some of which are BSD-esque enough so that USG
is not defined) want this header, and it won't do any harm. */
#include <fcntl.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#ifdef HAVE_TERMIO
#include <termio.h>
#undef TIOCGETP
#define TIOCGETP TCGETA
#undef TIOCSETN
#define TIOCSETN TCSETA
#undef TIOCSETP
#define TIOCSETP TCSETAF
#define TERMINAL struct termio
#else
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sgtty.h>
#define TERMINAL struct sgttyb
#endif
#ifdef SET_STACK_LIMIT_HUGE
#include <sys/time.h>
#include <sys/resource.h>
extern int original_stack_limit;
#endif /* SET_STACK_LIMIT_HUGE */
extern int errno;
/* Nonzero if we are debugging an attached outside process
rather than an inferior. */
int attach_flag;
/* Record terminal status separately for debugger and inferior. */
static TERMINAL sg_inferior;
static TERMINAL sg_ours;
static int tflags_inferior;
static int tflags_ours;
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
static struct tchars tc_inferior;
static struct tchars tc_ours;
#endif
#ifdef TIOCGLTC
static struct ltchars ltc_inferior;
static struct ltchars ltc_ours;
#endif
#ifdef TIOCLGET
static int lmode_inferior;
static int lmode_ours;
#endif
#ifdef TIOCGPGRP
static int pgrp_inferior;
static int pgrp_ours;
#else
static int (*sigint_ours) ();
static int (*sigquit_ours) ();
#endif /* TIOCGPGRP */
/* Copy of inferior_io_terminal when inferior was last started. */
static char *inferior_thisrun_terminal;
static void terminal_ours_1 ();
/* Nonzero if our terminal settings are in effect.
Zero if the inferior's settings are in effect. */
static int terminal_is_ours;
/* Initialize the terminal settings we record for the inferior,
before we actually run the inferior. */
void
terminal_init_inferior ()
{
if (remote_debugging)
return;
sg_inferior = sg_ours;
tflags_inferior = tflags_ours;
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
tc_inferior = tc_ours;
#endif
#ifdef TIOCGLTC
ltc_inferior = ltc_ours;
#endif
#ifdef TIOCLGET
lmode_inferior = lmode_ours;
#endif
#ifdef TIOCGPGRP
pgrp_inferior = inferior_pid;
#endif /* TIOCGPGRP */
terminal_is_ours = 1;
}
/* Put the inferior's terminal settings into effect.
This is preparation for starting or resuming the inferior. */
void
terminal_inferior ()
{
if (remote_debugging)
return;
if (terminal_is_ours) /* && inferior_thisrun_terminal == 0) */
{
fcntl (0, F_SETFL, tflags_inferior);
fcntl (0, F_SETFL, tflags_inferior);
ioctl (0, TIOCSETN, &sg_inferior);
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
ioctl (0, TIOCSETC, &tc_inferior);
#endif
#ifdef TIOCGLTC
ioctl (0, TIOCSLTC, &ltc_inferior);
#endif
#ifdef TIOCLGET
ioctl (0, TIOCLSET, &lmode_inferior);
#endif
#ifdef TIOCGPGRP
ioctl (0, TIOCSPGRP, &pgrp_inferior);
#else
sigint_ours = (int (*) ()) signal (SIGINT, SIG_IGN);
sigquit_ours = (int (*) ()) signal (SIGQUIT, SIG_IGN);
#endif /* TIOCGPGRP */
}
terminal_is_ours = 0;
}
/* Put some of our terminal settings into effect,
enough to get proper results from our output,
but do not change into or out of RAW mode
so that no input is discarded.
After doing this, either terminal_ours or terminal_inferior
should be called to get back to a normal state of affairs. */
void
terminal_ours_for_output ()
{
if (remote_debugging)
return;
terminal_ours_1 (1);
}
/* Put our terminal settings into effect.
First record the inferior's terminal settings
so they can be restored properly later. */
void
terminal_ours ()
{
if (remote_debugging)
return;
terminal_ours_1 (0);
}
static void
terminal_ours_1 (output_only)
int output_only;
{
#ifdef TIOCGPGRP
/* Ignore this signal since it will happen when we try to set the pgrp. */
void (*osigttou) ();
#endif /* TIOCGPGRP */
if (!terminal_is_ours) /* && inferior_thisrun_terminal == 0) */
{
terminal_is_ours = 1;
#ifdef TIOCGPGRP
osigttou = signal (SIGTTOU, SIG_IGN);
ioctl (0, TIOCGPGRP, &pgrp_inferior);
ioctl (0, TIOCSPGRP, &pgrp_ours);
signal (SIGTTOU, osigttou);
#else
signal (SIGINT, sigint_ours);
signal (SIGQUIT, sigquit_ours);
#endif /* TIOCGPGRP */
tflags_inferior = fcntl (0, F_GETFL, 0);
ioctl (0, TIOCGETP, &sg_inferior);
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
ioctl (0, TIOCGETC, &tc_inferior);
#endif
#ifdef TIOCGLTC
ioctl (0, TIOCGLTC, &ltc_inferior);
#endif
#ifdef TIOCLGET
ioctl (0, TIOCLGET, &lmode_inferior);
#endif
}
#ifdef HAVE_TERMIO
sg_ours.c_lflag |= ICANON;
if (output_only && !(sg_inferior.c_lflag & ICANON))
sg_ours.c_lflag &= ~ICANON;
#else /* not HAVE_TERMIO */
sg_ours.sg_flags &= ~RAW & ~CBREAK;
if (output_only)
sg_ours.sg_flags |= (RAW | CBREAK) & sg_inferior.sg_flags;
#endif /* not HAVE_TERMIO */
fcntl (0, F_SETFL, tflags_ours);
fcntl (0, F_SETFL, tflags_ours);
ioctl (0, TIOCSETN, &sg_ours);
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
ioctl (0, TIOCSETC, &tc_ours);
#endif
#ifdef TIOCGLTC
ioctl (0, TIOCSLTC, &ltc_ours);
#endif
#ifdef TIOCLGET
ioctl (0, TIOCLSET, &lmode_ours);
#endif
#ifdef HAVE_TERMIO
sg_ours.c_lflag |= ICANON;
#else /* not HAVE_TERMIO */
sg_ours.sg_flags &= ~RAW & ~CBREAK;
#endif /* not HAVE_TERMIO */
}
static void
term_status_command ()
{
register int i;
if (remote_debugging)
{
printf_filtered ("No terminal status when remote debugging.\n");
return;
}
printf_filtered ("Inferior's terminal status (currently saved by GDB):\n");
#ifdef HAVE_TERMIO
printf_filtered ("fcntl flags = 0x%x, c_iflag = 0x%x, c_oflag = 0x%x,\n",
tflags_inferior, sg_inferior.c_iflag, sg_inferior.c_oflag);
printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n",
sg_inferior.c_cflag, sg_inferior.c_lflag, sg_inferior.c_line);
printf_filtered ("c_cc: ");
for (i = 0; (i < NCC); i += 1)
printf_filtered ("0x%x ", sg_inferior.c_cc[i]);
printf_filtered ("\n");
#else /* not HAVE_TERMIO */
printf_filtered ("fcntl flags = 0x%x, sgttyb.sg_flags = 0x%x, owner pid = %d.\n",
tflags_inferior, sg_inferior.sg_flags, pgrp_inferior);
#endif /* not HAVE_TERMIO */
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
printf_filtered ("tchars: ");
for (i = 0; i < sizeof (struct tchars); i++)
printf_filtered ("0x%x ", ((char *)&tc_inferior)[i]);
printf_filtered ("\n");
#endif
#ifdef TIOCGLTC
printf_filtered ("ltchars: ");
for (i = 0; i < sizeof (struct ltchars); i++)
printf_filtered ("0x%x ", ((char *)&ltc_inferior)[i]);
printf_filtered ("\n");
ioctl (0, TIOCSLTC, &ltc_ours);
#endif
#ifdef TIOCLGET
printf_filtered ("lmode: %x\n", lmode_inferior);
#endif
}
static void
new_tty (ttyname)
char *ttyname;
{
register int tty;
register int fd;
#ifdef TIOCNOTTY
/* Disconnect the child process from our controlling terminal. */
tty = open("/dev/tty", O_RDWR);
if (tty > 0)
{
ioctl(tty, TIOCNOTTY, 0);
close(tty);
}
#endif
/* Now open the specified new terminal. */
tty = open(ttyname, O_RDWR);
if (tty == -1)
_exit(1);
/* Avoid use of dup2; doesn't exist on all systems. */
if (tty != 0)
{ close (0); dup (tty); }
if (tty != 1)
{ close (1); dup (tty); }
if (tty != 2)
{ close (2); dup (tty); }
if (tty > 2)
close(tty);
}
/* Start an inferior process and returns its pid.
ALLARGS is a string containing shell command to run the program.
ENV is the environment vector to pass. */
#ifndef SHELL_FILE
#define SHELL_FILE "/bin/sh"
#endif
int
create_inferior (allargs, env)
char *allargs;
char **env;
{
int pid;
char *shell_command;
extern int sys_nerr;
extern char *sys_errlist[];
extern int errno;
/* If desired, concat something onto the front of ALLARGS.
SHELL_COMMAND is the result. */
#ifdef SHELL_COMMAND_CONCAT
shell_command = (char *) alloca (strlen (SHELL_COMMAND_CONCAT) + strlen (allargs) + 1);
strcpy (shell_command, SHELL_COMMAND_CONCAT);
strcat (shell_command, allargs);
#else
shell_command = allargs;
#endif
/* exec is said to fail if the executable is open. */
close_exec_file ();
#if defined(USG) && !defined(HAVE_VFORK)
pid = fork ();
#else
pid = vfork ();
#endif
if (pid < 0)
perror_with_name ("vfork");
if (pid == 0)
{
#ifdef TIOCGPGRP
/* Run inferior in a separate process group. */
setpgrp (getpid (), getpid ());
#endif /* TIOCGPGRP */
#ifdef SET_STACK_LIMIT_HUGE
/* Reset the stack limit back to what it was. */
{
struct rlimit rlim;
getrlimit (RLIMIT_STACK, &rlim);
rlim.rlim_cur = original_stack_limit;
setrlimit (RLIMIT_STACK, &rlim);
}
#endif /* SET_STACK_LIMIT_HUGE */
inferior_thisrun_terminal = inferior_io_terminal;
if (inferior_io_terminal != 0)
new_tty (inferior_io_terminal);
/* It seems that changing the signal handlers for the inferior after
a vfork also changes them for the superior. See comments in
initialize_signals for how we get the right signal handlers
for the inferior. */
/* Not needed on Sun, at least, and loses there
because it clobbers the superior. */
/*??? signal (SIGQUIT, SIG_DFL);
signal (SIGINT, SIG_DFL); */
call_ptrace (0);
execle (SHELL_FILE, "sh", "-c", shell_command, 0, env);
fprintf (stderr, "Cannot exec %s: %s.\n", SHELL_FILE,
errno < sys_nerr ? sys_errlist[errno] : "unknown error");
fflush (stderr);
_exit (0177);
}
#ifdef TIOCGPGRP
/* Avoid race with TIOCSPGRP: guarantee that inferior's pgrp exists. */
setpgrp (pid, pid);
#endif /* TIOCGPGRP */
#ifdef CREATE_INFERIOR_HOOK
CREATE_INFERIOR_HOOK (pid);
#endif
return pid;
}
/* Kill the inferior process. Make us have no inferior. */
static void
kill_command ()
{
if (remote_debugging)
{
inferior_pid = 0;
return;
}
if (inferior_pid == 0)
error ("The program is not being run.");
if (!query ("Kill the inferior process? "))
error ("Not confirmed.");
kill_inferior ();
}
void
inferior_died ()
{
inferior_pid = 0;
attach_flag = 0;
mark_breakpoints_out ();
select_frame ((FRAME) 0, -1);
reopen_exec_file ();
if (have_core_file_p ())
set_current_frame ( create_new_frame (read_register (FP_REGNUM),
read_pc ()));
else
set_current_frame (0);
}
#if 0
/* This function is just for testing, and on some systems (Sony NewsOS
3.2) <sys/user.h> also includes <sys/time.h> which leads to errors
(since on this system at least sys/time.h is not protected against
multiple inclusion). */
static void
try_writing_regs_command ()
{
register int i;
register int value;
extern int errno;
if (inferior_pid == 0)
error ("There is no inferior process now.");
/* A Sun 3/50 or 3/60 (at least) running SunOS 4.0.3 will have a
kernel panic if we try to write past the end of the user area.
Presumably Sun will fix this bug (it has been reported), but it
is tacky to crash the system, so at least on SunOS4 we need to
stop writing when we hit the end of the user area. */
for (i = 0; i < sizeof (struct user); i += 2)
{
QUIT;
errno = 0;
value = call_ptrace (3, inferior_pid, i, 0);
call_ptrace (6, inferior_pid, i, value);
if (errno == 0)
{
printf (" Succeeded with address 0x%x; value 0x%x (%d).\n",
i, value, value);
}
else if ((i & 0377) == 0)
printf (" Failed at 0x%x.\n", i);
}
}
#endif
void
_initialize_inflow ()
{
add_com ("term-status", class_obscure, term_status_command,
"Print info on inferior's saved terminal status.");
#if 0
add_com ("try-writing-regs", class_obscure, try_writing_regs_command,
"Try writing all locations in inferior's system block.\n\
Report which ones can be written.");
#endif
add_com ("kill", class_run, kill_command,
"Kill execution of program being debugged.");
inferior_pid = 0;
ioctl (0, TIOCGETP, &sg_ours);
tflags_ours = fcntl (0, F_GETFL, 0);
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
ioctl (0, TIOCGETC, &tc_ours);
#endif
#ifdef TIOCGLTC
ioctl (0, TIOCGLTC, &ltc_ours);
#endif
#ifdef TIOCLGET
ioctl (0, TIOCLGET, &lmode_ours);
#endif
#ifdef TIOCGPGRP
ioctl (0, TIOCGPGRP, &pgrp_ours);
#endif /* TIOCGPGRP */
terminal_is_ours = 1;
}

1459
gnu/usr.bin/gdb/infrun.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,63 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Steven McCanne of Lawrence Berkeley Laboratory.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)kgdb_proto.h 6.3 (Berkeley) 5/8/91
*
*
* $Header: /home/cvs/386BSD/src/usr.bin/gdb/kgdb_proto.h,v 1.1.1.1 1993/06/12 14:52:25 rgrimes Exp $ (LBL)
*/
/*
* Message types.
*/
#define KGDB_MEM_R 0x01
#define KGDB_MEM_W 0x02
#define KGDB_REG_R 0x03
#define KGDB_REG_W 0x04
#define KGDB_CONT 0x05
#define KGDB_STEP 0x06
#define KGDB_KILL 0x07
#define KGDB_SIGNAL 0x08
#define KGDB_EXEC 0x09
#define KGDB_CMD(x) ((x) & 0x0f)
/*
* Message flags.
*/
#define KGDB_ACK 0x80
#define KGDB_DELTA 0x40
#define KGDB_MORE 0x20
#define KGDB_SEQ 0x10

2240
gnu/usr.bin/gdb/main.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,27 @@
# %W% (Berkeley) %G%
.include "../config/Makefile.$(MACHINE)"
PROG= ngdb
SRCS= i386bsd-dep.c blockframe.c
GDBOBJS+= i386-pinsn.o \
breakpoint.o command.o copying.o core.o \
cplus-dem.o dbxread.o environ.o eval.o expprint.o \
expread.o findvar.o infcmd.o inflow.o infrun.o \
main.o obstack.o printcmd.o regex.o remote.o \
remote-sl.o source.o stack.o symmisc.o symtab.o \
utils.o valarith.o valops.o valprint.o values.o \
version.o \
funmap.o history.o keymaps.o readline.o \
init.o
CFLAGS+= -g -I$(.CURDIR) -I.. -I$(.CURDIR)/.. -I$(.CURDIR)/../config \
-I/usr/src/sys.newvm \
-DNEWVM -DHAVE_VPRINTF -DVI_MODE -DKERNELDEBUG
# CC= /usr/old/bin/cc
# CC= cc -traditional
LDADD+= $(GDBOBJS:S/^/..\//g) -ltermcap
NOMAN= noman
.PATH: $(.CURDIR)/../config $(.CURDIR)/..
.include <bsd.prog.mk>

313
gnu/usr.bin/gdb/obstack.c Normal file
View file

@ -0,0 +1,313 @@
/* obstack.c - subroutines used implicitly by object stack macros
Copyright (C) 1988 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 1, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding! */
#include "obstack.h"
#ifdef __STDC__
#define POINTER void *
#else
#define POINTER char *
#endif
/* Determine default alignment. */
struct fooalign {char x; double d;};
#define DEFAULT_ALIGNMENT ((char *)&((struct fooalign *) 0)->d - (char *)0)
/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
But in fact it might be less smart and round addresses to as much as
DEFAULT_ROUNDING. So we prepare for it to do that. */
union fooround {long x; double d;};
#define DEFAULT_ROUNDING (sizeof (union fooround))
/* When we copy a long block of data, this is the unit to do it with.
On some machines, copying successive ints does not work;
in such a case, redefine COPYING_UNIT to `long' (if that works)
or `char' as a last resort. */
#ifndef COPYING_UNIT
#define COPYING_UNIT int
#endif
/* The non-GNU-C macros copy the obstack into this global variable
to avoid multiple evaluation. */
struct obstack *_obstack;
/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
Objects start on multiples of ALIGNMENT (0 means use default).
CHUNKFUN is the function to use to allocate chunks,
and FREEFUN the function to free them. */
void
_obstack_begin (h, size, alignment, chunkfun, freefun)
struct obstack *h;
int size;
int alignment;
POINTER (*chunkfun) ();
void (*freefun) ();
{
register struct _obstack_chunk* chunk; /* points to new chunk */
if (alignment == 0)
alignment = DEFAULT_ALIGNMENT;
if (size == 0)
/* Default size is what GNU malloc can fit in a 4096-byte block.
Pick a number small enough that when rounded up to DEFAULT_ROUNDING
it is still smaller than 4096 - 4. */
{
int extra = 4;
if (extra < DEFAULT_ROUNDING)
extra = DEFAULT_ROUNDING;
size = 4096 - extra;
}
h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
h->freefun = freefun;
h->chunk_size = size;
h->alignment_mask = alignment - 1;
chunk = h->chunk = (*h->chunkfun) (h->chunk_size);
h->next_free = h->object_base = chunk->contents;
h->chunk_limit = chunk->limit
= (char *) chunk + h->chunk_size;
chunk->prev = 0;
}
/* Allocate a new current chunk for the obstack *H
on the assumption that LENGTH bytes need to be added
to the current object, or a new object of length LENGTH allocated.
Copies any partial object from the end of the old chunk
to the beginning of the new one. */
void
_obstack_newchunk (h, length)
struct obstack *h;
int length;
{
register struct _obstack_chunk* old_chunk = h->chunk;
register struct _obstack_chunk* new_chunk;
register long new_size;
register int obj_size = h->next_free - h->object_base;
register int i;
/* Compute size for new chunk. */
new_size = (obj_size + length) << 1;
if (new_size < h->chunk_size)
new_size = h->chunk_size;
/* Allocate and initialize the new chunk. */
new_chunk = h->chunk = (*h->chunkfun) (new_size);
new_chunk->prev = old_chunk;
new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
/* Move the existing object to the new chunk.
Word at a time is fast and is safe because these
structures are aligned at least that much. */
for (i = (obj_size + sizeof (COPYING_UNIT) - 1) / sizeof (COPYING_UNIT) - 1;
i >= 0; i--)
((COPYING_UNIT *)new_chunk->contents)[i]
= ((COPYING_UNIT *)h->object_base)[i];
h->object_base = new_chunk->contents;
h->next_free = h->object_base + obj_size;
}
/* Return nonzero if object OBJ has been allocated from obstack H.
This is here for debugging.
If you use it in a program, you are probably losing. */
int
_obstack_allocated_p (h, obj)
struct obstack *h;
POINTER obj;
{
register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
register struct _obstack_chunk* plp; /* point to previous chunk if any */
lp = (h)->chunk;
while (lp != 0 && ((POINTER)lp > obj || (POINTER)(lp)->limit < obj))
{
plp = lp -> prev;
lp = plp;
}
return lp != 0;
}
/* Free objects in obstack H, including OBJ and everything allocate
more recently than OBJ. If OBJ is zero, free everything in H. */
void
#ifdef __STDC__
#undef obstack_free
obstack_free (struct obstack *h, POINTER obj)
#else
_obstack_free (h, obj)
struct obstack *h;
POINTER obj;
#endif
{
register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
register struct _obstack_chunk* plp; /* point to previous chunk if any */
lp = (h)->chunk;
while (lp != 0 && ((POINTER)lp > obj || (POINTER)(lp)->limit < obj))
{
plp = lp -> prev;
(*h->freefun) (lp);
lp = plp;
}
if (lp)
{
(h)->object_base = (h)->next_free = (char *)(obj);
(h)->chunk_limit = lp->limit;
(h)->chunk = lp;
}
else if (obj != 0)
/* obj is not in any of the chunks! */
abort ();
}
/* Let same .o link with output of gcc and other compilers. */
#ifdef __STDC__
void
_obstack_free (h, obj)
struct obstack *h;
POINTER obj;
{
obstack_free (h, obj);
}
#endif
#if 0
/* These are now turned off because the applications do not use it
and it uses bcopy via obstack_grow, which causes trouble on sysV. */
/* Now define the functional versions of the obstack macros.
Define them to simply use the corresponding macros to do the job. */
#ifdef __STDC__
/* These function definitions do not work with non-ANSI preprocessors;
they won't pass through the macro names in parentheses. */
/* The function names appear in parentheses in order to prevent
the macro-definitions of the names from being expanded there. */
POINTER (obstack_base) (obstack)
struct obstack *obstack;
{
return obstack_base (obstack);
}
POINTER (obstack_next_free) (obstack)
struct obstack *obstack;
{
return obstack_next_free (obstack);
}
int (obstack_object_size) (obstack)
struct obstack *obstack;
{
return obstack_object_size (obstack);
}
int (obstack_room) (obstack)
struct obstack *obstack;
{
return obstack_room (obstack);
}
void (obstack_grow) (obstack, pointer, length)
struct obstack *obstack;
POINTER pointer;
int length;
{
obstack_grow (obstack, pointer, length);
}
void (obstack_grow0) (obstack, pointer, length)
struct obstack *obstack;
POINTER pointer;
int length;
{
obstack_grow0 (obstack, pointer, length);
}
void (obstack_1grow) (obstack, character)
struct obstack *obstack;
int character;
{
obstack_1grow (obstack, character);
}
void (obstack_blank) (obstack, length)
struct obstack *obstack;
int length;
{
obstack_blank (obstack, length);
}
void (obstack_1grow_fast) (obstack, character)
struct obstack *obstack;
int character;
{
obstack_1grow_fast (obstack, character);
}
void (obstack_blank_fast) (obstack, length)
struct obstack *obstack;
int length;
{
obstack_blank_fast (obstack, length);
}
POINTER (obstack_finish) (obstack)
struct obstack *obstack;
{
return obstack_finish (obstack);
}
POINTER (obstack_alloc) (obstack, length)
struct obstack *obstack;
int length;
{
return obstack_alloc (obstack, length);
}
POINTER (obstack_copy) (obstack, pointer, length)
struct obstack *obstack;
POINTER pointer;
int length;
{
return obstack_copy (obstack, pointer, length);
}
POINTER (obstack_copy0) (obstack, pointer, length)
struct obstack *obstack;
POINTER pointer;
int length;
{
return obstack_copy0 (obstack, pointer, length);
}
#endif /* __STDC__ */
#endif /* 0 */

372
gnu/usr.bin/gdb/obstack.h Normal file
View file

@ -0,0 +1,372 @@
/* obstack.h - object stack macros
Copyright (C) 1988 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 1, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding! */
/* Summary:
All the apparent functions defined here are macros. The idea
is that you would use these pre-tested macros to solve a
very specific set of problems, and they would run fast.
Caution: no side-effects in arguments please!! They may be
evaluated MANY times!!
These macros operate a stack of objects. Each object starts life
small, and may grow to maturity. (Consider building a word syllable
by syllable.) An object can move while it is growing. Once it has
been "finished" it never changes address again. So the "top of the
stack" is typically an immature growing object, while the rest of the
stack is of mature, fixed size and fixed address objects.
These routines grab large chunks of memory, using a function you
supply, called `obstack_chunk_alloc'. On occasion, they free chunks,
by calling `obstack_chunk_free'. You must define them and declare
them before using any obstack macros.
Each independent stack is represented by a `struct obstack'.
Each of the obstack macros expects a pointer to such a structure
as the first argument.
One motivation for this package is the problem of growing char strings
in symbol tables. Unless you are "facist pig with a read-only mind"
[Gosper's immortal quote from HAKMEM item 154, out of context] you
would not like to put any arbitrary upper limit on the length of your
symbols.
In practice this often means you will build many short symbols and a
few long symbols. At the time you are reading a symbol you don't know
how long it is. One traditional method is to read a symbol into a
buffer, realloc()ating the buffer every time you try to read a symbol
that is longer than the buffer. This is beaut, but you still will
want to copy the symbol from the buffer to a more permanent
symbol-table entry say about half the time.
With obstacks, you can work differently. Use one obstack for all symbol
names. As you read a symbol, grow the name in the obstack gradually.
When the name is complete, finalize it. Then, if the symbol exists already,
free the newly read name.
The way we do this is to take a large chunk, allocating memory from
low addresses. When you want to build a aymbol in the chunk you just
add chars above the current "high water mark" in the chunk. When you
have finished adding chars, because you got to the end of the symbol,
you know how long the chars are, and you can create a new object.
Mostly the chars will not burst over the highest address of the chunk,
because you would typically expect a chunk to be (say) 100 times as
long as an average object.
In case that isn't clear, when we have enough chars to make up
the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
so we just point to it where it lies. No moving of chars is
needed and this is the second win: potentially long strings need
never be explicitly shuffled. Once an object is formed, it does not
change its address during its lifetime.
When the chars burst over a chunk boundary, we allocate a larger
chunk, and then copy the partly formed object from the end of the old
chunk to the beggining of the new larger chunk. We then carry on
accreting characters to the end of the object as we normaly would.
A special macro is provided to add a single char at a time to a
growing object. This allows the use of register variables, which
break the ordinary 'growth' macro.
Summary:
We allocate large chunks.
We carve out one object at a time from the current chunk.
Once carved, an object never moves.
We are free to append data of any size to the currently
growing object.
Exactly one object is growing in an obstack at any one time.
You can run one obstack per control block.
You may have as many control blocks as you dare.
Because of the way we do it, you can `unwind' a obstack
back to a previous state. (You may remove objects much
as you would with a stack.)
*/
/* Don't do the contents of this file more than once. */
#ifndef __OBSTACKS__
#define __OBSTACKS__
/* We use subtraction of (char *)0 instead of casting to int
because on word-addressable machines a simple cast to int
may ignore the byte-within-word field of the pointer. */
#ifndef __PTR_TO_INT
#define __PTR_TO_INT(P) ((P) - (char *)0)
#endif
#ifndef __INT_TO_PTR
#define __INT_TO_PTR(P) ((P) + (char *)0)
#endif
struct _obstack_chunk /* Lives at front of each chunk. */
{
char *limit; /* 1 past end of this chunk */
struct _obstack_chunk *prev; /* address of prior chunk or NULL */
char contents[4]; /* objects begin here */
};
struct obstack /* control current object in current chunk */
{
long chunk_size; /* preferred size to allocate chunks in */
struct _obstack_chunk* chunk; /* address of current struct obstack_chunk */
char *object_base; /* address of object we are building */
char *next_free; /* where to add next char to current object */
char *chunk_limit; /* address of char after current chunk */
int temp; /* Temporary for some macros. */
int alignment_mask; /* Mask of alignment for each object. */
struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */
void (*freefun) (); /* User's function to free a chunk. */
};
#ifdef __STDC__
/* Do the function-declarations after the structs
but before defining the macros. */
void obstack_init (struct obstack *obstack);
void * obstack_alloc (struct obstack *obstack, int size);
void * obstack_copy (struct obstack *obstack, void *address, int size);
void * obstack_copy0 (struct obstack *obstack, void *address, int size);
void obstack_free (struct obstack *obstack, void *block);
void obstack_blank (struct obstack *obstack, int size);
void obstack_grow (struct obstack *obstack, void *data, int size);
void obstack_grow0 (struct obstack *obstack, void *data, int size);
void obstack_1grow (struct obstack *obstack, int data_char);
void * obstack_finish (struct obstack *obstack);
int obstack_object_size (struct obstack *obstack);
int obstack_room (struct obstack *obstack);
void obstack_1grow_fast (struct obstack *obstack, int data_char);
void obstack_blank_fast (struct obstack *obstack, int size);
void * obstack_base (struct obstack *obstack);
void * obstack_next_free (struct obstack *obstack);
int obstack_alignment_mask (struct obstack *obstack);
int obstack_chunk_size (struct obstack *obstack);
#endif /* __STDC__ */
/* Non-ANSI C cannot really support alternative functions for these macros,
so we do not declare them. */
/* Pointer to beginning of object being allocated or to be allocated next.
Note that this might not be the final address of the object
because a new chunk might be needed to hold the final size. */
#define obstack_base(h) ((h)->object_base)
/* Size for allocating ordinary chunks. */
#define obstack_chunk_size(h) ((h)->chunk_size)
/* Pointer to next byte not yet allocated in current chunk. */
#define obstack_next_free(h) ((h)->next_free)
/* Mask specifying low bits that should be clear in address of an object. */
#define obstack_alignment_mask(h) ((h)->alignment_mask)
#define obstack_init(h) \
_obstack_begin ((h), 0, 0, obstack_chunk_alloc, obstack_chunk_free)
#define obstack_begin(h, size) \
_obstack_begin ((h), (size), 0, obstack_chunk_alloc, obstack_chunk_free)
#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
#define obstack_blank_fast(h,n) ((h)->next_free += (n))
#if defined (__GNUC__) && defined (__STDC__)
/* For GNU C, if not -traditional,
we can define these macros to compute all args only once
without using a global variable.
Also, we can avoid using the `temp' slot, to make faster code. */
#define obstack_object_size(OBSTACK) \
({ struct obstack *__o = (OBSTACK); \
(unsigned) (__o->next_free - __o->object_base); })
#define obstack_room(OBSTACK) \
({ struct obstack *__o = (OBSTACK); \
(unsigned) (__o->chunk_limit - __o->next_free); })
#define obstack_grow(OBSTACK,where,length) \
({ struct obstack *__o = (OBSTACK); \
int __len = (length); \
((__o->next_free + __len > __o->chunk_limit) \
? _obstack_newchunk (__o, __len) : 0); \
bcopy (where, __o->next_free, __len); \
__o->next_free += __len; \
(void) 0; })
#define obstack_grow0(OBSTACK,where,length) \
({ struct obstack *__o = (OBSTACK); \
int __len = (length); \
((__o->next_free + __len + 1 > __o->chunk_limit) \
? _obstack_newchunk (__o, __len + 1) : 0), \
bcopy (where, __o->next_free, __len), \
__o->next_free += __len, \
*(__o->next_free)++ = 0; \
(void) 0; })
#define obstack_1grow(OBSTACK,datum) \
({ struct obstack *__o = (OBSTACK); \
((__o->next_free + 1 > __o->chunk_limit) \
? _obstack_newchunk (__o, 1) : 0), \
*(__o->next_free)++ = (datum); \
(void) 0; })
#define obstack_blank(OBSTACK,length) \
({ struct obstack *__o = (OBSTACK); \
int __len = (length); \
((__o->next_free + __len > __o->chunk_limit) \
? _obstack_newchunk (__o, __len) : 0); \
__o->next_free += __len; \
(void) 0; })
#define obstack_alloc(OBSTACK,length) \
({ struct obstack *__h = (OBSTACK); \
obstack_blank (__h, (length)); \
obstack_finish (__h); })
#define obstack_copy(OBSTACK,where,length) \
({ struct obstack *__h = (OBSTACK); \
obstack_grow (__h, (where), (length)); \
obstack_finish (__h); })
#define obstack_copy0(OBSTACK,where,length) \
({ struct obstack *__h = (OBSTACK); \
obstack_grow0 (__h, (where), (length)); \
obstack_finish (__h); })
#define obstack_finish(OBSTACK) \
({ struct obstack *__o = (OBSTACK); \
void *value = (void *) __o->object_base; \
__o->next_free \
= __INT_TO_PTR ((__PTR_TO_INT (__o->next_free)+__o->alignment_mask)\
& ~ (__o->alignment_mask)); \
((__o->next_free - (char *)__o->chunk \
> __o->chunk_limit - (char *)__o->chunk) \
? (__o->next_free = __o->chunk_limit) : 0); \
__o->object_base = __o->next_free; \
value; })
#define obstack_free(OBSTACK, OBJ) \
({ struct obstack *__o = (OBSTACK); \
void *__obj = (OBJ); \
if (__obj >= (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
__o->next_free = __o->object_base = __obj; \
else (obstack_free) (__o, __obj); })
#else /* not __GNUC__ or not __STDC__ */
/* The non-GNU macros copy the obstack-pointer into this global variable
to avoid multiple evaluation. */
extern struct obstack *_obstack;
#define obstack_object_size(h) \
(unsigned) (_obstack = (h), (h)->next_free - (h)->object_base)
#define obstack_room(h) \
(unsigned) (_obstack = (h), (h)->chunk_limit - (h)->next_free)
#define obstack_grow(h,where,length) \
( (h)->temp = (length), \
(((h)->next_free + (h)->temp > (h)->chunk_limit) \
? _obstack_newchunk ((h), (h)->temp) : 0), \
bcopy (where, (h)->next_free, (h)->temp), \
(h)->next_free += (h)->temp)
#define obstack_grow0(h,where,length) \
( (h)->temp = (length), \
(((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \
? _obstack_newchunk ((h), (h)->temp + 1) : 0), \
bcopy (where, (h)->next_free, (h)->temp), \
(h)->next_free += (h)->temp, \
*((h)->next_free)++ = 0)
#define obstack_1grow(h,datum) \
( (((h)->next_free + 1 > (h)->chunk_limit) \
? _obstack_newchunk ((h), 1) : 0), \
*((h)->next_free)++ = (datum))
#define obstack_blank(h,length) \
( (h)->temp = (length), \
(((h)->next_free + (h)->temp > (h)->chunk_limit) \
? _obstack_newchunk ((h), (h)->temp) : 0), \
(h)->next_free += (h)->temp)
#define obstack_alloc(h,length) \
(obstack_blank ((h), (length)), obstack_finish ((h)))
#define obstack_copy(h,where,length) \
(obstack_grow ((h), (where), (length)), obstack_finish ((h)))
#define obstack_copy0(h,where,length) \
(obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
#define obstack_finish(h) \
( (h)->temp = __PTR_TO_INT ((h)->object_base), \
(h)->next_free \
= __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \
& ~ ((h)->alignment_mask)), \
(((h)->next_free - (char *)(h)->chunk \
> (h)->chunk_limit - (char *)(h)->chunk) \
? ((h)->next_free = (h)->chunk_limit) : 0), \
(h)->object_base = (h)->next_free, \
__INT_TO_PTR ((h)->temp))
#ifdef __STDC__
#define obstack_free(h,obj) \
( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
(((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
? (int) ((h)->next_free = (h)->object_base \
= (h)->temp + (char *) (h)->chunk) \
: ((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0)))
#else
#define obstack_free(h,obj) \
( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
(((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
? (int) ((h)->next_free = (h)->object_base \
= (h)->temp + (char *) (h)->chunk) \
: (int) _obstack_free ((h), (h)->temp + (char *) (h)->chunk)))
#endif
#endif /* not __GNUC__ or not __STDC__ */
#endif /* not __OBSTACKS__ */

1867
gnu/usr.bin/gdb/printcmd.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,98 @@
Thu Feb 8 01:04:00 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
* Makefile (the *other* libreadline.a): Uncomment out ranlib line.
Thu Feb 1 17:50:22 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
* Makefile (libreadline.a): Uncomment out ranlib line.
Sun Nov 26 16:29:11 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
* readline.c (rl_deprep_terminal): Only restore local_mode_flags
if they had been set.
Thu Oct 19 17:18:40 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
* Move vi_doing_insert from vi_mode.c to readline.c
* readline.c: Move compare_strings before its use.
Remove declarations.
* readline.c: Move defining_kbd_macro above rl_dispatch.
(rl_dispatch): Remove "extern int defining_kbd_macro".
Mon Oct 16 11:56:03 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
* readline.c (rl_set_signals): Remove unnecessary "static int
rl_signal_handler()".
Sat Sep 30 14:51:56 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
* readline.c (rl_initialize): Change parsing_conditionalized_out
to static.
(rl_dispatch): Change defining_kbd_macro to static.
(rl_newline): Change vi_doing_insert to static.
Fri Sep 8 09:00:45 1989 Brian Fox (bfox at aurel)
* readline.c: rl_prep_terminal (). Only turn on 8th bit
as meta-bit iff the terminal is not using parity.
Sun Sep 3 08:57:40 1989 Brian Fox (bfox at aurel)
* readline.c: start_insert (). Uses multiple
insertion call in cases where that makes sense.
rl_insert (). Read type-ahead buffer for additional
keys that are bound to rl_insert, and insert them
all at once. Make insertion of single keys given
with an argument much more efficient.
Tue Aug 8 18:13:57 1989 Brian Fox (bfox at aurel)
* readline.c: Changed handling of EOF. readline () returns
(char *)EOF or consed string. The EOF character is read from the
tty, or if the tty doesn't have one, defaults to C-d.
* readline.c: Added support for event driven programs.
rl_event_hook is the address of a function you want called
while Readline is waiting for input.
* readline.c: Cleanup time. Functions without type declarations
do not use return with a value.
* history.c: history_expand () has new variable which is the
characters to ignore immediately following history_expansion_char.
Sun Jul 16 08:14:00 1989 Brian Fox (bfox at aurel)
* rl_prep_terminal ()
BSD version turns off C-s, C-q, C-y, C-v.
* readline.c -- rl_prep_terminal ()
SYSV version hacks readline_echoing_p.
BSD version turns on passing of the 8th bit for the duration
of reading the line.
Tue Jul 11 06:25:01 1989 Brian Fox (bfox at aurel)
* readline.c: new variable rl_tilde_expander.
If non-null, this contains the address of a function to call if
the standard meaning for expanding a tilde fails. The function is
called with the text sans tilde (as in "foo"), and returns a
malloc()'ed string which is the expansion, or a NULL pointer if
there is no expansion.
* readline.h - new file chardefs.h
Separates things that only readline.c needs from the standard
header file publishing interesting things about readline.
* readline.c:
readline_default_bindings () now looks at terminal chararacters
and binds those as well.
Wed Jun 28 20:20:51 1989 Brian Fox (bfox at aurel)
* Made readline and history into independent libraries.

View file

@ -0,0 +1,114 @@
## -*- text -*- ####################################################
# #
# Makefile for readline and history libraries. #
# #
####################################################################
# Here is a rule for making .o files from .c files that doesn't force
# the type of the machine (like -sun3) into the flags.
.c.o:
$(CC) -c $(CFLAGS) $(LOCAL_INCLUDES) $(CPPFLAGS) $*.c
# Destination installation directory. The libraries are copied to DESTDIR
# when you do a `make install', and the header files to INCDIR/readline/*.h.
DESTDIR = /usr/gnu/lib
INCDIR = /usr/gnu/include
# Define TYPES as -DVOID_SIGHANDLER if your operating system uses
# a return type of "void" for signal handlers.
TYPES = -DVOID_SIGHANDLER
# Define SYSV as -DSYSV if you are using a System V operating system.
#SYSV = -DSYSV
# HP-UX compilation requires the BSD library.
#LOCAL_LIBS = -lBSD
# Xenix compilation requires -ldir -lx
#LOCAL_LIBS = -ldir -lx
# Comment this out if you don't think that anyone will ever desire
# the vi line editing mode and features.
READLINE_DEFINES = -DVI_MODE
DEBUG_FLAGS = -g
LDFLAGS = $(DEBUG_FLAGS)
CFLAGS = $(DEBUG_FLAGS) $(TYPE) $(SYSV) -I.
# A good alternative is gcc -traditional.
#CC = gcc -traditional
CC = cc
RANLIB = /usr/bin/ranlib
AR = ar
RM = rm
CP = cp
LOCAL_INCLUDES = -I../
CSOURCES = readline.c history.c funmap.c keymaps.c vi_mode.c \
emacs_keymap.c vi_keymap.c keymaps.c
HSOURCES = readline.h chardefs.h history.h keymaps.h
SOURCES = $(CSOURCES) $(HSOURCES)
DOCUMENTATION = readline.texinfo inc-readline.texinfo \
history.texinfo inc-history.texinfo
SUPPORT = COPYING Makefile $(DOCUMENTATION) ChangeLog
THINGS_TO_TAR = $(SOURCES) $(SUPPORT)
##########################################################################
all: libreadline.a
libreadline.a: readline.o history.o funmap.o keymaps.o
$(RM) -f libreadline.a
$(AR) clq libreadline.a readline.o history.o funmap.o keymaps.o
if [ -f $(RANLIB) ]; then $(RANLIB) libreadline.a; fi
readline.o: readline.h chardefs.h keymaps.h history.h readline.c vi_mode.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $(READLINE_DEFINES) \
$(LOCAL_INCLUDES) $*.c
history.o: history.c history.h
$(CC) -c $(CFLAGS) $(CPPFLAGS) $(READLINE_DEFINES) \
$(LOCAL_INCLUDES) $*.c
funmap.o: readline.h
$(CC) -c $(CFLAGS) $(CPPFLAGS) $(READLINE_DEFINES) \
$(LOCAL_INCLUDES) $*.c
keymaps.o: emacs_keymap.c vi_keymap.c keymaps.h chardefs.h keymaps.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $(READLINE_DEFINES) \
$(LOCAL_INCLUDES) $*.c
libtest: libreadline.a libtest.c
$(CC) -o libtest $(CFLAGS) $(CPPFLAGS) -L. libtest.c -lreadline -ltermcap
readline: readline.c history.o keymaps.o funmap.o readline.h chardefs.h
$(CC) $(CFLAGS) $(CPPFLAGS) $(READLINE_DEFINES) \
$(LOCAL_INCLUDES) -DTEST -o readline readline.c funmap.o \
keymaps.o history.o -L. -ltermcap
readline.tar: $(THINGS_TO_TAR)
tar -cf readline.tar $(THINGS_TO_TAR)
readline.tar.Z: readline.tar
compress -f readline.tar
install: $(DESTDIR)/libreadline.a includes
includes:
if [ ! -r $(INCDIR)/readline ]; then\
mkdir $(INCDIR)/readline;\
chmod a+r $(INCDIR)/readline;\
fi
$(CP) readline.h keymaps.h chardefs.h $(INCDIR)/readline/
clean:
rm -f *.o *.a *.log *.cp *.tp *.vr *.fn *.aux *.pg *.toc
$(DESTDIR)/libreadline.a: libreadline.a
-mv $(DESTDIR)/libreadline.a $(DESTDIR)/libreadline.old
cp libreadline.a $(DESTDIR)/libreadline.a
$(RANLIB) -t $(DESTDIR)/libreadline.a

View file

@ -0,0 +1,50 @@
/* chardefs.h -- Character definitions for readline. */
#ifndef _CHARDEFS_
#ifndef savestring
#define savestring(x) (char *)strcpy (xmalloc (1 + strlen (x)), (x))
#endif
#ifndef whitespace
#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
#endif
#ifdef CTRL
#undef CTRL
#endif
/* Some character stuff. */
#define control_character_threshold 0x020 /* smaller than this is control */
#define meta_character_threshold 0x07f /* larger than this is Meta. */
#define control_character_bit 0x40 /* 0x000000, must be off. */
#define meta_character_bit 0x080 /* x0000000, must be on. */
#define CTRL(c) ((c) & (~control_character_bit))
#define META(c) ((c) | meta_character_bit)
#define UNMETA(c) ((c) & (~meta_character_bit))
#define UNCTRL(c) to_upper(((c)|control_character_bit))
#define lowercase_p(c) (((c) > ('a' - 1) && (c) < ('z' + 1)))
#define uppercase_p(c) (((c) > ('A' - 1) && (c) < ('Z' + 1)))
#define pure_alphabetic(c) (lowercase_p(c) || uppercase_p(c))
#ifndef to_upper
#define to_upper(c) (lowercase_p(c) ? ((c) - 32) : (c))
#define to_lower(c) (uppercase_p(c) ? ((c) + 32) : (c))
#endif
#define CTRL_P(c) ((c) < control_character_threshold)
#define META_P(c) ((c) > meta_character_threshold)
#define NEWLINE '\n'
#define RETURN CTRL('M')
#define RUBOUT 0x07f
#define TAB '\t'
#define ABORT_CHAR CTRL('G')
#define PAGE CTRL('L')
#define SPACE 0x020
#define ESC CTRL('[')
#endif /* _CHARDEFS_ */

View file

@ -0,0 +1,472 @@
/* emacs_keymap.c -- the keymap for emacs_mode in readline (). */
/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
This file is part of GNU Readline, a library for reading lines
of text with interactive input and history editing.
Readline is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 1, or (at your option) any
later version.
Readline is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with Readline; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef FILE
#include <stdio.h>
#endif /* FILE */
#include "readline.h"
/* An array of function pointers, one for each possible key.
If the type byte is ISKMAP, then the pointer is the address of
a keymap. */
KEYMAP_ENTRY_ARRAY emacs_standard_keymap = {
/* Control keys. */
{ ISFUNC, (Function *)0x0 }, /* Control-@ */
{ ISFUNC, rl_beg_of_line }, /* Control-a */
{ ISFUNC, rl_backward }, /* Control-b */
{ ISFUNC, (Function *)0x0 }, /* Control-c */
{ ISFUNC, rl_delete }, /* Control-d */
{ ISFUNC, rl_end_of_line }, /* Control-e */
{ ISFUNC, rl_forward }, /* Control-f */
{ ISFUNC, rl_abort }, /* Control-g */
{ ISFUNC, rl_backward }, /* Control-h */
{ ISFUNC, rl_complete }, /* Control-i */
{ ISFUNC, rl_newline }, /* Control-j */
{ ISFUNC, rl_kill_line }, /* Control-k */
{ ISFUNC, rl_clear_screen }, /* Control-l */
{ ISFUNC, rl_newline }, /* Control-m */
{ ISFUNC, rl_get_next_history }, /* Control-n */
{ ISFUNC, (Function *)0x0 }, /* Control-o */
{ ISFUNC, rl_get_previous_history }, /* Control-p */
{ ISFUNC, rl_quoted_insert }, /* Control-q */
{ ISFUNC, rl_reverse_search_history }, /* Control-r */
{ ISFUNC, rl_forward_search_history }, /* Control-s */
{ ISFUNC, rl_transpose_chars }, /* Control-t */
{ ISFUNC, rl_unix_line_discard }, /* Control-u */
{ ISFUNC, rl_quoted_insert }, /* Control-v */
{ ISFUNC, rl_unix_word_rubout }, /* Control-w */
{ ISKMAP, (Function *)emacs_ctlx_keymap }, /* Control-x */
{ ISFUNC, rl_yank }, /* Control-y */
{ ISFUNC, (Function *)0x0 }, /* Control-z */
{ ISKMAP, (Function *)emacs_meta_keymap }, /* Control-[ */
{ ISFUNC, (Function *)0x0 }, /* Control-\ */
{ ISFUNC, (Function *)0x0 }, /* Control-] */
{ ISFUNC, (Function *)0x0 }, /* Control-^ */
{ ISFUNC, rl_undo_command }, /* Control-_ */
/* The start of printing characters. */
{ ISFUNC, rl_insert }, /* SPACE */
{ ISFUNC, rl_insert }, /* ! */
{ ISFUNC, rl_insert }, /* " */
{ ISFUNC, rl_insert }, /* # */
{ ISFUNC, rl_insert }, /* $ */
{ ISFUNC, rl_insert }, /* % */
{ ISFUNC, rl_insert }, /* & */
{ ISFUNC, rl_insert }, /* ' */
{ ISFUNC, rl_insert }, /* ( */
{ ISFUNC, rl_insert }, /* ) */
{ ISFUNC, rl_insert }, /* * */
{ ISFUNC, rl_insert }, /* + */
{ ISFUNC, rl_insert }, /* , */
{ ISFUNC, rl_insert }, /* - */
{ ISFUNC, rl_insert }, /* . */
{ ISFUNC, rl_insert }, /* / */
/* Regular digits. */
{ ISFUNC, rl_insert }, /* 0 */
{ ISFUNC, rl_insert }, /* 1 */
{ ISFUNC, rl_insert }, /* 2 */
{ ISFUNC, rl_insert }, /* 3 */
{ ISFUNC, rl_insert }, /* 4 */
{ ISFUNC, rl_insert }, /* 5 */
{ ISFUNC, rl_insert }, /* 6 */
{ ISFUNC, rl_insert }, /* 7 */
{ ISFUNC, rl_insert }, /* 8 */
{ ISFUNC, rl_insert }, /* 9 */
/* A little more punctuation. */
{ ISFUNC, rl_insert }, /* : */
{ ISFUNC, rl_insert }, /* ; */
{ ISFUNC, rl_insert }, /* < */
{ ISFUNC, rl_insert }, /* = */
{ ISFUNC, rl_insert }, /* > */
{ ISFUNC, rl_insert }, /* ? */
{ ISFUNC, rl_insert }, /* @ */
/* Uppercase alphabet. */
{ ISFUNC, rl_insert }, /* A */
{ ISFUNC, rl_insert }, /* B */
{ ISFUNC, rl_insert }, /* C */
{ ISFUNC, rl_insert }, /* D */
{ ISFUNC, rl_insert }, /* E */
{ ISFUNC, rl_insert }, /* F */
{ ISFUNC, rl_insert }, /* G */
{ ISFUNC, rl_insert }, /* H */
{ ISFUNC, rl_insert }, /* I */
{ ISFUNC, rl_insert }, /* J */
{ ISFUNC, rl_insert }, /* K */
{ ISFUNC, rl_insert }, /* L */
{ ISFUNC, rl_insert }, /* M */
{ ISFUNC, rl_insert }, /* N */
{ ISFUNC, rl_insert }, /* O */
{ ISFUNC, rl_insert }, /* P */
{ ISFUNC, rl_insert }, /* Q */
{ ISFUNC, rl_insert }, /* R */
{ ISFUNC, rl_insert }, /* S */
{ ISFUNC, rl_insert }, /* T */
{ ISFUNC, rl_insert }, /* U */
{ ISFUNC, rl_insert }, /* V */
{ ISFUNC, rl_insert }, /* W */
{ ISFUNC, rl_insert }, /* X */
{ ISFUNC, rl_insert }, /* Y */
{ ISFUNC, rl_insert }, /* Z */
/* Some more punctuation. */
{ ISFUNC, rl_insert }, /* [ */
{ ISFUNC, rl_insert }, /* \ */
{ ISFUNC, rl_insert }, /* ] */
{ ISFUNC, rl_insert }, /* ^ */
{ ISFUNC, rl_insert }, /* _ */
{ ISFUNC, rl_insert }, /* ` */
/* Lowercase alphabet. */
{ ISFUNC, rl_insert }, /* a */
{ ISFUNC, rl_insert }, /* b */
{ ISFUNC, rl_insert }, /* c */
{ ISFUNC, rl_insert }, /* d */
{ ISFUNC, rl_insert }, /* e */
{ ISFUNC, rl_insert }, /* f */
{ ISFUNC, rl_insert }, /* g */
{ ISFUNC, rl_insert }, /* h */
{ ISFUNC, rl_insert }, /* i */
{ ISFUNC, rl_insert }, /* j */
{ ISFUNC, rl_insert }, /* k */
{ ISFUNC, rl_insert }, /* l */
{ ISFUNC, rl_insert }, /* m */
{ ISFUNC, rl_insert }, /* n */
{ ISFUNC, rl_insert }, /* o */
{ ISFUNC, rl_insert }, /* p */
{ ISFUNC, rl_insert }, /* q */
{ ISFUNC, rl_insert }, /* r */
{ ISFUNC, rl_insert }, /* s */
{ ISFUNC, rl_insert }, /* t */
{ ISFUNC, rl_insert }, /* u */
{ ISFUNC, rl_insert }, /* v */
{ ISFUNC, rl_insert }, /* w */
{ ISFUNC, rl_insert }, /* x */
{ ISFUNC, rl_insert }, /* y */
{ ISFUNC, rl_insert }, /* z */
/* Final punctuation. */
{ ISFUNC, rl_insert }, /* { */
{ ISFUNC, rl_insert }, /* | */
{ ISFUNC, rl_insert }, /* } */
{ ISFUNC, rl_insert }, /* ~ */
{ ISFUNC, rl_rubout } /* RUBOUT */
};
KEYMAP_ENTRY_ARRAY emacs_meta_keymap = {
/* Meta keys. Just like above, but the high bit is set. */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-@ */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-a */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-b */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-c */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-d */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-e */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-f */
{ ISFUNC, rl_abort }, /* Meta-Control-g */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-h */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-i */
{ ISFUNC, rl_vi_editing_mode }, /* Meta-Control-j */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-k */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-l */
{ ISFUNC, rl_vi_editing_mode }, /* Meta-Control-m */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-n */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-o */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-p */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-q */
{ ISFUNC, rl_revert_line }, /* Meta-Control-r */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-s */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-t */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-u */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-v */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-w */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-x */
{ ISFUNC, rl_yank_nth_arg }, /* Meta-Control-y */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-z */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-[ */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-\ */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-] */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-^ */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-_ */
/* The start of printing characters. */
{ ISFUNC, (Function *)0x0 }, /* Meta-SPACE */
{ ISFUNC, (Function *)0x0 }, /* Meta-! */
{ ISFUNC, (Function *)0x0 }, /* Meta-" */
{ ISFUNC, (Function *)0x0 }, /* Meta-# */
{ ISFUNC, (Function *)0x0 }, /* Meta-$ */
{ ISFUNC, (Function *)0x0 }, /* Meta-% */
{ ISFUNC, (Function *)0x0 }, /* Meta-& */
{ ISFUNC, (Function *)0x0 }, /* Meta-' */
{ ISFUNC, (Function *)0x0 }, /* Meta-( */
{ ISFUNC, (Function *)0x0 }, /* Meta-) */
{ ISFUNC, (Function *)0x0 }, /* Meta-* */
{ ISFUNC, (Function *)0x0 }, /* Meta-+ */
{ ISFUNC, (Function *)0x0 }, /* Meta-, */
{ ISFUNC, rl_digit_argument }, /* Meta-- */
{ ISFUNC, (Function *)0x0 }, /* Meta-. */
{ ISFUNC, (Function *)0x0 }, /* Meta-/ */
/* Regular digits. */
{ ISFUNC, rl_digit_argument }, /* Meta-0 */
{ ISFUNC, rl_digit_argument }, /* Meta-1 */
{ ISFUNC, rl_digit_argument }, /* Meta-2 */
{ ISFUNC, rl_digit_argument }, /* Meta-3 */
{ ISFUNC, rl_digit_argument }, /* Meta-4 */
{ ISFUNC, rl_digit_argument }, /* Meta-5 */
{ ISFUNC, rl_digit_argument }, /* Meta-6 */
{ ISFUNC, rl_digit_argument }, /* Meta-7 */
{ ISFUNC, rl_digit_argument }, /* Meta-8 */
{ ISFUNC, rl_digit_argument }, /* Meta-9 */
/* A little more punctuation. */
{ ISFUNC, (Function *)0x0 }, /* Meta-: */
{ ISFUNC, (Function *)0x0 }, /* Meta-; */
{ ISFUNC, rl_beginning_of_history }, /* Meta-< */
{ ISFUNC, (Function *)0x0 }, /* Meta-= */
{ ISFUNC, rl_end_of_history }, /* Meta-> */
{ ISFUNC, rl_possible_completions }, /* Meta-? */
{ ISFUNC, (Function *)0x0 }, /* Meta-@ */
/* Uppercase alphabet. */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-A */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-B */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-C */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-D */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-E */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-F */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-G */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-H */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-I */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-J */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-K */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-L */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-M */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-N */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-O */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-P */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-Q */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-R */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-S */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-T */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-U */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-V */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-W */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-X */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-Y */
{ ISFUNC, rl_do_lowercase_version }, /* Meta-Z */
/* Some more punctuation. */
{ ISFUNC, (Function *)0x0 }, /* Meta-[ */
{ ISFUNC, (Function *)0x0 }, /* Meta-\ */
{ ISFUNC, (Function *)0x0 }, /* Meta-] */
{ ISFUNC, (Function *)0x0 }, /* Meta-^ */
{ ISFUNC, (Function *)0x0 }, /* Meta-_ */
{ ISFUNC, (Function *)0x0 }, /* Meta-` */
/* Lowercase alphabet. */
{ ISFUNC, (Function *)0x0 }, /* Meta-a */
{ ISFUNC, rl_backward_word }, /* Meta-b */
{ ISFUNC, rl_capitalize_word }, /* Meta-c */
{ ISFUNC, rl_kill_word }, /* Meta-d */
{ ISFUNC, (Function *)0x0 }, /* Meta-e */
{ ISFUNC, rl_forward_word }, /* Meta-f */
{ ISFUNC, (Function *)0x0 }, /* Meta-g */
{ ISFUNC, (Function *)0x0 }, /* Meta-h */
{ ISFUNC, (Function *)0x0 }, /* Meta-i */
{ ISFUNC, (Function *)0x0 }, /* Meta-j */
{ ISFUNC, (Function *)0x0 }, /* Meta-k */
{ ISFUNC, rl_downcase_word }, /* Meta-l */
{ ISFUNC, (Function *)0x0 }, /* Meta-m */
{ ISFUNC, (Function *)0x0 }, /* Meta-n */
{ ISFUNC, (Function *)0x0 }, /* Meta-o */
{ ISFUNC, (Function *)0x0 }, /* Meta-p */
{ ISFUNC, (Function *)0x0 }, /* Meta-q */
{ ISFUNC, rl_revert_line }, /* Meta-r */
{ ISFUNC, (Function *)0x0 }, /* Meta-s */
{ ISFUNC, rl_transpose_words }, /* Meta-t */
{ ISFUNC, rl_upcase_word }, /* Meta-u */
{ ISFUNC, (Function *)0x0 }, /* Meta-v */
{ ISFUNC, (Function *)0x0 }, /* Meta-w */
{ ISFUNC, (Function *)0x0 }, /* Meta-x */
{ ISFUNC, rl_yank_pop }, /* Meta-y */
{ ISFUNC, (Function *)0x0 }, /* Meta-z */
/* Final punctuation. */
{ ISFUNC, (Function *)0x0 }, /* Meta-{ */
{ ISFUNC, (Function *)0x0 }, /* Meta-| */
{ ISFUNC, (Function *)0x0 }, /* Meta-} */
{ ISFUNC, (Function *)0x0 }, /* Meta-~ */
{ ISFUNC, rl_backward_kill_word } /* Meta-rubout */
};
KEYMAP_ENTRY_ARRAY emacs_ctlx_keymap = {
/* Control keys. */
{ ISFUNC, (Function *)0x0 }, /* Control-@ */
{ ISFUNC, (Function *)0x0 }, /* Control-a */
{ ISFUNC, (Function *)0x0 }, /* Control-b */
{ ISFUNC, (Function *)0x0 }, /* Control-c */
{ ISFUNC, (Function *)0x0 }, /* Control-d */
{ ISFUNC, (Function *)0x0 }, /* Control-e */
{ ISFUNC, (Function *)0x0 }, /* Control-f */
{ ISFUNC, rl_abort }, /* Control-g */
{ ISFUNC, (Function *)0x0 }, /* Control-h */
{ ISFUNC, (Function *)0x0 }, /* Control-i */
{ ISFUNC, (Function *)0x0 }, /* Control-j */
{ ISFUNC, (Function *)0x0 }, /* Control-k */
{ ISFUNC, (Function *)0x0 }, /* Control-l */
{ ISFUNC, (Function *)0x0 }, /* Control-m */
{ ISFUNC, (Function *)0x0 }, /* Control-n */
{ ISFUNC, (Function *)0x0 }, /* Control-o */
{ ISFUNC, (Function *)0x0 }, /* Control-p */
{ ISFUNC, (Function *)0x0 }, /* Control-q */
{ ISFUNC, rl_re_read_init_file }, /* Control-r */
{ ISFUNC, (Function *)0x0 }, /* Control-s */
{ ISFUNC, (Function *)0x0 }, /* Control-t */
{ ISFUNC, rl_undo_command }, /* Control-u */
{ ISFUNC, (Function *)0x0 }, /* Control-v */
{ ISFUNC, (Function *)0x0 }, /* Control-w */
{ ISFUNC, (Function *)0x0 }, /* Control-x */
{ ISFUNC, (Function *)0x0 }, /* Control-y */
{ ISFUNC, (Function *)0x0 }, /* Control-z */
{ ISFUNC, (Function *)0x0 }, /* Control-[ */
{ ISFUNC, (Function *)0x0 }, /* Control-\ */
{ ISFUNC, (Function *)0x0 }, /* Control-] */
{ ISFUNC, (Function *)0x0 }, /* Control-^ */
{ ISFUNC, (Function *)0x0 }, /* Control-_ */
/* The start of printing characters. */
{ ISFUNC, (Function *)0x0 }, /* SPACE */
{ ISFUNC, (Function *)0x0 }, /* ! */
{ ISFUNC, (Function *)0x0 }, /* " */
{ ISFUNC, (Function *)0x0 }, /* # */
{ ISFUNC, (Function *)0x0 }, /* $ */
{ ISFUNC, (Function *)0x0 }, /* % */
{ ISFUNC, (Function *)0x0 }, /* & */
{ ISFUNC, (Function *)0x0 }, /* ' */
{ ISFUNC, rl_start_kbd_macro }, /* ( */
{ ISFUNC, rl_end_kbd_macro }, /* ) */
{ ISFUNC, (Function *)0x0 }, /* * */
{ ISFUNC, (Function *)0x0 }, /* + */
{ ISFUNC, (Function *)0x0 }, /* , */
{ ISFUNC, (Function *)0x0 }, /* - */
{ ISFUNC, (Function *)0x0 }, /* . */
{ ISFUNC, (Function *)0x0 }, /* / */
/* Regular digits. */
{ ISFUNC, (Function *)0x0 }, /* 0 */
{ ISFUNC, (Function *)0x0 }, /* 1 */
{ ISFUNC, (Function *)0x0 }, /* 2 */
{ ISFUNC, (Function *)0x0 }, /* 3 */
{ ISFUNC, (Function *)0x0 }, /* 4 */
{ ISFUNC, (Function *)0x0 }, /* 5 */
{ ISFUNC, (Function *)0x0 }, /* 6 */
{ ISFUNC, (Function *)0x0 }, /* 7 */
{ ISFUNC, (Function *)0x0 }, /* 8 */
{ ISFUNC, (Function *)0x0 }, /* 9 */
/* A little more punctuation. */
{ ISFUNC, (Function *)0x0 }, /* : */
{ ISFUNC, (Function *)0x0 }, /* ; */
{ ISFUNC, (Function *)0x0 }, /* < */
{ ISFUNC, (Function *)0x0 }, /* = */
{ ISFUNC, (Function *)0x0 }, /* > */
{ ISFUNC, (Function *)0x0 }, /* ? */
{ ISFUNC, (Function *)0x0 }, /* @ */
/* Uppercase alphabet. */
{ ISFUNC, rl_do_lowercase_version }, /* A */
{ ISFUNC, rl_do_lowercase_version }, /* B */
{ ISFUNC, rl_do_lowercase_version }, /* C */
{ ISFUNC, rl_do_lowercase_version }, /* D */
{ ISFUNC, rl_do_lowercase_version }, /* E */
{ ISFUNC, rl_do_lowercase_version }, /* F */
{ ISFUNC, rl_do_lowercase_version }, /* G */
{ ISFUNC, rl_do_lowercase_version }, /* H */
{ ISFUNC, rl_do_lowercase_version }, /* I */
{ ISFUNC, rl_do_lowercase_version }, /* J */
{ ISFUNC, rl_do_lowercase_version }, /* K */
{ ISFUNC, rl_do_lowercase_version }, /* L */
{ ISFUNC, rl_do_lowercase_version }, /* M */
{ ISFUNC, rl_do_lowercase_version }, /* N */
{ ISFUNC, rl_do_lowercase_version }, /* O */
{ ISFUNC, rl_do_lowercase_version }, /* P */
{ ISFUNC, rl_do_lowercase_version }, /* Q */
{ ISFUNC, rl_do_lowercase_version }, /* R */
{ ISFUNC, rl_do_lowercase_version }, /* S */
{ ISFUNC, rl_do_lowercase_version }, /* T */
{ ISFUNC, rl_do_lowercase_version }, /* U */
{ ISFUNC, rl_do_lowercase_version }, /* V */
{ ISFUNC, rl_do_lowercase_version }, /* W */
{ ISFUNC, rl_do_lowercase_version }, /* X */
{ ISFUNC, rl_do_lowercase_version }, /* Y */
{ ISFUNC, rl_do_lowercase_version }, /* Z */
/* Some more punctuation. */
{ ISFUNC, (Function *)0x0 }, /* [ */
{ ISFUNC, (Function *)0x0 }, /* \ */
{ ISFUNC, (Function *)0x0 }, /* ] */
{ ISFUNC, (Function *)0x0 }, /* ^ */
{ ISFUNC, (Function *)0x0 }, /* _ */
{ ISFUNC, (Function *)0x0 }, /* ` */
/* Lowercase alphabet. */
{ ISFUNC, (Function *)0x0 }, /* a */
{ ISFUNC, (Function *)0x0 }, /* b */
{ ISFUNC, (Function *)0x0 }, /* c */
{ ISFUNC, (Function *)0x0 }, /* d */
{ ISFUNC, rl_call_last_kbd_macro }, /* e */
{ ISFUNC, (Function *)0x0 }, /* f */
{ ISFUNC, (Function *)0x0 }, /* g */
{ ISFUNC, (Function *)0x0 }, /* h */
{ ISFUNC, (Function *)0x0 }, /* i */
{ ISFUNC, (Function *)0x0 }, /* j */
{ ISFUNC, (Function *)0x0 }, /* k */
{ ISFUNC, (Function *)0x0 }, /* l */
{ ISFUNC, (Function *)0x0 }, /* m */
{ ISFUNC, (Function *)0x0 }, /* n */
{ ISFUNC, (Function *)0x0 }, /* o */
{ ISFUNC, (Function *)0x0 }, /* p */
{ ISFUNC, (Function *)0x0 }, /* q */
{ ISFUNC, rl_re_read_init_file }, /* r */
{ ISFUNC, (Function *)0x0 }, /* s */
{ ISFUNC, (Function *)0x0 }, /* t */
{ ISFUNC, (Function *)0x0 }, /* u */
{ ISFUNC, (Function *)0x0 }, /* v */
{ ISFUNC, (Function *)0x0 }, /* w */
{ ISFUNC, (Function *)0x0 }, /* x */
{ ISFUNC, (Function *)0x0 }, /* y */
{ ISFUNC, (Function *)0x0 }, /* z */
/* Final punctuation. */
{ ISFUNC, (Function *)0x0 }, /* { */
{ ISFUNC, (Function *)0x0 }, /* | */
{ ISFUNC, (Function *)0x0 }, /* } */
{ ISFUNC, (Function *)0x0 }, /* ~ */
{ ISFUNC, rl_backward_kill_line } /* RUBOUT */
};

View file

@ -0,0 +1,217 @@
/* funmap.c -- attach names to functions. */
/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
This file is part of GNU Readline, a library for reading lines
of text with interactive input and history editing.
Readline is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 1, or (at your option) any
later version.
Readline is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with Readline; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define STATIC_MALLOC
#ifndef STATIC_MALLOC
extern char *xmalloc (), *xrealloc ();
#else
static char *xmalloc (), *xrealloc ();
#endif
#ifndef FILE
#include <stdio.h>
#endif /* FILE */
#include "readline.h"
FUNMAP **funmap = (FUNMAP **)NULL;
static int funmap_size = 0;
static int just_testing_ar_tmp = 0;
static int just_testing_ar_tmp_2 = 5;
int foo_testing_ar;
static int funmap_entry = 0;
static FUNMAP default_funmap[] = {
{ "beginning-of-line", rl_beg_of_line },
{ "backward-char", rl_backward },
{ "delete-char", rl_delete },
{ "end-of-line", rl_end_of_line },
{ "forward-char", rl_forward },
{ "accept-line", rl_newline },
{ "kill-line", rl_kill_line },
{ "clear-screen", rl_clear_screen },
{ "next-history", rl_get_next_history },
{ "previous-history", rl_get_previous_history },
{ "quoted-insert", rl_quoted_insert },
{ "reverse-search-history", rl_reverse_search_history },
{ "forward-search-history", rl_forward_search_history },
{ "transpose-chars", rl_transpose_chars },
{ "unix-line-discard", rl_unix_line_discard },
{ "unix-word-rubout", rl_unix_word_rubout },
{ "yank", rl_yank },
{ "yank-pop", rl_yank_pop },
{ "yank-nth-arg", rl_yank_nth_arg },
{ "backward-delete-char", rl_rubout },
{ "backward-word", rl_backward_word },
{ "kill-word", rl_kill_word },
{ "forward-word", rl_forward_word },
{ "tab-insert", rl_tab_insert },
{ "backward-kill-word", rl_backward_kill_word },
{ "backward-kill-line", rl_backward_kill_line },
{ "transpose-words", rl_transpose_words },
{ "digit-argument", rl_digit_argument },
{ "complete", rl_complete },
{ "possible-completions", rl_possible_completions },
{ "do-lowercase-version", rl_do_lowercase_version },
{ "digit-argument", rl_digit_argument },
{ "universal-argument", rl_universal_argument },
{ "abort", rl_abort },
{ "undo", rl_undo_command },
{ "upcase-word", rl_upcase_word },
{ "downcase-word", rl_downcase_word },
{ "capitalize-word", rl_capitalize_word },
{ "revert-line", rl_revert_line },
{ "beginning-of-history", rl_beginning_of_history },
{ "end-of-history", rl_end_of_history },
{ "self-insert", rl_insert },
{ "start-kbd-macro", rl_start_kbd_macro },
{ "end-kbd-macro", rl_end_kbd_macro },
{ "re-read-init-file", rl_re_read_init_file },
#ifdef VI_MODE
{ "vi-movement-mode", rl_vi_movement_mode },
{ "vi-insertion-mode", rl_vi_insertion_mode },
{ "vi-arg-digit", rl_vi_arg_digit },
{ "vi-prev-word", rl_vi_prev_word },
{ "vi-next-word", rl_vi_next_word },
{ "vi-char-search", rl_vi_char_search },
{ "vi-editing-mode", rl_vi_editing_mode },
{ "vi-eof-maybe", rl_vi_eof_maybe },
{ "vi-append-mode", rl_vi_append_mode },
{ "vi-put", rl_vi_put },
{ "vi-append-eol", rl_vi_append_eol },
{ "vi-insert-beg", rl_vi_insert_beg },
{ "vi-delete", rl_vi_delete },
{ "vi-comment", rl_vi_comment },
{ "vi-first-print", rl_vi_first_print },
{ "vi-fword", rl_vi_fword },
{ "vi-fWord", rl_vi_fWord },
{ "vi-bword", rl_vi_bword },
{ "vi-bWord", rl_vi_bWord },
{ "vi-eword", rl_vi_eword },
{ "vi-eWord", rl_vi_eWord },
{ "vi-end-word", rl_vi_end_word },
{ "vi-change-case", rl_vi_change_case },
{ "vi-match", rl_vi_match },
{ "vi-bracktype", rl_vi_bracktype },
{ "vi-change-char", rl_vi_change_char },
{ "vi-yank-arg", rl_vi_yank_arg },
{ "vi-search", rl_vi_search },
{ "vi-search-again", rl_vi_search_again },
{ "vi-dosearch", rl_vi_dosearch },
{ "vi-subst", rl_vi_subst },
{ "vi-overstrike", rl_vi_overstrike },
{ "vi-overstrike-delete", rl_vi_overstrike_delete },
{ "vi-replace, ", rl_vi_replace },
{ "vi-column", rl_vi_column },
{ "vi-delete-to", rl_vi_delete_to },
{ "vi-change-to", rl_vi_change_to },
{ "vi-yank-to", rl_vi_yank_to },
{ "vi-complete", rl_vi_complete },
#endif /* VI_MODE */
{(char *)NULL, (Function *)NULL }
};
rl_add_funmap_entry (name, function)
char *name;
Function *function;
{
if (funmap_entry + 2 >= funmap_size)
if (!funmap)
funmap = (FUNMAP **)xmalloc ((funmap_size = 80) * sizeof (FUNMAP *));
else
funmap =
(FUNMAP **)xrealloc (funmap, (funmap_size += 80) * sizeof (FUNMAP *));
funmap[funmap_entry] = (FUNMAP *)xmalloc (sizeof (FUNMAP));
funmap[funmap_entry]->name = name;
funmap[funmap_entry]->function = function;
funmap[++funmap_entry] = (FUNMAP *)NULL;
}
static int funmap_initialized = 0;
/* Make the funmap contain all of the default entries. */
rl_initialize_funmap ()
{
register int i;
if (funmap_initialized)
return;
for (i = 0; default_funmap[i].name; i++)
rl_add_funmap_entry (default_funmap[i].name, default_funmap[i].function);
funmap_initialized = 1;
}
/* Things that mean `Control'. */
char *possible_control_prefixes[] = {
"Control-", "C-", "CTRL-", (char *)NULL
};
char *possible_meta_prefixes[] = {
"Meta", "M-", (char *)NULL
};
#ifdef STATIC_MALLOC
/* **************************************************************** */
/* */
/* xmalloc and xrealloc () */
/* */
/* **************************************************************** */
static char *
xmalloc (bytes)
int bytes;
{
static memory_error_and_abort ();
char *temp = (char *)malloc (bytes);
if (!temp)
memory_error_and_abort ();
return (temp);
}
static char *
xrealloc (pointer, bytes)
char *pointer;
int bytes;
{
static memory_error_and_abort ();
char *temp = (char *)realloc (pointer, bytes);
if (!temp)
memory_error_and_abort ();
return (temp);
}
static
memory_error_and_abort ()
{
fprintf (stderr, "history: Out of virtual memory!\n");
abort ();
}
#endif /* STATIC_MALLOC */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,108 @@
/* History.h -- the names of functions that you can call in history. */
typedef struct _hist_entry {
char *line;
char *data;
} HIST_ENTRY;
/* For convenience only. You set this when interpreting history commands.
It is the logical offset of the first history element. */
extern int history_base;
/* Begin a session in which the history functions might be used. This
just initializes the interactive variables. */
extern void using_history ();
/* Place STRING at the end of the history list.
The associated data field (if any) is set to NULL. */
extern void add_history ();
/* Returns the number which says what history element we are now
looking at. */
extern int where_history ();
/* Set the position in the history list to POS. */
int history_set_pos ();
/* Search for STRING in the history list, starting at POS, an
absolute index into the list. DIR, if negative, says to search
backwards from POS, else forwards.
Returns the absolute index of the history element where STRING
was found, or -1 otherwise. */
extern int history_search_pos ();
/* A reasonably useless function, only here for completeness. WHICH
is the magic number that tells us which element to delete. The
elements are numbered from 0. */
extern HIST_ENTRY *remove_history ();
/* Stifle the history list, remembering only MAX number of entries. */
extern void stifle_history ();
/* Stop stifling the history. This returns the previous amount the
history was stifled by. The value is positive if the history was
stifled, negative if it wasn't. */
extern int unstifle_history ();
/* Add the contents of FILENAME to the history list, a line at a time.
If FILENAME is NULL, then read from ~/.history. Returns 0 if
successful, or errno if not. */
extern int read_history ();
/* Append the current history to FILENAME. If FILENAME is NULL,
then append the history list to ~/.history. Values returned
are as in read_history (). */
extern int write_history ();
/* Make the history entry at WHICH have LINE and DATA. This returns
the old entry so you can dispose of the data. In the case of an
invalid WHICH, a NULL pointer is returned. */
extern HIST_ENTRY *replace_history_entry ();
/* Return the history entry at the current position, as determined by
history_offset. If there is no entry there, return a NULL pointer. */
HIST_ENTRY *current_history ();
/* Back up history_offset to the previous history entry, and return
a pointer to that entry. If there is no previous entry, return
a NULL pointer. */
extern HIST_ENTRY *previous_history ();
/* Move history_offset forward to the next item in the input_history,
and return the a pointer to that entry. If there is no next entry,
return a NULL pointer. */
extern HIST_ENTRY *next_history ();
/* Return a NULL terminated array of HIST_ENTRY which is the current input
history. Element 0 of this list is the beginning of time. If there
is no history, return NULL. */
extern HIST_ENTRY **history_list ();
/* Search the history for STRING, starting at history_offset.
If DIRECTION < 0, then the search is through previous entries,
else through subsequent. If the string is found, then
current_history () is the history entry, and the value of this function
is the offset in the line of that history entry that the string was
found in. Otherwise, nothing is changed, and a -1 is returned. */
extern int history_search ();
/* Expand the string STRING, placing the result into OUTPUT, a pointer
to a string. Returns:
0) If no expansions took place (or, if the only change in
the text was the de-slashifying of the history expansion
character)
1) If expansions did take place
-1) If there was an error in expansion.
If an error ocurred in expansion, then OUTPUT contains a descriptive
error message. */
extern int history_expand ();
/* Extract a string segment consisting of the FIRST through LAST
arguments present in STRING. Arguments are broken up as in
the shell. */
extern char *history_arg_extract ();

View file

@ -0,0 +1,172 @@
/* keymaps.c -- Functions and keymaps for the GNU Readline library. */
/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
This file is part of GNU Readline, a library for reading lines
of text with interactive input and history editing.
Readline is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 1, or (at your option) any
later version.
Readline is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with Readline; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "keymaps.h"
#include "emacs_keymap.c"
#ifdef VI_MODE
#include "vi_keymap.c"
#endif
/* Remove these declarations when we have a complete libgnu.a. */
#define STATIC_MALLOC
#ifndef STATIC_MALLOC
extern char *xmalloc (), *xrealloc ();
#else
static char *xmalloc (), *xrealloc ();
#endif
/* **************************************************************** */
/* */
/* Functions for manipulating Keymaps. */
/* */
/* **************************************************************** */
/* Return a new, empty keymap.
Free it with free() when you are done. */
Keymap
rl_make_bare_keymap ()
{
register int i;
Keymap keymap = (Keymap)xmalloc (128 * sizeof (KEYMAP_ENTRY));
for (i = 0; i < 128; i++)
{
keymap[i].type = ISFUNC;
keymap[i].function = (Function *)NULL;
}
for (i = 'A'; i < ('Z' + 1); i++)
{
keymap[i].type = ISFUNC;
keymap[i].function = rl_do_lowercase_version;
}
return (keymap);
}
/* Return a new keymap which is a copy of MAP. */
Keymap
rl_copy_keymap (map)
Keymap map;
{
register int i;
Keymap temp = rl_make_bare_keymap ();
for (i = 0; i < 128; i++)
{
temp[i].type = map[i].type;
temp[i].function = map[i].function;
}
return (temp);
}
/* Return a new keymap with the printing characters bound to rl_insert,
the uppercase Meta characters bound to run their lowercase equivalents,
and the Meta digits bound to produce numeric arguments. */
Keymap
rl_make_keymap ()
{
extern rl_insert (), rl_rubout (), rl_do_lowercase_version ();
extern rl_digit_argument ();
register int i;
Keymap newmap;
newmap = rl_make_bare_keymap ();
/* All printing characters are self-inserting. */
for (i = ' '; i < 126; i++)
newmap[i].function = rl_insert;
newmap[TAB].function = rl_insert;
newmap[RUBOUT].function = rl_rubout;
return (newmap);
}
/* Free the storage associated with MAP. */
rl_discard_keymap (map)
Keymap (map);
{
int i;
if (!map)
return;
for (i = 0; i < 128; i++)
{
switch (map[i].type)
{
case ISFUNC:
break;
case ISKMAP:
rl_discard_keymap ((Keymap)map[i].function);
break;
case ISMACR:
free ((char *)map[i].function);
break;
}
}
}
#ifdef STATIC_MALLOC
/* **************************************************************** */
/* */
/* xmalloc and xrealloc () */
/* */
/* **************************************************************** */
static char *
xmalloc (bytes)
int bytes;
{
static memory_error_and_abort ();
char *temp = (char *)malloc (bytes);
if (!temp)
memory_error_and_abort ();
return (temp);
}
static char *
xrealloc (pointer, bytes)
char *pointer;
int bytes;
{
static memory_error_and_abort ();
char *temp = (char *)realloc (pointer, bytes);
if (!temp)
memory_error_and_abort ();
return (temp);
}
static
memory_error_and_abort ()
{
fprintf (stderr, "readline: Out of virtual memory!\n");
abort ();
}
#endif /* STATIC_MALLOC */

View file

@ -0,0 +1,53 @@
/* keymaps.h -- Manipulation of readline keymaps. */
#ifndef _KEYMAPS_H_
#define _KEYMAPS_H_
#include <readline/chardefs.h>
#ifndef __FUNCTION_DEF
typedef int Function ();
#define __FUNCTION_DEF
#endif
/* A keymap contains one entry for each key in the ASCII set.
Each entry consists of a type and a pointer.
POINTER is the address of a function to run, or the
address of a keymap to indirect through.
TYPE says which kind of thing POINTER is. */
typedef struct _keymap_entry {
char type;
Function *function;
} KEYMAP_ENTRY;
/* I wanted to make the above structure contain a union of:
union { Function *function; struct _keymap_entry *keymap; } value;
but this made it impossible for me to create a static array.
Maybe I need C lessons. */
typedef KEYMAP_ENTRY KEYMAP_ENTRY_ARRAY[128];
typedef KEYMAP_ENTRY *Keymap;
/* The values that TYPE can have in a keymap entry. */
#define ISFUNC 0
#define ISKMAP 1
#define ISMACR 2
extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap, emacs_meta_keymap, emacs_ctlx_keymap;
extern KEYMAP_ENTRY_ARRAY vi_insertion_keymap, vi_movement_keymap;
/* Return a new, empty keymap.
Free it with free() when you are done. */
Keymap rl_make_bare_keymap ();
/* Return a new keymap which is a copy of MAP. */
Keymap rl_copy_keymap ();
/* Return a new keymap with the printing characters bound to rl_insert,
the lowercase Meta characters bound to run their equivalents, and
the Meta digits bound to produce numeric arguments. */
Keymap rl_make_keymap ();
#endif /* _KEYMAPS_H_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,161 @@
/* Readline.h -- the names of functions callable from within readline. */
#ifndef _READLINE_H_
#define _READLINE_H_
#include <readline/keymaps.h>
#ifndef __FUNCTION_DEF
typedef int Function ();
#define __FUNCTION_DEF
#endif
/* The functions for manipulating the text of the line within readline.
Most of these functions are bound to keys by default. */
extern int
rl_beg_of_line (), rl_backward (), rl_delete (), rl_end_of_line (),
rl_forward (), ding (), rl_backward (), rl_newline (), rl_kill_line (),
rl_clear_screen (), rl_get_next_history (), rl_get_previous_history (),
rl_quoted_insert (), rl_reverse_search_history (), rl_transpose_chars
(), rl_unix_line_discard (), rl_quoted_insert (), rl_unix_word_rubout
(), rl_yank (), rl_rubout (), rl_backward_word (), rl_kill_word (),
rl_forward_word (), rl_tab_insert (), rl_yank_pop (), rl_yank_nth_arg (),
rl_backward_kill_word (), rl_backward_kill_line (), rl_transpose_words
(), rl_complete (), rl_possible_completions (), rl_do_lowercase_version
(), rl_digit_argument (), rl_universal_argument (), rl_abort (),
rl_undo_command (), rl_revert_line (), rl_beginning_of_history (),
rl_end_of_history (), rl_forward_search_history (), rl_insert (),
rl_upcase_word (), rl_downcase_word (), rl_capitalize_word (),
rl_restart_output (), rl_re_read_init_file ();
/* These are *both* defined even when VI_MODE is not. */
extern int rl_vi_editing_mode (), rl_emacs_editing_mode ();
#ifdef VI_MODE
/* Things for vi mode. */
extern int rl_vi_movement_mode (), rl_vi_insertion_mode (), rl_vi_arg_digit (),
rl_vi_prev_word (), rl_vi_next_word (), rl_vi_char_search (),
rl_vi_eof_maybe (), rl_vi_append_mode (), rl_vi_put (),
rl_vi_append_eol (), rl_vi_insert_beg (), rl_vi_delete (), rl_vi_comment (),
rl_vi_first_print (), rl_vi_fword (), rl_vi_fWord (), rl_vi_bword (),
rl_vi_bWord (), rl_vi_eword (), rl_vi_eWord (), rl_vi_end_word (),
rl_vi_change_case (), rl_vi_match (), rl_vi_bracktype (), rl_vi_change_char (),
rl_vi_yank_arg (), rl_vi_search (), rl_vi_search_again (),
rl_vi_dosearch (), rl_vi_subst (), rl_vi_overstrike (),
rl_vi_overstrike_delete (), rl_vi_replace(), rl_vi_column (),
rl_vi_delete_to (), rl_vi_change_to (), rl_vi_yank_to (), rl_vi_complete ();
#endif /* VI_MODE */
/* Keyboard macro commands. */
extern int
rl_start_kbd_macro (), rl_end_kbd_macro (), rl_call_last_kbd_macro ();
/* Maintaining the state of undo. We remember individual deletes and inserts
on a chain of things to do. */
/* The actions that undo knows how to undo. Notice that UNDO_DELETE means
to insert some text, and UNDO_INSERT means to delete some text. I.e.,
the code tells undo what to undo, not how to undo it. */
enum undo_code { UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END };
/* What an element of THE_UNDO_LIST looks like. */
typedef struct undo_list {
struct undo_list *next;
int start, end; /* Where the change took place. */
char *text; /* The text to insert, if undoing a delete. */
enum undo_code what; /* Delete, Insert, Begin, End. */
} UNDO_LIST;
/* The current undo list for RL_LINE_BUFFER. */
extern UNDO_LIST *rl_undo_list;
/* The data structure for mapping textual names to code addresses. */
typedef struct {
char *name;
Function *function;
} FUNMAP;
extern FUNMAP **funmap;
/* **************************************************************** */
/* */
/* Well Published Variables */
/* */
/* **************************************************************** */
/* The name of the calling program. You should initialize this to
whatever was in argv[0]. It is used when parsing conditionals. */
extern char *rl_readline_name;
/* The line buffer that is in use. */
extern char *rl_line_buffer;
/* The location of point, and end. */
extern int rl_point, rl_end;
/* The name of the terminal to use. */
extern char *rl_terminal_name;
/* The input and output streams. */
extern FILE *rl_instream, *rl_outstream;
/* The basic list of characters that signal a break between words for the
completer routine. The contents of this variable is what breaks words
in the shell, i.e. "n\"\\'`@$>". */
extern char *rl_basic_word_break_characters;
/* The list of characters that signal a break between words for
rl_complete_internal. The default list is the contents of
rl_basic_word_break_characters. */
extern char *rl_completer_word_break_characters;
/* List of characters that are word break characters, but should be left
in TEXT when it is passed to the completion function. The shell uses
this to help determine what kind of completing to do. */
extern char *rl_special_prefixes;
/* Pointer to the generator function for completion_matches ().
NULL means to use filename_entry_function (), the default filename
completer. */
extern Function *rl_completion_entry_function;
/* Pointer to alternative function to create matches.
Function is called with TEXT, START, and END.
START and END are indices in RL_LINE_BUFFER saying what the boundaries
of TEXT are.
If this function exists and returns NULL then call the value of
rl_completion_entry_function to try to match, otherwise use the
array of strings returned. */
extern Function *rl_attempted_completion_function;
/* If non-null, this contains the address of a function to call if the
standard meaning for expanding a tilde fails. The function is called
with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
which is the expansion, or a NULL pointer if there is no expansion. */
extern Function *rl_tilde_expander;
/* If non-zero, then this is the address of a function to call just
before readline_internal () prints the first prompt. */
extern Function *rl_startup_hook;
/* **************************************************************** */
/* */
/* Well Published Functions */
/* */
/* **************************************************************** */
/* Read a line of input. Prompt with PROMPT. A NULL PROMPT means none. */
extern char *readline ();
/* Return an array of strings which are the result of repeatadly calling
FUNC with TEXT. */
extern char **completion_matches ();
/* rl_add_defun (char *name, Function *function, int key)
Add NAME to the list of named functions. Make FUNCTION
be the function that gets called.
If KEY is not -1, then bind it. */
extern int rl_add_defun ();
#endif /* _READLINE_H_ */

View file

@ -0,0 +1,484 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
* Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
*
* @(#)vi_keymap.c 6.4 (Berkeley) 5/8/91
*/
/* vi_keymap.c -- the keymap for vi_mode in readline (). */
/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
This file is part of GNU Readline, a library for reading lines
of text with interactive input and history editing.
Readline is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 1, or (at your option) any
later version.
Readline is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with Readline; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef FILE
#include <stdio.h>
#endif /* FILE */
#include "readline.h"
extern KEYMAP_ENTRY_ARRAY vi_escape_keymap;
/* The keymap arrays for handling vi mode. */
KEYMAP_ENTRY_ARRAY vi_movement_keymap = {
/* The regular control keys come first. */
{ ISFUNC, (Function *)0x0 }, /* Control-@ */
{ ISFUNC, (Function *)0x0 }, /* Control-a */
{ ISFUNC, (Function *)0x0 }, /* Control-b */
{ ISFUNC, (Function *)0x0 }, /* Control-c */
{ ISFUNC, rl_vi_eof_maybe }, /* Control-d */
{ ISFUNC, rl_emacs_editing_mode }, /* Control-e */
{ ISFUNC, (Function *)0x0 }, /* Control-f */
{ ISFUNC, rl_abort }, /* Control-g */
{ ISFUNC, rl_backward }, /* Control-h */
{ ISFUNC, (Function *)0x0 }, /* Control-i */
{ ISFUNC, rl_newline }, /* Control-j */
{ ISFUNC, rl_kill_line }, /* Control-k */
{ ISFUNC, rl_clear_screen }, /* Control-l */
{ ISFUNC, rl_newline }, /* Control-m */
{ ISFUNC, rl_get_next_history }, /* Control-n */
{ ISFUNC, (Function *)0x0 }, /* Control-o */
{ ISFUNC, rl_get_previous_history }, /* Control-p */
{ ISFUNC, rl_quoted_insert }, /* Control-q */
{ ISFUNC, rl_reverse_search_history }, /* Control-r */
{ ISFUNC, rl_forward_search_history }, /* Control-s */
{ ISFUNC, rl_transpose_chars }, /* Control-t */
{ ISFUNC, rl_unix_line_discard }, /* Control-u */
{ ISFUNC, rl_quoted_insert }, /* Control-v */
{ ISFUNC, rl_unix_word_rubout }, /* Control-w */
{ ISFUNC, (Function *)0x0 }, /* Control-x */
{ ISFUNC, rl_yank }, /* Control-y */
{ ISFUNC, (Function *)0x0 }, /* Control-z */
{ ISKMAP, (Function *)vi_escape_keymap }, /* Control-[ */
{ ISFUNC, (Function *)0x0 }, /* Control-\ */
{ ISFUNC, (Function *)0x0 }, /* Control-] */
{ ISFUNC, (Function *)0x0 }, /* Control-^ */
{ ISFUNC, rl_undo_command }, /* Control-_ */
/* The start of printing characters. */
{ ISFUNC, rl_forward }, /* SPACE */
{ ISFUNC, (Function *)0x0 }, /* ! */
{ ISFUNC, (Function *)0x0 }, /* " */
{ ISFUNC, rl_vi_comment }, /* # */
{ ISFUNC, rl_end_of_line }, /* $ */
{ ISFUNC, rl_vi_match }, /* % */
{ ISFUNC, (Function *)0x0 }, /* & */
{ ISFUNC, (Function *)0x0 }, /* ' */
{ ISFUNC, (Function *)0x0 }, /* ( */
{ ISFUNC, (Function *)0x0 }, /* ) */
{ ISFUNC, rl_vi_complete }, /* * */
{ ISFUNC, rl_get_previous_history}, /* + */
{ ISFUNC, rl_vi_char_search }, /* , */
{ ISFUNC, rl_get_next_history }, /* - */
{ ISFUNC, (Function *)0x0 }, /* . */
{ ISFUNC, rl_vi_search }, /* / */
/* Regular digits. */
{ ISFUNC, rl_vi_arg_digit }, /* 0 */
{ ISFUNC, rl_vi_arg_digit }, /* 1 */
{ ISFUNC, rl_vi_arg_digit }, /* 2 */
{ ISFUNC, rl_vi_arg_digit }, /* 3 */
{ ISFUNC, rl_vi_arg_digit }, /* 4 */
{ ISFUNC, rl_vi_arg_digit }, /* 5 */
{ ISFUNC, rl_vi_arg_digit }, /* 6 */
{ ISFUNC, rl_vi_arg_digit }, /* 7 */
{ ISFUNC, rl_vi_arg_digit }, /* 8 */
{ ISFUNC, rl_vi_arg_digit }, /* 9 */
/* A little more punctuation. */
{ ISFUNC, (Function *)0x0 }, /* : */
{ ISFUNC, rl_vi_char_search }, /* ; */
{ ISFUNC, (Function *)0x0 }, /* < */
{ ISFUNC, (Function *)0x0 }, /* = */
{ ISFUNC, (Function *)0x0 }, /* > */
{ ISFUNC, rl_vi_search }, /* ? */
{ ISFUNC, (Function *)0x0 }, /* @ */
/* Uppercase alphabet. */
{ ISFUNC, rl_vi_append_eol }, /* A */
{ ISFUNC, rl_vi_prev_word}, /* B */
{ ISFUNC, rl_vi_change_to }, /* C */
{ ISFUNC, rl_vi_delete_to }, /* D */
{ ISFUNC, rl_vi_end_word }, /* E */
{ ISFUNC, rl_vi_char_search }, /* F */
{ ISFUNC, (Function *)0x0 }, /* G */
{ ISFUNC, (Function *)0x0 }, /* H */
{ ISFUNC, rl_vi_insert_beg }, /* I */
{ ISFUNC, (Function *)0x0 }, /* J */
{ ISFUNC, (Function *)0x0 }, /* K */
{ ISFUNC, (Function *)0x0 }, /* L */
{ ISFUNC, (Function *)0x0 }, /* M */
{ ISFUNC, rl_vi_search_again }, /* N */
{ ISFUNC, (Function *)0x0 }, /* O */
{ ISFUNC, rl_vi_put }, /* P */
{ ISFUNC, (Function *)0x0 }, /* Q */
{ ISFUNC, rl_vi_replace }, /* R */
{ ISFUNC, rl_vi_subst }, /* S */
{ ISFUNC, rl_vi_char_search }, /* T */
{ ISFUNC, rl_revert_line }, /* U */
{ ISFUNC, (Function *)0x0 }, /* V */
{ ISFUNC, rl_vi_next_word }, /* W */
{ ISFUNC, rl_rubout }, /* X */
{ ISFUNC, rl_vi_yank_to }, /* Y */
{ ISFUNC, (Function *)0x0 }, /* Z */
/* Some more punctuation. */
{ ISFUNC, (Function *)0x0 }, /* [ */
{ ISFUNC, (Function *)0x0 }, /* \ */
{ ISFUNC, (Function *)0x0 }, /* ] */
{ ISFUNC, rl_vi_first_print }, /* ^ */
{ ISFUNC, rl_vi_yank_arg }, /* _ */
{ ISFUNC, (Function *)0x0 }, /* ` */
/* Lowercase alphabet. */
{ ISFUNC, rl_vi_append_mode }, /* a */
{ ISFUNC, rl_vi_prev_word }, /* b */
{ ISFUNC, rl_vi_change_to }, /* c */
{ ISFUNC, rl_vi_delete_to }, /* d */
{ ISFUNC, rl_vi_end_word }, /* e */
{ ISFUNC, rl_vi_char_search }, /* f */
{ ISFUNC, (Function *)0x0 }, /* g */
{ ISFUNC, rl_backward }, /* h */
{ ISFUNC, rl_vi_insertion_mode }, /* i */
{ ISFUNC, rl_get_next_history }, /* j */
{ ISFUNC, rl_get_previous_history }, /* k */
{ ISFUNC, rl_forward }, /* l */
{ ISFUNC, (Function *)0x0 }, /* m */
{ ISFUNC, rl_vi_search_again }, /* n */
{ ISFUNC, (Function *)0x0 }, /* o */
{ ISFUNC, rl_vi_put }, /* p */
{ ISFUNC, (Function *)0x0 }, /* q */
{ ISFUNC, rl_vi_change_char }, /* r */
{ ISFUNC, rl_vi_subst }, /* s */
{ ISFUNC, rl_vi_char_search }, /* t */
{ ISFUNC, rl_undo_command }, /* u */
{ ISFUNC, (Function *)0x0 }, /* v */
{ ISFUNC, rl_vi_next_word }, /* w */
{ ISFUNC, rl_vi_delete }, /* x */
{ ISFUNC, rl_vi_yank_to }, /* y */
{ ISFUNC, (Function *)0x0 }, /* z */
/* Final punctuation. */
{ ISFUNC, (Function *)0x0 }, /* { */
{ ISFUNC, rl_vi_column }, /* | */
{ ISFUNC, (Function *)0x0 }, /* } */
{ ISFUNC, rl_vi_change_case }, /* ~ */
{ ISFUNC, rl_backward } /* RUBOUT */
};
KEYMAP_ENTRY_ARRAY vi_insertion_keymap = {
/* The regular control keys come first. */
{ ISFUNC, (Function *)0x0 }, /* Control-@ */
{ ISFUNC, rl_insert }, /* Control-a */
{ ISFUNC, rl_insert }, /* Control-b */
{ ISFUNC, rl_insert }, /* Control-c */
{ ISFUNC, rl_vi_eof_maybe }, /* Control-d */
{ ISFUNC, rl_insert }, /* Control-e */
{ ISFUNC, rl_insert }, /* Control-f */
{ ISFUNC, rl_insert }, /* Control-g */
{ ISFUNC, rl_rubout }, /* Control-h */
{ ISFUNC, rl_complete }, /* Control-i */
{ ISFUNC, rl_newline }, /* Control-j */
{ ISFUNC, rl_insert }, /* Control-k */
{ ISFUNC, rl_insert }, /* Control-l */
{ ISFUNC, rl_newline }, /* Control-m */
{ ISFUNC, rl_insert }, /* Control-n */
{ ISFUNC, rl_insert }, /* Control-o */
{ ISFUNC, rl_insert }, /* Control-p */
{ ISFUNC, rl_insert }, /* Control-q */
{ ISFUNC, rl_reverse_search_history }, /* Control-r */
{ ISFUNC, rl_forward_search_history }, /* Control-s */
{ ISFUNC, rl_transpose_chars }, /* Control-t */
{ ISFUNC, rl_unix_line_discard }, /* Control-u */
{ ISFUNC, rl_quoted_insert }, /* Control-v */
{ ISFUNC, rl_unix_word_rubout }, /* Control-w */
{ ISFUNC, rl_insert }, /* Control-x */
{ ISFUNC, rl_yank }, /* Control-y */
{ ISFUNC, rl_insert }, /* Control-z */
{ ISFUNC, rl_vi_movement_mode }, /* Control-[ */
{ ISFUNC, rl_insert }, /* Control-\ */
{ ISFUNC, rl_insert }, /* Control-] */
{ ISFUNC, rl_insert }, /* Control-^ */
{ ISFUNC, rl_undo_command }, /* Control-_ */
/* The start of printing characters. */
{ ISFUNC, rl_insert }, /* SPACE */
{ ISFUNC, rl_insert }, /* ! */
{ ISFUNC, rl_insert }, /* " */
{ ISFUNC, rl_insert }, /* # */
{ ISFUNC, rl_insert }, /* $ */
{ ISFUNC, rl_insert }, /* % */
{ ISFUNC, rl_insert }, /* & */
{ ISFUNC, rl_insert }, /* ' */
{ ISFUNC, rl_insert }, /* ( */
{ ISFUNC, rl_insert }, /* ) */
{ ISFUNC, rl_insert }, /* * */
{ ISFUNC, rl_insert }, /* + */
{ ISFUNC, rl_insert }, /* , */
{ ISFUNC, rl_insert }, /* - */
{ ISFUNC, rl_insert }, /* . */
{ ISFUNC, rl_insert }, /* / */
/* Regular digits. */
{ ISFUNC, rl_insert }, /* 0 */
{ ISFUNC, rl_insert }, /* 1 */
{ ISFUNC, rl_insert }, /* 2 */
{ ISFUNC, rl_insert }, /* 3 */
{ ISFUNC, rl_insert }, /* 4 */
{ ISFUNC, rl_insert }, /* 5 */
{ ISFUNC, rl_insert }, /* 6 */
{ ISFUNC, rl_insert }, /* 7 */
{ ISFUNC, rl_insert }, /* 8 */
{ ISFUNC, rl_insert }, /* 9 */
/* A little more punctuation. */
{ ISFUNC, rl_insert }, /* : */
{ ISFUNC, rl_insert }, /* ; */
{ ISFUNC, rl_insert }, /* < */
{ ISFUNC, rl_insert }, /* = */
{ ISFUNC, rl_insert }, /* > */
{ ISFUNC, rl_insert }, /* ? */
{ ISFUNC, rl_insert }, /* @ */
/* Uppercase alphabet. */
{ ISFUNC, rl_insert }, /* A */
{ ISFUNC, rl_insert }, /* B */
{ ISFUNC, rl_insert }, /* C */
{ ISFUNC, rl_insert }, /* D */
{ ISFUNC, rl_insert }, /* E */
{ ISFUNC, rl_insert }, /* F */
{ ISFUNC, rl_insert }, /* G */
{ ISFUNC, rl_insert }, /* H */
{ ISFUNC, rl_insert }, /* I */
{ ISFUNC, rl_insert }, /* J */
{ ISFUNC, rl_insert }, /* K */
{ ISFUNC, rl_insert }, /* L */
{ ISFUNC, rl_insert }, /* M */
{ ISFUNC, rl_insert }, /* N */
{ ISFUNC, rl_insert }, /* O */
{ ISFUNC, rl_insert }, /* P */
{ ISFUNC, rl_insert }, /* Q */
{ ISFUNC, rl_insert }, /* R */
{ ISFUNC, rl_insert }, /* S */
{ ISFUNC, rl_insert }, /* T */
{ ISFUNC, rl_insert }, /* U */
{ ISFUNC, rl_insert }, /* V */
{ ISFUNC, rl_insert }, /* W */
{ ISFUNC, rl_insert }, /* X */
{ ISFUNC, rl_insert }, /* Y */
{ ISFUNC, rl_insert }, /* Z */
/* Some more punctuation. */
{ ISFUNC, rl_insert }, /* [ */
{ ISFUNC, rl_insert }, /* \ */
{ ISFUNC, rl_insert }, /* ] */
{ ISFUNC, rl_insert }, /* ^ */
{ ISFUNC, rl_insert }, /* _ */
{ ISFUNC, rl_insert }, /* ` */
/* Lowercase alphabet. */
{ ISFUNC, rl_insert }, /* a */
{ ISFUNC, rl_insert }, /* b */
{ ISFUNC, rl_insert }, /* c */
{ ISFUNC, rl_insert }, /* d */
{ ISFUNC, rl_insert }, /* e */
{ ISFUNC, rl_insert }, /* f */
{ ISFUNC, rl_insert }, /* g */
{ ISFUNC, rl_insert }, /* h */
{ ISFUNC, rl_insert }, /* i */
{ ISFUNC, rl_insert }, /* j */
{ ISFUNC, rl_insert }, /* k */
{ ISFUNC, rl_insert }, /* l */
{ ISFUNC, rl_insert }, /* m */
{ ISFUNC, rl_insert }, /* n */
{ ISFUNC, rl_insert }, /* o */
{ ISFUNC, rl_insert }, /* p */
{ ISFUNC, rl_insert }, /* q */
{ ISFUNC, rl_insert }, /* r */
{ ISFUNC, rl_insert }, /* s */
{ ISFUNC, rl_insert }, /* t */
{ ISFUNC, rl_insert }, /* u */
{ ISFUNC, rl_insert }, /* v */
{ ISFUNC, rl_insert }, /* w */
{ ISFUNC, rl_insert }, /* x */
{ ISFUNC, rl_insert }, /* y */
{ ISFUNC, rl_insert }, /* z */
/* Final punctuation. */
{ ISFUNC, rl_insert }, /* { */
{ ISFUNC, rl_insert }, /* | */
{ ISFUNC, rl_insert }, /* } */
{ ISFUNC, rl_insert }, /* ~ */
{ ISFUNC, rl_rubout } /* RUBOUT */
};
KEYMAP_ENTRY_ARRAY vi_escape_keymap = {
/* The regular control keys come first. */
{ ISFUNC, (Function *)0x0 }, /* Control-@ */
{ ISFUNC, (Function *)0x0 }, /* Control-a */
{ ISFUNC, (Function *)0x0 }, /* Control-b */
{ ISFUNC, (Function *)0x0 }, /* Control-c */
{ ISFUNC, (Function *)0x0 }, /* Control-d */
{ ISFUNC, (Function *)0x0 }, /* Control-e */
{ ISFUNC, (Function *)0x0 }, /* Control-f */
{ ISFUNC, (Function *)0x0 }, /* Control-g */
{ ISFUNC, (Function *)0x0 }, /* Control-h */
{ ISFUNC, rl_tab_insert}, /* Control-i */
{ ISFUNC, rl_emacs_editing_mode}, /* Control-j */
{ ISFUNC, rl_kill_line }, /* Control-k */
{ ISFUNC, (Function *)0x0 }, /* Control-l */
{ ISFUNC, rl_emacs_editing_mode}, /* Control-m */
{ ISFUNC, (Function *)0x0 }, /* Control-n */
{ ISFUNC, (Function *)0x0 }, /* Control-o */
{ ISFUNC, (Function *)0x0 }, /* Control-p */
{ ISFUNC, (Function *)0x0 }, /* Control-q */
{ ISFUNC, (Function *)0x0 }, /* Control-r */
{ ISFUNC, (Function *)0x0 }, /* Control-s */
{ ISFUNC, (Function *)0x0 }, /* Control-t */
{ ISFUNC, (Function *)0x0 }, /* Control-u */
{ ISFUNC, (Function *)0x0 }, /* Control-v */
{ ISFUNC, (Function *)0x0 }, /* Control-w */
{ ISFUNC, (Function *)0x0 }, /* Control-x */
{ ISFUNC, (Function *)0x0 }, /* Control-y */
{ ISFUNC, (Function *)0x0 }, /* Control-z */
{ ISFUNC, rl_vi_movement_mode }, /* Control-[ */
{ ISFUNC, (Function *)0x0 }, /* Control-\ */
{ ISFUNC, (Function *)0x0 }, /* Control-] */
{ ISFUNC, (Function *)0x0 }, /* Control-^ */
{ ISFUNC, rl_undo_command }, /* Control-_ */
/* The start of printing characters. */
{ ISFUNC, (Function *)0x0 }, /* SPACE */
{ ISFUNC, (Function *)0x0 }, /* ! */
{ ISFUNC, (Function *)0x0 }, /* " */
{ ISFUNC, (Function *)0x0 }, /* # */
{ ISFUNC, (Function *)0x0 }, /* $ */
{ ISFUNC, (Function *)0x0 }, /* % */
{ ISFUNC, (Function *)0x0 }, /* & */
{ ISFUNC, (Function *)0x0 }, /* ' */
{ ISFUNC, (Function *)0x0 }, /* ( */
{ ISFUNC, (Function *)0x0 }, /* ) */
{ ISFUNC, (Function *)0x0 }, /* * */
{ ISFUNC, (Function *)0x0 }, /* + */
{ ISFUNC, (Function *)0x0 }, /* , */
{ ISFUNC, (Function *)0x0 }, /* - */
{ ISFUNC, (Function *)0x0 }, /* . */
{ ISFUNC, (Function *)0x0 }, /* / */
/* Regular digits. */
{ ISFUNC, rl_vi_arg_digit }, /* 0 */
{ ISFUNC, rl_vi_arg_digit }, /* 1 */
{ ISFUNC, rl_vi_arg_digit }, /* 2 */
{ ISFUNC, rl_vi_arg_digit }, /* 3 */
{ ISFUNC, rl_vi_arg_digit }, /* 4 */
{ ISFUNC, rl_vi_arg_digit }, /* 5 */
{ ISFUNC, rl_vi_arg_digit }, /* 6 */
{ ISFUNC, rl_vi_arg_digit }, /* 7 */
{ ISFUNC, rl_vi_arg_digit }, /* 8 */
{ ISFUNC, rl_vi_arg_digit }, /* 9 */
/* A little more punctuation. */
{ ISFUNC, (Function *)0x0 }, /* : */
{ ISFUNC, (Function *)0x0 }, /* ; */
{ ISFUNC, (Function *)0x0 }, /* < */
{ ISFUNC, (Function *)0x0 }, /* = */
{ ISFUNC, (Function *)0x0 }, /* > */
{ ISFUNC, (Function *)0x0 }, /* ? */
{ ISFUNC, (Function *)0x0 }, /* @ */
/* Uppercase alphabet. */
{ ISFUNC, rl_do_lowercase_version }, /* A */
{ ISFUNC, rl_do_lowercase_version }, /* B */
{ ISFUNC, rl_do_lowercase_version }, /* C */
{ ISFUNC, rl_do_lowercase_version }, /* D */
{ ISFUNC, rl_do_lowercase_version }, /* E */
{ ISFUNC, rl_do_lowercase_version }, /* F */
{ ISFUNC, rl_do_lowercase_version }, /* G */
{ ISFUNC, rl_do_lowercase_version }, /* H */
{ ISFUNC, rl_do_lowercase_version }, /* I */
{ ISFUNC, rl_do_lowercase_version }, /* J */
{ ISFUNC, rl_do_lowercase_version }, /* K */
{ ISFUNC, rl_do_lowercase_version }, /* L */
{ ISFUNC, rl_do_lowercase_version }, /* M */
{ ISFUNC, rl_do_lowercase_version }, /* N */
{ ISFUNC, rl_do_lowercase_version }, /* O */
{ ISFUNC, rl_do_lowercase_version }, /* P */
{ ISFUNC, rl_do_lowercase_version }, /* Q */
{ ISFUNC, rl_do_lowercase_version }, /* R */
{ ISFUNC, rl_do_lowercase_version }, /* S */
{ ISFUNC, rl_do_lowercase_version }, /* T */
{ ISFUNC, rl_do_lowercase_version }, /* U */
{ ISFUNC, rl_do_lowercase_version }, /* V */
{ ISFUNC, rl_do_lowercase_version }, /* W */
{ ISFUNC, rl_do_lowercase_version }, /* X */
{ ISFUNC, rl_do_lowercase_version }, /* Y */
{ ISFUNC, rl_do_lowercase_version }, /* Z */
/* Some more punctuation. */
{ ISFUNC, (Function *)0x0 }, /* [ */
{ ISFUNC, (Function *)0x0 }, /* \ */
{ ISFUNC, (Function *)0x0 }, /* ] */
{ ISFUNC, (Function *)0x0 }, /* ^ */
{ ISFUNC, (Function *)0x0 }, /* _ */
{ ISFUNC, (Function *)0x0 }, /* ` */
/* Lowercase alphabet. */
{ ISFUNC, (Function *)0x0 }, /* a */
{ ISFUNC, (Function *)0x0 }, /* b */
{ ISFUNC, (Function *)0x0 }, /* c */
{ ISFUNC, (Function *)0x0 }, /* d */
{ ISFUNC, (Function *)0x0 }, /* e */
{ ISFUNC, (Function *)0x0 }, /* f */
{ ISFUNC, (Function *)0x0 }, /* g */
{ ISFUNC, (Function *)0x0 }, /* h */
{ ISFUNC, (Function *)0x0 }, /* i */
{ ISFUNC, (Function *)0x0 }, /* j */
{ ISFUNC, (Function *)0x0 }, /* k */
{ ISFUNC, (Function *)0x0 }, /* l */
{ ISFUNC, (Function *)0x0 }, /* m */
{ ISFUNC, (Function *)0x0 }, /* n */
{ ISFUNC, (Function *)0x0 }, /* o */
{ ISFUNC, (Function *)0x0 }, /* p */
{ ISFUNC, (Function *)0x0 }, /* q */
{ ISFUNC, (Function *)0x0 }, /* r */
{ ISFUNC, (Function *)0x0 }, /* s */
{ ISFUNC, (Function *)0x0 }, /* t */
{ ISFUNC, (Function *)0x0 }, /* u */
{ ISFUNC, (Function *)0x0 }, /* v */
{ ISFUNC, (Function *)0x0 }, /* w */
{ ISFUNC, (Function *)0x0 }, /* x */
{ ISFUNC, (Function *)0x0 }, /* y */
{ ISFUNC, (Function *)0x0 }, /* z */
/* Final punctuation. */
{ ISFUNC, (Function *)0x0 }, /* { */
{ ISFUNC, (Function *)0x0 }, /* | */
{ ISFUNC, (Function *)0x0 }, /* } */
{ ISFUNC, (Function *)0x0 }, /* ~ */
{ ISFUNC, rl_backward_kill_word } /* RUBOUT */
};

View file

@ -0,0 +1,875 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
* Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
*
* @(#)vi_mode.c 6.4 (Berkeley) 5/8/91
*/
/* vi_mode.c -- A vi emulation mode for Bash.
Mostly written by Jeff Sparkes (jeff1@????).
*/
/* **************************************************************** */
/* */
/* VI Emulation Mode */
/* */
/* **************************************************************** */
/* Last string searched for from `/' or `?'. */
static char *vi_last_search = (char *)NULL;
static int vi_histpos;
/* *** UNCLEAN *** */
/* Command keys which do movement for xxx_to commands. */
static char *vi_motion = " hl^$0ftFt;,%wbeWBE|";
/* Keymap used for vi replace characters. Created dynamically since
rarely used. */
static Keymap vi_replace_map = (Keymap)NULL;
/* The number of characters inserted in the last replace operation. */
static vi_replace_count = 0;
/* Yank the nth arg from the previous line into this line at point. */
rl_vi_yank_arg (count)
int count;
{
rl_yank_nth_arg (count);
}
/* Search again for the last thing searched for. */
rl_vi_search_again (ignore, key)
int ignore, key;
{
switch (key)
{
case 'n':
rl_vi_dosearch (vi_last_search, -1);
break;
case 'N':
rl_vi_dosearch (vi_last_search, 1);
break;
}
}
/* Do a vi style search. */
rl_vi_search (count, key)
int count, key;
{
int dir, c;
char *p;
switch (key)
{
case '?':
dir = 1;
break;
case '/':
dir = -1;
break;
default:
ding ();
return;
}
vi_histpos = where_history ();
maybe_save_line ();
/* Reuse the line input buffer to read the search string. */
the_line[0] = 0;
rl_end = rl_point = 0;
p = (char *)alloca (2 + (rl_prompt ? strlen (rl_prompt) : 0));
sprintf (p, "%s%c", rl_prompt ? rl_prompt : "", key);
rl_message (p);
while (c = rl_read_key (in_stream))
{
switch (c)
{
case CTRL('W'):
case CTRL('U'):
case CTRL('H'):
case RUBOUT:
rl_dispatch (c, keymap);
break;
case ESC:
case RETURN:
case NEWLINE:
goto dosearch;
break;
case CTRL('C'):
maybe_unsave_line ();
rl_clear_message ();
rl_point = 0;
ding ();
return;
default:
rl_insert (1, c);
break;
}
rl_redisplay ();
}
dosearch:
if (vi_last_search)
free (vi_last_search);
vi_last_search = savestring (the_line);
rl_vi_dosearch (the_line, dir);
}
rl_vi_dosearch (string, dir)
char *string;
int dir;
{
int old, save = vi_histpos;
HIST_ENTRY *h;
if (string == 0 || *string == 0 || vi_histpos < 0)
{
ding ();
return;
}
if ((save = history_search_pos (string, dir, vi_histpos + dir)) == -1)
{
maybe_unsave_line ();
rl_clear_message ();
rl_point = 0;
ding ();
return;
}
vi_histpos = save;
old = where_history ();
history_set_pos (vi_histpos);
h = current_history ();
history_set_pos (old);
strcpy (the_line, h->line);
rl_undo_list = (UNDO_LIST *)h->data;
rl_end = strlen (the_line);
rl_point = 0;
rl_clear_message ();
}
/* Completion, from vi's point of view. */
rl_vi_complete (ignore, key)
int ignore, key;
{
if (!whitespace (the_line[rl_point]))
{
rl_vi_end_word (1, 'E');
rl_point++;
}
rl_complete_internal ('*');
rl_vi_insertion_mode ();
}
/* Previous word in vi mode. */
rl_vi_prev_word (count, key)
int count, key;
{
if (count < 0)
{
rl_vi_next_word (-count, key);
return;
}
if (uppercase_p (key))
rl_vi_bWord (count);
else
rl_vi_bword (count);
}
/* Next word in vi mode. */
rl_vi_next_word (count, key)
int count;
{
if (count < 0)
{
rl_vi_prev_word (-count, key);
return;
}
if (uppercase_p (key))
rl_vi_fWord (count);
else
rl_vi_fword (count);
}
/* Move to the end of the ?next? word. */
rl_vi_end_word (count, key)
int count, key;
{
if (count < 0)
{
ding ();
return;
}
if (uppercase_p (key))
rl_vi_eWord (count);
else
rl_vi_eword (count);
}
/* Move forward a word the way that 'W' does. */
rl_vi_fWord (count)
int count;
{
while (count-- && rl_point < (rl_end - 1))
{
/* Skip until whitespace. */
while (!whitespace (the_line[rl_point]) && rl_point < rl_end)
rl_point++;
/* Now skip whitespace. */
while (whitespace (the_line[rl_point]) && rl_point < rl_end)
rl_point++;
}
}
rl_vi_bWord (count)
int count;
{
while (count-- && rl_point > 0)
{
while (rl_point-- >= 0 && whitespace (the_line[rl_point]));
while (rl_point >= 0 && !whitespace (the_line[rl_point]))
rl_point--;
rl_point++;
}
}
rl_vi_eWord (count)
int count;
{
while (count -- && rl_point < (rl_end - 1))
{
while (rl_point++ < rl_end && whitespace (the_line[rl_point]));
while (rl_point++ < rl_end && !whitespace (the_line[rl_point]));
rl_point--;
}
}
rl_vi_fword (count)
int count;
{
while (count -- && rl_point < (rl_end - 1))
{
if (isident (the_line[rl_point]))
{
while (isident (the_line[rl_point]) && rl_point < rl_end)
rl_point += 1;
}
else if (!whitespace (the_line[rl_point]))
{
while (!isident (the_line[rl_point]) &&
!whitespace (the_line[rl_point]) && rl_point < rl_end)
rl_point += 1;
}
while (whitespace (the_line[rl_point]) && rl_point < rl_end)
rl_point++;
}
}
rl_vi_bword (count)
int count;
{
while (count -- && rl_point > 0)
{
while (--rl_point > 0 && whitespace (the_line[rl_point]));
if (rl_point > 0)
{
if (isident (the_line[rl_point]))
while (--rl_point >= 0 && isident (the_line[rl_point]));
else
while (--rl_point >= 0 && !isident (the_line[rl_point]) &&
!whitespace (the_line[rl_point]));
rl_point++;
}
}
}
rl_vi_eword (count)
int count;
{
while (count -- && rl_point < rl_end - 1)
{
while (++rl_point < rl_end && whitespace (the_line[rl_point]));
if (rl_point < rl_end)
{
if (isident (the_line[rl_point]))
while (++rl_point < rl_end && isident (the_line[rl_point]));
else
while (++rl_point < rl_end && !isident (the_line[rl_point])
&& !whitespace (the_line[rl_point]));
rl_point--;
}
}
}
rl_vi_insert_beg ()
{
rl_beg_of_line ();
rl_vi_insertion_mode ();
return 0;
}
rl_vi_append_mode ()
{
if (rl_point < rl_end)
rl_point += 1;
rl_vi_insertion_mode ();
return 0;
}
rl_vi_append_eol ()
{
rl_end_of_line ();
rl_vi_append_mode ();
return 0;
}
/* What to do in the case of C-d. */
rl_vi_eof_maybe (count, c)
int count, c;
{
rl_newline (1, '\n');
}
/* Insertion mode stuff. */
/* Switching from one mode to the other really just involves
switching keymaps. */
rl_vi_insertion_mode ()
{
keymap = vi_insertion_keymap;
}
rl_vi_movement_mode ()
{
if (rl_point > 0)
rl_backward (1);
keymap = vi_movement_keymap;
if (vi_doing_insert)
{
rl_end_undo_group ();
vi_doing_insert = 0;
}
}
rl_vi_arg_digit (count, c)
int count, c;
{
if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
rl_beg_of_line ();
else
rl_digit_argument (count, c);
}
/* Doesn't take an arg count in vi */
rl_vi_change_case (ignore1, ignore2)
int ignore1, ignore2;
{
char c = 0;
if (uppercase_p (the_line[rl_point]))
c = to_lower (the_line[rl_point]);
else if (lowercase_p (the_line[rl_point]))
c = to_upper (the_line[rl_point]);
/* Vi is kind of strange here. */
if (c)
{
rl_begin_undo_group ();
rl_delete (1);
rl_insert (1, c);
rl_end_undo_group ();
rl_vi_check ();
}
else
rl_forward (1);
}
rl_vi_put (count, key)
int count, key;
{
if (!uppercase_p (key))
{
if(rl_point != rl_end)
rl_point++;
}
rl_yank ();
rl_backward (1);
}
rl_vi_check ()
{
if (rl_point && rl_point == rl_end)
rl_point--;
}
rl_vi_column (count)
{
if (count > rl_end)
rl_end_of_line ();
else
rl_point = count - 1;
}
int
rl_vi_domove ()
{
int c, save;
rl_mark = rl_point;
c = rl_read_key (in_stream);
if (!member (c, vi_motion))
{
if (digit (c))
{
save = rl_numeric_arg;
rl_digit_loop1 ();
rl_numeric_arg *= save;
}
else
return (-1);
}
rl_dispatch (c, keymap);
/* No change in position means the command failed. */
if (rl_mark == rl_point)
return (-1);
if ((c == 'w' || c == 'W') && rl_point < rl_end)
{
rl_point--;
while((rl_point > 0) && whitespace (the_line[rl_point]))
rl_point--;
rl_point++;
}
if (rl_mark < rl_point)
exchange (rl_point, rl_mark);
return (0);
}
/* A simplified loop for vi. Don't dispatch key at end.
Don't recognize minus sign? */
rl_digit_loop1 ()
{
int key, c;
while (1)
{
rl_message ("(arg: %d) ", arg_sign * rl_numeric_arg);
key = c = rl_read_key ();
if (keymap[c].type == ISFUNC &&
keymap[c].function == rl_universal_argument)
{
rl_numeric_arg *= 4;
continue;
}
c = UNMETA (c);
if (numeric (c))
{
if (rl_explicit_arg)
rl_numeric_arg = (rl_numeric_arg * 10) + (c - '0');
else
rl_numeric_arg = (c - '0');
rl_explicit_arg = 1;
}
else
{
rl_clear_message ();
rl_stuff_char (key);
}
}
}
rl_vi_delete_to (count, key)
int count, key;
{
if (uppercase_p (key))
rl_stuff_char ('$');
if (rl_vi_domove ())
{
ding ();
return;
}
rl_kill_text (rl_point, rl_mark);
}
rl_vi_change_to (count, key)
int count, key;
{
if (uppercase_p (key))
rl_stuff_char ('$');
if (rl_vi_domove ())
{
ding ();
return;
}
rl_begin_undo_group ();
vi_doing_insert = 1;
rl_kill_text (rl_point, rl_mark);
rl_vi_insertion_mode ();
}
rl_vi_yank_to (count, key)
int count, key;
{
int save = rl_point;
if (uppercase_p (key))
rl_stuff_char ('$');
if (rl_vi_domove ())
{
ding ();
return;
}
rl_begin_undo_group ();
rl_kill_text (rl_point, rl_mark);
rl_end_undo_group ();
rl_do_undo ();
rl_point = save;
}
rl_vi_delete (count)
{
if (rl_point >= rl_end - 1)
{
rl_delete (count);
if (rl_point > 0)
rl_backward (1);
}
else
rl_delete (count);
}
/* Turn the current line into a comment in shell history. A ksh function */
rl_vi_comment ()
{
rl_beg_of_line ();
rl_insert_text (": "); /* # doesn't work in interactive mode */
rl_redisplay ();
rl_newline (1, '\010');
}
rl_vi_first_print ()
{
rl_back_to_indent ();
}
rl_back_to_indent (ignore1, ignore2)
int ignore1, ignore2;
{
rl_beg_of_line ();
while (rl_point < rl_end && whitespace (the_line[rl_point]))
rl_point++;
}
/* NOTE: it is necessary that opposite directions are inverses */
#define FTO 1 /* forward to */
#define BTO -1 /* backward to */
#define FFIND 2 /* forward find */
#define BFIND -2 /* backward find */
rl_vi_char_search (count, key)
int count, key;
{
static char target;
static int orig_dir, dir;
int pos;
if (key == ';' || key == ',')
dir = (key == ';' ? orig_dir : -orig_dir);
else
{
target = rl_read_key();
switch (key)
{
case 't':
orig_dir = dir = FTO;
break;
case 'T':
orig_dir = dir = BTO;
break;
case 'f':
orig_dir = dir = FFIND;
break;
case 'F':
orig_dir = dir = BFIND;
break;
}
}
pos = rl_point;
if (dir < 0)
{
pos--;
do
{
if (the_line[pos] == target)
{
if (dir == BTO)
rl_point = pos + 1;
else
rl_point = pos;
return;
}
}
while (pos--);
if (pos < 0)
{
ding ();
return;
}
}
else
{ /* dir > 0 */
pos++;
do
{
if (the_line[pos] == target)
{
if (dir == FTO)
rl_point = pos - 1;
else
rl_point = pos;
return;
}
}
while (++pos < rl_end);
if (pos >= (rl_end - 1))
ding ();
}
}
/* Match brackets */
rl_vi_match ()
{
int count = 1, brack, pos;
pos = rl_point;
if ((brack = rl_vi_bracktype (the_line[rl_point])) == 0)
{
while ((brack = rl_vi_bracktype (the_line[rl_point])) == 0 &&
rl_point < rl_end - 1)
rl_forward (1);
if (brack <= 0)
{
rl_point = pos;
ding ();
return;
}
}
pos = rl_point;
if (brack < 0)
{
while (count)
{
if (--pos >= 0)
{
int b = rl_vi_bracktype (the_line[pos]);
if (b == -brack)
count--;
else if (b == brack)
count++;
}
else
{
ding ();
return;
}
}
}
else
{ /* brack > 0 */
while (count)
{
if (++pos < rl_end)
{
int b = rl_vi_bracktype (the_line[pos]);
if (b == -brack)
count--;
else if (b == brack)
count++;
}
else
{
ding ();
return;
}
}
}
rl_point = pos;
}
int
rl_vi_bracktype (c)
int c;
{
switch (c)
{
case '(': return 1;
case ')': return -1;
case '[': return 2;
case ']': return -2;
case '{': return 3;
case '}': return -3;
default: return 0;
}
}
rl_vi_change_char ()
{
int c;
c = rl_read_key();
switch (c)
{
case '\033':
case CTRL('C'):
return;
default:
rl_begin_undo_group ();
rl_delete (1);
rl_insert (1, c);
rl_end_undo_group ();
break;
}
}
rl_vi_subst (count, key)
int count, key;
{
rl_begin_undo_group ();
vi_doing_insert = 1;
if (uppercase_p (key))
{
rl_beg_of_line ();
rl_kill_line (1);
}
else
rl_delete (1);
rl_vi_insertion_mode ();
}
rl_vi_overstrike (count, key)
int count, key;
{
int i;
if (vi_doing_insert == 0)
{
vi_doing_insert = 1;
rl_begin_undo_group ();
}
for (i = 0; i < count; i++)
{
vi_replace_count++;
rl_begin_undo_group ();
if (rl_point < rl_end)
{
rl_delete (1);
rl_insert (1, key);
}
else
rl_insert (1, key);
rl_end_undo_group ();
}
}
rl_vi_overstrike_delete (count)
int count;
{
int i, s;
for (i = 0; i < count; i++)
{
if (vi_replace_count == 0)
{
ding ();
break;
}
s = rl_point;
if (rl_do_undo ())
vi_replace_count--;
if (rl_point == s)
rl_backward (1);
}
if (vi_replace_count == 0 && vi_doing_insert)
{
rl_end_undo_group ();
rl_do_undo ();
vi_doing_insert = 0;
}
}
rl_vi_replace ()
{
int i;
vi_replace_count = 0;
vi_replace_map = rl_make_bare_keymap ();
for (i = ' '; i < 127; i++)
vi_replace_map[i].function = rl_vi_overstrike;
vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
vi_replace_map[CTRL('H')].function = rl_vi_overstrike_delete;
vi_replace_map[ESC].function = rl_vi_movement_mode;
vi_replace_map[RETURN].function = rl_newline;
vi_replace_map[NEWLINE].function = rl_newline;
keymap = vi_replace_map;
}

1738
gnu/usr.bin/gdb/regex.c Normal file

File diff suppressed because it is too large Load diff

185
gnu/usr.bin/gdb/regex.h Normal file
View file

@ -0,0 +1,185 @@
/* Definitions for data structures callers pass the regex library.
Copyright (C) 1985, 1989 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding! */
/* Define number of parens for which we record the beginnings and ends.
This affects how much space the `struct re_registers' type takes up. */
#ifndef RE_NREGS
#define RE_NREGS 10
#endif
/* These bits are used in the obscure_syntax variable to choose among
alternative regexp syntaxes. */
/* 1 means plain parentheses serve as grouping, and backslash
parentheses are needed for literal searching.
0 means backslash-parentheses are grouping, and plain parentheses
are for literal searching. */
#define RE_NO_BK_PARENS 1
/* 1 means plain | serves as the "or"-operator, and \| is a literal.
0 means \| serves as the "or"-operator, and | is a literal. */
#define RE_NO_BK_VBAR 2
/* 0 means plain + or ? serves as an operator, and \+, \? are literals.
1 means \+, \? are operators and plain +, ? are literals. */
#define RE_BK_PLUS_QM 4
/* 1 means | binds tighter than ^ or $.
0 means the contrary. */
#define RE_TIGHT_VBAR 8
/* 1 means treat \n as an _OR operator
0 means treat it as a normal character */
#define RE_NEWLINE_OR 16
/* 0 means that a special characters (such as *, ^, and $) always have
their special meaning regardless of the surrounding context.
1 means that special characters may act as normal characters in some
contexts. Specifically, this applies to:
^ - only special at the beginning, or after ( or |
$ - only special at the end, or before ) or |
*, +, ? - only special when not after the beginning, (, or | */
#define RE_CONTEXT_INDEP_OPS 32
/* Now define combinations of bits for the standard possibilities. */
#define RE_SYNTAX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR | RE_CONTEXT_INDEP_OPS)
#define RE_SYNTAX_EGREP (RE_SYNTAX_AWK | RE_NEWLINE_OR)
#define RE_SYNTAX_GREP (RE_BK_PLUS_QM | RE_NEWLINE_OR)
#define RE_SYNTAX_EMACS 0
/* This data structure is used to represent a compiled pattern. */
struct re_pattern_buffer
{
char *buffer; /* Space holding the compiled pattern commands. */
int allocated; /* Size of space that buffer points to */
int used; /* Length of portion of buffer actually occupied */
char *fastmap; /* Pointer to fastmap, if any, or zero if none. */
/* re_search uses the fastmap, if there is one,
to skip quickly over totally implausible characters */
char *translate; /* Translate table to apply to all characters before comparing.
Or zero for no translation.
The translation is applied to a pattern when it is compiled
and to data when it is matched. */
char fastmap_accurate;
/* Set to zero when a new pattern is stored,
set to one when the fastmap is updated from it. */
char can_be_null; /* Set to one by compiling fastmap
if this pattern might match the null string.
It does not necessarily match the null string
in that case, but if this is zero, it cannot.
2 as value means can match null string
but at end of range or before a character
listed in the fastmap. */
};
/* Structure to store "register" contents data in.
Pass the address of such a structure as an argument to re_match, etc.,
if you want this information back.
start[i] and end[i] record the string matched by \( ... \) grouping i,
for i from 1 to RE_NREGS - 1.
start[0] and end[0] record the entire string matched. */
struct re_registers
{
int start[RE_NREGS];
int end[RE_NREGS];
};
/* These are the command codes that appear in compiled regular expressions, one per byte.
Some command codes are followed by argument bytes.
A command code can specify any interpretation whatever for its arguments.
Zero-bytes may appear in the compiled regular expression. */
enum regexpcode
{
unused,
exactn, /* followed by one byte giving n, and then by n literal bytes */
begline, /* fails unless at beginning of line */
endline, /* fails unless at end of line */
jump, /* followed by two bytes giving relative address to jump to */
on_failure_jump, /* followed by two bytes giving relative address of place
to resume at in case of failure. */
finalize_jump, /* Throw away latest failure point and then jump to address. */
maybe_finalize_jump, /* Like jump but finalize if safe to do so.
This is used to jump back to the beginning
of a repeat. If the command that follows
this jump is clearly incompatible with the
one at the beginning of the repeat, such that
we can be sure that there is no use backtracking
out of repetitions already completed,
then we finalize. */
dummy_failure_jump, /* jump, and push a dummy failure point.
This failure point will be thrown away
if an attempt is made to use it for a failure.
A + construct makes this before the first repeat. */
anychar, /* matches any one character */
charset, /* matches any one char belonging to specified set.
First following byte is # bitmap bytes.
Then come bytes for a bit-map saying which chars are in.
Bits in each byte are ordered low-bit-first.
A character is in the set if its bit is 1.
A character too large to have a bit in the map
is automatically not in the set */
charset_not, /* similar but match any character that is NOT one of those specified */
start_memory, /* starts remembering the text that is matched
and stores it in a memory register.
followed by one byte containing the register number.
Register numbers must be in the range 0 through NREGS. */
stop_memory, /* stops remembering the text that is matched
and stores it in a memory register.
followed by one byte containing the register number.
Register numbers must be in the range 0 through NREGS. */
duplicate, /* match a duplicate of something remembered.
Followed by one byte containing the index of the memory register. */
before_dot, /* Succeeds if before dot */
at_dot, /* Succeeds if at dot */
after_dot, /* Succeeds if after dot */
begbuf, /* Succeeds if at beginning of buffer */
endbuf, /* Succeeds if at end of buffer */
wordchar, /* Matches any word-constituent character */
notwordchar, /* Matches any char that is not a word-constituent */
wordbeg, /* Succeeds if at word beginning */
wordend, /* Succeeds if at word end */
wordbound, /* Succeeds if at a word boundary */
notwordbound, /* Succeeds if not at a word boundary */
syntaxspec, /* Matches any character whose syntax is specified.
followed by a byte which contains a syntax code, Sword or such like */
notsyntaxspec /* Matches any character whose syntax differs from the specified. */
};
extern char *re_compile_pattern ();
/* Is this really advertised? */
extern void re_compile_fastmap ();
extern int re_search (), re_search_2 ();
extern int re_match (), re_match_2 ();
/* 4.2 bsd compatibility (yuck) */
extern char *re_comp ();
extern int re_exec ();
#ifdef SYNTAX_TABLE
extern char *re_syntax_table;
#endif

View file

@ -0,0 +1,10 @@
/*
* The binary remote protocol is still under development at LBL;
* the current version can't be released.
* Sorry, folks...
*/
int
sl_open()
{
return -1;
}

626
gnu/usr.bin/gdb/remote.c Normal file
View file

@ -0,0 +1,626 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Van Jacobson and Steven McCanne of Lawrence Berkeley Laboratory.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Header: /home/cvs/386BSD/src/usr.bin/gdb/remote.c,v 1.1.1.1 1993/06/12 14:52:22 rgrimes Exp $;
*/
#ifndef lint
static char sccsid[] = "@(#)remote.c 6.5 (Berkeley) 5/8/91";
#endif /* not lint */
#include "param.h"
#include <stdio.h>
#include <varargs.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include "wait.h"
#include "kgdb_proto.h"
static FILE *kiodebug;
static int icache = 1;
extern int kernel_debugging;
static int remote_cache_valid;
static int remote_instub;
static void remote_signal();
static void remote_debug();
static void print_msg();
static int remote_mtu;
static int (*send_msg)();
static int (*recv_msg)();
static void (*closelink)();
static u_char *inbuffer;
static u_char *outbuffer;
/*
* Statistics.
*/
static int remote_ierrs;
static int remote_oerrs;
static int remote_seqerrs;
static int remote_spurious;
#define PUTCMD(cmd) m_xchg(cmd, (u_char *)0, 0, (u_char *)0, (int *)0)
/*
* Send an outbound message to the remote machine and read the reply.
* Either or both message buffers may be NULL.
*/
static int
m_xchg(type, out, outlen, in, inlen)
int type;
u_char *out;
int outlen;
u_char *in;
int *inlen;
{
register int err, (*send)() = send_msg, (*recv)() = recv_msg;
int ack;
static int seqbit = 0;
if (!remote_instub) {
remote_instub = 1;
PUTCMD(KGDB_EXEC);
}
seqbit ^= KGDB_SEQ;
while (1) {
err = (*send)(type | seqbit, out, outlen);
if (err) {
++remote_oerrs;
if (kiodebug)
remote_debug("send error %d\n", err);
}
if (kiodebug)
print_msg(type | seqbit, out, outlen, 'O');
recv:
err = (*recv)(&ack, in, inlen);
if (err) {
++remote_ierrs;
if (kiodebug)
remote_debug("recv error %d\n", err);
remote_cache_valid = 0;
} else if (kiodebug)
print_msg(ack, in, inlen ? *inlen : 0, 'I');
if (err)
continue;
if ((ack & KGDB_ACK) == 0 || KGDB_CMD(ack) != KGDB_CMD(type)) {
++remote_spurious;
continue;
}
if ((ack & KGDB_SEQ) ^ seqbit) {
++remote_seqerrs;
goto recv;
}
return ack;
}
}
/*
* Wait for the specified message type. Discard anything else.
* (this is used by 'remote-signal' to help us resync with other side.)
*/
static void
m_recv(type, in, inlen)
int type;
u_char *in;
int *inlen;
{
int reply, err;
while (1) {
err = (*recv_msg)(&reply, in, inlen);
if (err) {
++remote_ierrs;
if (kiodebug)
remote_debug("recv error %d\n", err);
} else if (kiodebug)
print_msg(reply, in, inlen ? *inlen : 0, 'I');
if (KGDB_CMD(reply) == type)
return;
++remote_spurious;
}
}
/*
* Send a message. Do not wait for *any* response from the other side.
* Some other thread of control will pick up the ack that will be generated.
*/
static void
m_send(type, buf, len)
int type;
u_char *buf;
int len;
{
int err;
if (!remote_instub) {
remote_instub = 1;
PUTCMD(KGDB_EXEC);
}
err = (*send_msg)(type, buf, len);
if (err) {
++remote_ierrs;
if (kiodebug)
remote_debug("[send error %d] ", err);
}
if (kiodebug)
print_msg(type, buf, len, 'O');
}
/*
* Open a connection to a remote debugger.
* NAME is the filename used for communication.
*/
void
remote_open(name, from_tty)
char *name;
int from_tty;
{
int bufsize;
remote_debugging = 0;
if (sl_open(name, &send_msg, &recv_msg, &closelink, &remote_mtu,
&bufsize))
return;
if (from_tty)
printf("Remote debugging using %s\n", name);
remote_debugging = 1;
remote_cache_valid = 0;
inbuffer = (u_char *)malloc(bufsize);
outbuffer = (u_char *)malloc(bufsize);
remote_signal();
remote_ierrs = 0;
remote_oerrs = 0;
remote_spurious = 0;
}
/*
* Close the open connection to the remote debugger. Use this when you want
* to detach and do something else with your gdb.
*/
void
remote_close(from_tty)
int from_tty;
{
if (!remote_debugging)
error("remote debugging not enabled");
remote_debugging = 0;
/*
* Take remote machine out of debug mode.
*/
(void)PUTCMD(KGDB_KILL);
(*closelink)();
if (from_tty)
printf("Ending remote debugging\n");
free((char *)inbuffer);
free((char *)outbuffer);
}
/*
* Tell the remote machine to resume.
*/
int
remote_resume(step, signal)
int step, signal;
{
if (!step) {
(void)PUTCMD(KGDB_CONT);
remote_instub = 0;
} else {
#ifdef NO_SINGLE_STEP
single_step(0);
#else
(void)PUTCMD(KGDB_STEP);
#endif
}
}
/*
* Wait until the remote machine stops, then return, storing status in STATUS
* just as `wait' would.
*/
int
remote_wait(status)
WAITTYPE *status;
{
int len;
WSETEXIT((*status), 0);
/*
* When the machine stops, it will send us a KGDB_SIGNAL message,
* so we wait for one of these.
*/
m_recv(KGDB_SIGNAL, inbuffer, &len);
WSETSTOP((*status), inbuffer[0]);
}
/*
* Register context as of last remote_fetch_registers().
*/
static char reg_cache[REGISTER_BYTES];
/*
* Read the remote registers into the block REGS.
*/
void
remote_fetch_registers(regs)
char *regs;
{
int regno, len, rlen, ack;
u_char *cp, *ep;
regno = -1;
do {
outbuffer[0] = regno + 1;
ack = m_xchg(remote_cache_valid ?
KGDB_REG_R|KGDB_DELTA : KGDB_REG_R,
outbuffer, 1, inbuffer, &len);
cp = inbuffer;
ep = cp + len;
while (cp < ep) {
regno = *cp++;
rlen = REGISTER_RAW_SIZE(regno);
bcopy((char *)cp,
&reg_cache[REGISTER_BYTE(regno)], rlen);
cp += rlen;
}
} while (ack & KGDB_MORE);
remote_cache_valid = 1;
bcopy(reg_cache, regs, REGISTER_BYTES);
}
/*
* Store the remote registers from the contents of the block REGS.
*/
void
remote_store_registers(regs)
char *regs;
{
u_char *cp, *ep;
int regno, off, rlen;
cp = outbuffer;
ep = cp + remote_mtu;
for (regno = 0; regno < NUM_REGS; ++regno) {
off = REGISTER_BYTE(regno);
rlen = REGISTER_RAW_SIZE(regno);
if (!remote_cache_valid ||
bcmp(&regs[off], &reg_cache[off], rlen) != 0) {
if (cp + rlen + 1 >= ep) {
(void)m_xchg(KGDB_REG_W,
outbuffer, cp - outbuffer,
(u_char *)0, (int *)0);
cp = outbuffer;
}
*cp++ = regno;
bcopy(&regs[off], cp, rlen);
cp += rlen;
}
}
if (cp != outbuffer)
(void)m_xchg(KGDB_REG_W, outbuffer, cp - outbuffer,
(u_char *)0, (int *)0);
bcopy(regs, reg_cache, REGISTER_BYTES);
}
/*
* Store a chunk of memory into the remote host.
* 'remote_addr' is the address in the remote memory space.
* 'cp' is the address of the buffer in our space, and 'len' is
* the number of bytes. Returns an errno status.
*/
int
remote_write_inferior_memory(remote_addr, cp, len)
CORE_ADDR remote_addr;
u_char *cp;
int len;
{
int cnt;
while (len > 0) {
cnt = min(len, remote_mtu - 4);
bcopy((char *)&remote_addr, outbuffer, 4);
bcopy(cp, outbuffer + 4, cnt);
(void)m_xchg(KGDB_MEM_W, outbuffer, cnt + 4, inbuffer, &len);
if (inbuffer[0])
return inbuffer[0];
remote_addr += cnt;
cp += cnt;
len -= cnt;
}
return 0;
}
/*
* Read memory data directly from the remote machine.
* 'remote_addr' is the address in the remote memory space.
* 'cp' is the address of the buffer in our space, and 'len' is
* the number of bytes. Returns an errno status.
*/
static int
remote_read_memory(remote_addr, cp, len)
CORE_ADDR remote_addr;
u_char *cp;
int len;
{
int cnt, inlen;
while (len > 0) {
cnt = min(len, remote_mtu - 1);
outbuffer[0] = cnt;
bcopy((char *)&remote_addr, (char *)&outbuffer[1], 4);
(void)m_xchg(KGDB_MEM_R, outbuffer, 5, inbuffer, &inlen);
if (inbuffer[0] != 0)
return inbuffer[0];
if (cnt != inlen - 1)
/* XXX */
error("remote_read_memory() request botched");
bcopy((char *)&inbuffer[1], (char *)cp, cnt);
remote_addr += cnt;
cp += cnt;
len -= cnt;
}
return 0;
}
int
remote_read_inferior_memory(remote_addr, cp, len)
CORE_ADDR remote_addr;
char *cp;
int len;
{
int stat = 0;
if (icache) {
extern CORE_ADDR text_start, text_end;
CORE_ADDR xferend = remote_addr + len;
if (remote_addr < text_end && text_start < xferend) {
/*
* at least part of this xfer is in the text
* space -- xfer the overlap from the exec file.
*/
if (remote_addr >= text_start && xferend < text_end)
return (xfer_core_file(remote_addr, cp, len));
if (remote_addr >= text_start) {
int i = text_end - remote_addr;
if (stat = xfer_core_file(remote_addr, cp, i))
return (stat);
remote_addr += i;
cp += i;
len -= i;
} else if (xferend <= text_end) {
int i = xferend - text_start;
len = text_start - remote_addr;
if (stat = xfer_core_file(text_start,
cp + len, i))
return (stat);
}
}
}
return remote_read_memory(remote_addr, cp, len);
}
/*
* Signal the remote machine. The remote end might be idle or it might
* already be in debug mode -- we need to handle both case. Thus, we use
* the framing character as the wakeup byte, and send a SIGNAL packet.
* If the remote host is idle, the framing character will wake it up.
* If it is in the kgdb stub, then we will get a SIGNAL reply.
*/
static void
remote_signal()
{
if (!remote_debugging)
printf("Remote debugging not enabled.\n");
else {
remote_instub = 0;
m_send(KGDB_SIGNAL, (u_char *)0, 0);
}
}
static void
remote_signal_command()
{
extern int stop_after_attach;
if (!remote_debugging)
error("Not debugging remote.");
remote_cache_valid = 0;
remote_signal();
restart_remote();
}
/*
* Print a message for debugging.
*/
static void
print_msg(type, buf, len, dir)
int type;
u_char *buf;
int len;
int dir;
{
int i;
char *s;
switch (KGDB_CMD(type)) {
case KGDB_MEM_R: s = "memr"; break;
case KGDB_MEM_W: s = "memw"; break;
case KGDB_REG_R: s = "regr"; break;
case KGDB_REG_W: s = "regw"; break;
case KGDB_CONT: s = "cont"; break;
case KGDB_STEP: s = "step"; break;
case KGDB_KILL: s = "kill"; break;
case KGDB_SIGNAL: s = "sig "; break;
case KGDB_EXEC: s = "exec"; break;
default: s = "unk "; break;
}
remote_debug("%c %c%c%c%c %s (%02x): ", dir,
(type & KGDB_ACK) ? 'A' : '.',
(type & KGDB_DELTA) ? 'D' : '.',
(type & KGDB_MORE) ? 'M' : '.',
(type & KGDB_SEQ) ? '-' : '+',
s, type);
if (buf)
for (i = 0; i < len; ++i)
remote_debug("%02x", buf[i]);
remote_debug("\n");
}
static void
set_remote_text_refs_command(arg, from_tty)
char *arg;
int from_tty;
{
icache = !parse_binary_operation("set remote-text-refs", arg);
}
static void
remote_debug_command(arg, from_tty)
char *arg;
int from_tty;
{
char *name;
if (kiodebug != 0 && kiodebug != stderr)
(void)fclose(kiodebug);
if (arg == 0) {
kiodebug = 0;
printf("Remote debugging off.\n");
return;
}
if (arg[0] == '-') {
kiodebug = stderr;
name = "stderr";
} else {
kiodebug = fopen(arg, "w");
if (kiodebug == 0) {
printf("Cannot open '%s'.\n", arg);
return;
}
name = arg;
}
printf("Remote debugging output routed to %s.\n", name);
}
/* ARGSUSED */
static void
remote_info(arg, from_tty)
char *arg;
int from_tty;
{
printf("Using %s for text references.\n",
icache? "local executable" : "remote");
printf("Protocol debugging is %s.\n", kiodebug? "on" : "off");
printf("%d spurious input messages.\n", remote_spurious);
printf("%d input errors; %d output errors; %d sequence errors.\n",
remote_ierrs, remote_oerrs, remote_seqerrs);
}
/* VARARGS */
static void
remote_debug(va_alist)
va_dcl
{
register char *cp;
va_list ap;
va_start(ap);
cp = va_arg(ap, char *);
(void)vfprintf(kiodebug, cp, ap);
va_end(ap);
fflush(kiodebug);
}
extern struct cmd_list_element *setlist;
void
_initialize_remote()
{
add_com("remote-signal", class_run, remote_signal_command,
"If remote debugging, send interrupt signal to remote.");
add_cmd("remote-text-refs", class_support,
set_remote_text_refs_command,
"Enable/disable use of local executable for text segment references.\n\
If on, all memory read/writes go to remote.\n\
If off, text segment reads use the local executable.",
&setlist);
add_com("remote-debug", class_run, remote_debug_command,
"With a file name argument, enables output of remote protocol debugging\n\
messages to said file. If file is `-', stderr is used.\n\
With no argument, remote debugging is disabled.");
add_info("remote", remote_info,
"Show current settings of remote debugging options.");
}

1166
gnu/usr.bin/gdb/source.c Normal file

File diff suppressed because it is too large Load diff

115
gnu/usr.bin/gdb/stab.def Normal file
View file

@ -0,0 +1,115 @@
/* Table of DBX symbol codes for the GNU system.
Copyright (C) 1988 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Global variable. Only the name is significant.
To find the address, look in the corresponding external symbol. */
__define_stab (N_GSYM, 0x20, "GSYM")
/* Function name for BSD Fortran. Only the name is significant.
To find the address, look in the corresponding external symbol. */
__define_stab (N_FNAME, 0x22, "FNAME")
/* Function name or text-segment variable for C. Value is its address.
Desc is supposedly starting line number, but GCC doesn't set it
and DBX seems not to miss it. */
__define_stab (N_FUN, 0x24, "FUN")
/* Data-segment variable with internal linkage. Value is its address. */
__define_stab (N_STSYM, 0x26, "STSYM")
/* BSS-segment variable with internal linkage. Value is its address. */
__define_stab (N_LCSYM, 0x28, "LCSYM")
/* Name of main routine. Only the name is significant.
This is not used in C. */
__define_stab (N_MAIN, 0x2a, "MAIN")
/* Register variable. Value is number of register. */
__define_stab (N_RSYM, 0x40, "RSYM")
/* Structure or union element. Value is offset in the structure. */
__define_stab (N_SSYM, 0x60, "SSYM")
/* Parameter variable. Value is offset from argument pointer.
(On most machines the argument pointer is the same as the frame pointer. */
__define_stab (N_PSYM, 0xa0, "PSYM")
/* Automatic variable in the stack. Value is offset from frame pointer.
Also used for type descriptions. */
__define_stab (N_LSYM, 0x80, "LSYM")
/* Alternate entry point. Value is its address. */
__define_stab (N_ENTRY, 0xa4, "ENTRY")
/* Name of main source file.
Value is starting text address of the compilation. */
__define_stab (N_SO, 0x64, "SO")
/* Name of sub-source file.
Value is starting text address of the compilation. */
__define_stab (N_SOL, 0x84, "SOL")
/* Line number in text segment. Desc is the line number;
value is corresponding address. */
__define_stab (N_SLINE, 0x44, "SLINE")
/* Similar, for data segment. */
__define_stab (N_DSLINE, 0x46, "DSLINE")
/* Similar, for bss segment. */
__define_stab (N_BSLINE, 0x48, "BSLINE")
/* Beginning of an include file. Only Sun uses this.
In an object file, only the name is significant.
The Sun linker puts data into some of the other fields. */
__define_stab (N_BINCL, 0x82, "BINCL")
/* End of an include file. No name.
These two act as brackets around the file's output.
In an object file, there is no significant data in this entry.
The Sun linker puts data into some of the fields. */
__define_stab (N_EINCL, 0xa2, "EINCL")
/* Place holder for deleted include file.
This appears only in output from the Sun linker. */
__define_stab (N_EXCL, 0xc2, "EXCL")
/* Beginning of lexical block.
The desc is the nesting level in lexical blocks.
The value is the address of the start of the text for the block.
The variables declared inside the block *precede* the N_LBRAC symbol. */
__define_stab (N_LBRAC, 0xc0, "LBRAC")
/* End of a lexical block. Desc matches the N_LBRAC's desc.
The value is the address of the end of the text for the block. */
__define_stab (N_RBRAC, 0xe0, "RBRAC")
/* Begin named common block. Only the name is significant. */
__define_stab (N_BCOMM, 0xe2, "BCOMM")
/* Begin named common block. Only the name is significant
(and it should match the N_BCOMM). */
__define_stab (N_ECOMM, 0xe4, "ECOMM")
/* End common (local name): value is address.
I'm not sure how this is used. */
__define_stab (N_ECOML, 0xe8, "ECOML")
/* Second symbol entry containing a length-value for the preceding entry.
The value is the length. */
__define_stab (N_LENG, 0xfe, "LENG")
/* Global symbol in Pascal.
Supposedly the value is its line number; I'm skeptical. */
__define_stab (N_PC, 0x30, "PC")
/* Modula-2 compilation unit. Can someone say what info it contains? */
__define_stab (N_M2C, 0x42, "M2C")
/* Modula-2 scope information. Can someone say what info it contains? */
__define_stab (N_SCOPE, 0xc4, "SCOPE")

960
gnu/usr.bin/gdb/stack.c Normal file
View file

@ -0,0 +1,960 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
* Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
*/
#ifndef lint
static char sccsid[] = "@(#)stack.c 6.3 (Berkeley) 5/8/91";
#endif /* not lint */
/* Print and select stack frames for GDB, the GNU debugger.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* modified by rjc Thu Nov 1 16:46:57 1990, fixed return_command so that
it can return values, it still has problems when running on pmax,
cannot write register 65 */
#include <stdio.h>
#include "defs.h"
#include "param.h"
#include "symtab.h"
#include "frame.h"
#include "value.h"
/* Thie "selected" stack frame is used by default for local and arg access.
May be zero, for no selected frame. */
FRAME selected_frame;
/* Level of the selected frame:
0 for innermost, 1 for its caller, ...
or -1 for frame specified by address with no defined level. */
int selected_frame_level;
/* Nonzero means print the full filename and linenumber
when a frame is printed, and do so in a format programs can parse. */
int frame_file_full_name = 0;
static void select_calling_frame ();
void print_frame_info ();
/* Print a stack frame briefly. FRAME should be the frame id
and LEVEL should be its level in the stack (or -1 for level not defined).
This prints the level, the function executing, the arguments,
and the file name and line number.
If the pc is not at the beginning of the source line,
the actual pc is printed at the beginning.
If SOURCE is 1, print the source line as well.
If SOURCE is -1, print ONLY the source line. */
static void
print_stack_frame (frame, level, source)
FRAME frame;
int level;
int source;
{
struct frame_info *fi;
fi = get_frame_info (frame);
print_frame_info (fi, level, source, 1);
}
/* Flag which will indicate when the frame has been changed
by and "up" or "down" command. */
static int frame_changed;
void
print_frame_info (fi, level, source, args)
struct frame_info *fi;
register int level;
int source;
int args;
{
struct symtab_and_line sal;
struct symbol *func;
register char *funname = 0;
int numargs;
struct partial_symtab *pst;
/* Don't give very much information if we haven't readin the
symbol table yet. */
pst = find_pc_psymtab (fi->pc);
if (pst && !pst->readin)
{
/* Abbreviated information. */
char *fname;
if (!find_pc_partial_function (fi->pc, &fname, 0))
fname = "??";
printf_filtered ("#%-2d ", level);
printf_filtered ("0x%x in ", fi->pc);
fputs_demangled(fname, stdout, -1);
fputs_filtered(" (...)\n", stdout);
return;
}
sal = find_pc_line (fi->pc, fi->next_frame);
func = find_pc_function (fi->pc);
if (func)
{
/* In certain pathological cases, the symtabs give the wrong
function (when we are in the first function in a file which
is compiled without debugging symbols, the previous function
is compiled with debugging symbols, and the "foo.o" symbol
that is supposed to tell us where the file with debugging symbols
ends has been truncated by ar because it is longer than 15
characters).
So look in the misc_function_vector as well, and if it comes
up with a larger address for the function use that instead.
I don't think this can ever cause any problems;
there shouldn't be any
misc_function_vector symbols in the middle of a function. */
int misc_index = find_pc_misc_function (fi->pc);
if (misc_index >= 0
&& (misc_function_vector[misc_index].address
> BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
{
/* In this case we have no way of knowing the source file
and line number, so don't print them. */
sal.symtab = 0;
/* We also don't know anything about the function besides
its address and name. */
func = 0;
funname = misc_function_vector[misc_index].name;
}
else
funname = SYMBOL_NAME (func);
}
else
{
register int misc_index = find_pc_misc_function (fi->pc);
if (misc_index >= 0)
funname = misc_function_vector[misc_index].name;
}
if (frame_changed || source >= 0 || !sal.symtab)
{
if (level >= 0)
printf_filtered ("#%-2d ", level);
else if (frame_changed)
printf ("#%-2d ", 0);
if (fi->pc != sal.pc || !sal.symtab)
printf_filtered ("0x%x in ", fi->pc);
fputs_demangled(funname ? funname : "??", stdout, -1);
printf_filtered(" (");
if (args)
{
if (func)
numargs = -1;
else
FRAME_NUM_ARGS (numargs, fi);
print_frame_args (func, fi, numargs, stdout);
}
printf_filtered (")");
if (sal.symtab)
printf_filtered (" (%s line %d)", sal.symtab->filename, sal.line);
printf_filtered ("\n");
}
if ((frame_changed || source != 0) && sal.symtab)
{
int done = 0;
int mid_statement = source < 0 && fi->pc != sal.pc;
if (frame_file_full_name)
done = identify_source_line (sal.symtab, sal.line, mid_statement);
if (!done)
{
if (mid_statement)
printf_filtered ("0x%x\t", fi->pc);
print_source_lines (sal.symtab, sal.line, sal.line + 1, 1);
}
current_source_line = max (sal.line - 5, 1);
}
frame_changed = 0;
if (source != 0)
set_default_breakpoint (1, fi->pc, sal.symtab, sal.line);
fflush (stdout);
}
/* Call here to print info on selected frame, after a trap. */
void
print_sel_frame (just_source)
int just_source;
{
print_stack_frame (selected_frame, -1, just_source ? -1 : 1);
}
/* Print info on the selected frame, including level number
but not source. */
void
print_selected_frame ()
{
print_stack_frame (selected_frame, selected_frame_level, 0);
}
void flush_cached_frames ();
#ifdef FRAME_SPECIFICATION_DYADIC
extern FRAME setup_arbitrary_frame ();
#endif
/*
* Read a frame specification in whatever the appropriate format is.
*/
static FRAME
parse_frame_specification (frame_exp)
char *frame_exp;
{
int numargs = 0;
int arg1, arg2;
if (frame_exp)
{
char *addr_string, *p;
struct cleanup *tmp_cleanup;
struct frame_info *fci;
while (*frame_exp == ' ') frame_exp++;
for (p = frame_exp; *p && *p != ' '; p++)
;
if (*frame_exp)
{
numargs = 1;
addr_string = savestring(frame_exp, p - frame_exp);
{
tmp_cleanup = make_cleanup (free, addr_string);
arg1 = parse_and_eval_address (addr_string);
do_cleanups (tmp_cleanup);
}
while (*p == ' ') p++;
if (*p)
{
numargs = 2;
arg2 = parse_and_eval_address (p);
}
}
}
switch (numargs)
{
case 0:
return selected_frame;
/* NOTREACHED */
case 1:
{
int level = arg1;
FRAME fid = find_relative_frame (get_current_frame (), &level);
FRAME tfid;
if (level == 0)
/* find_relative_frame was successful */
return fid;
/* If (s)he specifies the frame with an address, he deserves what
(s)he gets. Still, give the highest one that matches. */
for (fid = get_current_frame ();
fid && FRAME_FP (fid) != arg1;
fid = get_prev_frame (fid))
;
if (fid)
while ((tfid = get_prev_frame (fid)) &&
(FRAME_FP (tfid) == arg1))
fid = tfid;
#ifdef FRAME_SPECIFICATION_DYADIC
if (!fid)
error ("Incorrect number of args in frame specification");
return fid;
#else
return create_new_frame (arg1, 0);
#endif
}
/* NOTREACHED */
case 2:
/* Must be addresses */
#ifndef FRAME_SPECIFICATION_DYADIC
error ("Incorrect number of args in frame specification");
#else
return setup_arbitrary_frame (arg1, arg2);
#endif
/* NOTREACHED */
}
fatal ("Internal: Error in parsing in parse_frame_specification");
/* NOTREACHED */
}
/* FRAME_ARGS_ADDRESS_CORRECT is just like FRAME_ARGS_ADDRESS except
that if it is unsure about the answer, it returns Frame_unknown
instead of guessing (this happens on the VAX, for example).
On most machines, we never have to guess about the args address,
so FRAME_ARGS_ADDRESS{,_CORRECT} are the same. */
#if !defined (FRAME_ARGS_ADDRESS_CORRECT)
#define FRAME_ARGS_ADDRESS_CORRECT FRAME_ARGS_ADDRESS
#endif
/* Print verbosely the selected frame or the frame at address ADDR.
This means absolutely all information in the frame is printed. */
static void
frame_info (addr_exp)
char *addr_exp;
{
FRAME frame;
struct frame_info *fi;
struct frame_saved_regs fsr;
struct symtab_and_line sal;
struct symbol *func;
FRAME calling_frame;
int i, count;
char *funname = 0;
if (!(have_inferior_p () || have_core_file_p ()))
error ("No inferior or core file.");
frame = parse_frame_specification (addr_exp);
if (!frame)
error ("Invalid frame specified.");
fi = get_frame_info (frame);
get_frame_saved_regs (fi, &fsr);
sal = find_pc_line (fi->pc, fi->next_frame);
func = get_frame_function (frame);
if (func)
funname = SYMBOL_NAME (func);
else
{
register int misc_index = find_pc_misc_function (fi->pc);
if (misc_index >= 0)
funname = misc_function_vector[misc_index].name;
}
calling_frame = get_prev_frame (frame);
if (!addr_exp && selected_frame_level >= 0)
printf ("Stack level %d, frame at 0x%x:\n pc = 0x%x",
selected_frame_level, FRAME_FP(frame), fi->pc);
else
printf ("Stack frame at 0x%x:\n pc = 0x%x",
FRAME_FP(frame), fi->pc);
if (funname)
printf (" in %s", funname);
if (sal.symtab)
printf (" (%s line %d)", sal.symtab->filename, sal.line);
printf ("; saved pc 0x%x\n", FRAME_SAVED_PC (frame));
if (calling_frame)
printf (" called by frame at 0x%x", FRAME_FP (calling_frame));
if (fi->next_frame && calling_frame)
printf (",");
if (fi->next_frame)
printf (" caller of frame at 0x%x", fi->next_frame);
if (fi->next_frame || calling_frame)
printf ("\n");
{
/* Address of the argument list for this frame, or Frame_unknown. */
CORE_ADDR arg_list = FRAME_ARGS_ADDRESS_CORRECT (fi);
/* Number of args for this frame, or -1 if unknown. */
int numargs;
if (arg_list != Frame_unknown)
{
printf (" Arglist at 0x%x,", arg_list);
FRAME_NUM_ARGS (numargs, fi);
if (numargs < 0)
printf (" args: ");
else if (numargs == 0)
printf (" no args.");
else if (numargs == 1)
printf (" 1 arg: ");
else
printf (" %d args: ", numargs);
print_frame_args (func, fi, numargs, stdout);
printf ("\n");
}
}
/* The sp is special; what's returned isn't the save address, but
actually the value of the previous frame's sp. */
printf (" Previous frame's sp is 0x%x\n", fsr.regs[SP_REGNUM]);
count = 0;
for (i = 0; i < NUM_REGS; i++)
if (fsr.regs[i] && i != SP_REGNUM)
{
if (count % 4 != 0)
printf (", ");
else
{
if (count == 0)
printf (" Saved registers:");
printf ("\n ");
}
printf ("%s at 0x%x", reg_names[i], fsr.regs[i]);
count++;
}
if (count)
printf ("\n");
}
#if 0
/* Set a limit on the number of frames printed by default in a
backtrace. */
static int backtrace_limit;
static void
set_backtrace_limit_command (count_exp, from_tty)
char *count_exp;
int from_tty;
{
int count = parse_and_eval_address (count_exp);
if (count < 0)
error ("Negative argument not meaningful as backtrace limit.");
backtrace_limit = count;
}
static void
backtrace_limit_info (arg, from_tty)
char *arg;
int from_tty;
{
if (arg)
error ("\"Info backtrace-limit\" takes no arguments.");
printf ("Backtrace limit: %d.\n", backtrace_limit);
}
#endif
/* Print briefly all stack frames or just the innermost COUNT frames. */
static void
backtrace_command (count_exp)
char *count_exp;
{
struct frame_info *fi;
register int count;
register FRAME frame;
register int i;
register FRAME trailing;
register int trailing_level;
/* The following code must do two things. First, it must
set the variable TRAILING to the frame from which we should start
printing. Second, it must set the variable count to the number
of frames which we should print, or -1 if all of them. */
trailing = get_current_frame ();
trailing_level = 0;
if (count_exp)
{
count = parse_and_eval_address (count_exp);
if (count < 0)
{
FRAME current;
count = -count;
current = trailing;
while (current && count--)
current = get_prev_frame (current);
/* Will stop when CURRENT reaches the top of the stack. TRAILING
will be COUNT below it. */
while (current)
{
trailing = get_prev_frame (trailing);
current = get_prev_frame (current);
trailing_level++;
}
count = -1;
}
}
else
count = -1;
for (i = 0, frame = trailing;
frame && count--;
i++, frame = get_prev_frame (frame))
{
QUIT;
fi = get_frame_info (frame);
print_frame_info (fi, trailing_level + i, 0, 1);
}
/* If we've stopped before the end, mention that. */
if (frame)
printf_filtered ("(More stack frames follow...)\n");
}
/* Print the local variables of a block B active in FRAME.
Return 1 if any variables were printed; 0 otherwise. */
static int
print_block_frame_locals (b, frame, stream)
struct block *b;
register FRAME frame;
register FILE *stream;
{
int nsyms;
register int i;
register struct symbol *sym;
register int values_printed = 0;
nsyms = BLOCK_NSYMS (b);
for (i = 0; i < nsyms; i++)
{
sym = BLOCK_SYM (b, i);
if (SYMBOL_CLASS (sym) == LOC_LOCAL
|| SYMBOL_CLASS (sym) == LOC_REGISTER
|| SYMBOL_CLASS (sym) == LOC_STATIC)
{
values_printed = 1;
fputs_filtered (SYMBOL_NAME (sym), stream);
fputs_filtered (" = ", stream);
print_variable_value (sym, frame, stream);
fprintf_filtered (stream, "\n");
fflush (stream);
}
}
return values_printed;
}
/* Print on STREAM all the local variables in frame FRAME,
including all the blocks active in that frame
at its current pc.
Returns 1 if the job was done,
or 0 if nothing was printed because we have no info
on the function running in FRAME. */
static int
print_frame_local_vars (frame, stream)
register FRAME frame;
register FILE *stream;
{
register struct block *block = get_frame_block (frame);
register int values_printed = 0;
if (block == 0)
{
fprintf_filtered (stream, "No symbol table info available.\n");
fflush (stream);
return 0;
}
while (block != 0)
{
if (print_block_frame_locals (block, frame, stream))
values_printed = 1;
/* After handling the function's top-level block, stop.
Don't continue to its superblock, the block of
per-file symbols. */
if (BLOCK_FUNCTION (block))
break;
block = BLOCK_SUPERBLOCK (block);
}
if (!values_printed)
{
fprintf_filtered (stream, "No locals.\n");
fflush (stream);
}
return 1;
}
static void
locals_info ()
{
if (!have_inferior_p () && !have_core_file_p ())
error ("No inferior or core file.");
print_frame_local_vars (selected_frame, stdout);
}
static int
print_frame_arg_vars (frame, stream)
register FRAME frame;
register FILE *stream;
{
struct symbol *func = get_frame_function (frame);
register struct block *b;
int nsyms;
register int i;
register struct symbol *sym;
register int values_printed = 0;
if (func == 0)
{
fprintf_filtered (stream, "No symbol table info available.\n");
fflush (stream);
return 0;
}
b = SYMBOL_BLOCK_VALUE (func);
nsyms = BLOCK_NSYMS (b);
for (i = 0; i < nsyms; i++)
{
sym = BLOCK_SYM (b, i);
if (SYMBOL_CLASS (sym) == LOC_ARG
|| SYMBOL_CLASS (sym) == LOC_REF_ARG
|| SYMBOL_CLASS (sym) == LOC_REGPARM)
{
values_printed = 1;
fputs_filtered (SYMBOL_NAME (sym), stream);
fputs_filtered (" = ", stream);
print_variable_value (sym, frame, stream);
fprintf_filtered (stream, "\n");
fflush (stream);
}
}
if (!values_printed)
{
fprintf_filtered (stream, "No arguments.\n");
fflush (stream);
}
return 1;
}
static void
args_info ()
{
if (!have_inferior_p () && !have_core_file_p ())
error ("No inferior or core file.");
print_frame_arg_vars (selected_frame, stdout);
}
/* Select frame FRAME, and note that its stack level is LEVEL.
LEVEL may be -1 if an actual level number is not known. */
void
select_frame (frame, level)
FRAME frame;
int level;
{
selected_frame = frame;
selected_frame_level = level;
/* Ensure that symbols for this frame are readin. */
if (frame)
find_pc_symtab (get_frame_info (frame)->pc);
}
/* Store the selected frame and its level into *FRAMEP and *LEVELP. */
void
record_selected_frame (frameaddrp, levelp)
FRAME_ADDR *frameaddrp;
int *levelp;
{
*frameaddrp = FRAME_FP (selected_frame);
*levelp = selected_frame_level;
}
/* Return the symbol-block in which the selected frame is executing.
Can return zero under various legitimate circumstances. */
struct block *
get_selected_block ()
{
if (!have_inferior_p () && !have_core_file_p ())
return 0;
if (!selected_frame)
return get_current_block ();
return get_frame_block (selected_frame);
}
/* Find a frame a certain number of levels away from FRAME.
LEVEL_OFFSET_PTR points to an int containing the number of levels.
Positive means go to earlier frames (up); negative, the reverse.
The int that contains the number of levels is counted toward
zero as the frames for those levels are found.
If the top or bottom frame is reached, that frame is returned,
but the final value of *LEVEL_OFFSET_PTR is nonzero and indicates
how much farther the original request asked to go. */
FRAME
find_relative_frame (frame, level_offset_ptr)
register FRAME frame;
register int* level_offset_ptr;
{
register FRAME prev;
register FRAME frame1, frame2;
/* Going up is simple: just do get_prev_frame enough times
or until initial frame is reached. */
while (*level_offset_ptr > 0)
{
prev = get_prev_frame (frame);
if (prev == 0)
break;
(*level_offset_ptr)--;
frame = prev;
}
/* Going down could be done by iterating get_frame_info to
find the next frame, but that would be quadratic
since get_frame_info must scan all the way from the current frame.
The following algorithm is linear. */
if (*level_offset_ptr < 0)
{
/* First put frame1 at innermost frame
and frame2 N levels up from there. */
frame1 = get_current_frame ();
frame2 = frame1;
while (*level_offset_ptr < 0 && frame2 != frame)
{
frame2 = get_prev_frame (frame2);
(*level_offset_ptr) ++;
}
/* Then slide frame1 and frame2 up in synchrony
and when frame2 reaches our starting point
frame1 must be N levels down from there. */
while (frame2 != frame)
{
frame1 = get_prev_frame (frame1);
frame2 = get_prev_frame (frame2);
}
return frame1;
}
return frame;
}
/* The "frame" command. With no arg, print selected frame briefly.
With arg LEVEL_EXP, select the frame at level LEVEL if it is a
valid level. Otherwise, treat level_exp as an address expression
and print it. See parse_frame_specification for more info on proper
frame expressions. */
static void
frame_command (level_exp, from_tty)
char *level_exp;
int from_tty;
{
register FRAME frame, frame1;
unsigned int level = 0;
if (!have_inferior_p () && ! have_core_file_p ())
error ("No inferior or core file.");
frame = parse_frame_specification (level_exp);
for (frame1 = get_prev_frame (0);
frame1 && frame1 != frame;
frame1 = get_prev_frame (frame1))
level++;
if (!frame1)
level = 0;
frame_changed = level;
select_frame (frame, level);
if (!from_tty)
return;
print_stack_frame (selected_frame, selected_frame_level, 1);
}
/* Select the frame up one or COUNT stack levels
from the previously selected frame, and print it briefly. */
static void
up_command (count_exp)
char *count_exp;
{
register FRAME frame;
int count = 1, count1;
if (count_exp)
count = parse_and_eval_address (count_exp);
count1 = count;
if (!have_inferior_p () && !have_core_file_p ())
error ("No inferior or core file.");
frame = find_relative_frame (selected_frame, &count1);
if (count1 != 0 && count_exp == 0)
error ("Initial frame selected; you cannot go up.");
select_frame (frame, selected_frame_level + count - count1);
print_stack_frame (selected_frame, selected_frame_level, 1);
frame_changed++;
}
/* Select the frame down one or COUNT stack levels
from the previously selected frame, and print it briefly. */
static void
down_command (count_exp)
char *count_exp;
{
register FRAME frame;
int count = -1, count1;
if (count_exp)
count = - parse_and_eval_address (count_exp);
count1 = count;
frame = find_relative_frame (selected_frame, &count1);
if (count1 != 0 && count_exp == 0)
error ("Bottom (i.e., innermost) frame selected; you cannot go down.");
select_frame (frame, selected_frame_level + count - count1);
print_stack_frame (selected_frame, selected_frame_level, 1);
frame_changed--;
}
static void
return_command (retval_exp, from_tty)
char *retval_exp;
int from_tty;
{
value return_value;
struct symbol *thisfun = get_frame_function (selected_frame);
FRAME_ADDR selected_frame_addr = FRAME_FP (selected_frame);
/* If interactive, require confirmation. */
if (from_tty)
{
if (thisfun != 0)
{
if (!query ("Make %s return now? ", SYMBOL_NAME (thisfun)))
error ("Not confirmed.");
}
else
if (!query ("Make selected stack frame return now? "))
error ("Not confirmed.");
}
/* Do the real work. Pop until the specified frame is current. We
use this method because the selected_frame is not valid after
a POP_FRAME. Note that this will not work if the selected frame
shares it's fp with another frame. */
while (selected_frame_addr != FRAME_FP (get_current_frame()))
POP_FRAME;
/* get the return value while still in this frame */
if (retval_exp)
return_value = parse_and_eval (retval_exp);
/* Then pop that frame. */
POP_FRAME;
/* Store the return value if there was one */
if (retval_exp)
set_return_value (return_value);
/* If interactive, print the frame that is now current. */
if (from_tty)
frame_command ("0", 1);
}
extern struct cmd_list_element *setlist;
void
_initialize_stack ()
{
#if 0
backtrace_limit = 30;
#endif
add_com ("return", class_stack, return_command,
"Make selected stack frame return to its caller.\n\
Control remains in the debugger, but when you continue\n\
execution will resume in the frame above the one now selected.\n\
If an argument is given, it is an expression for the value to return.");
add_com ("up", class_stack, up_command,
"Select and print stack frame that called this one.\n\
An argument says how many frames up to go.");
add_com ("down", class_stack, down_command,
"Select and print stack frame called by this one.\n\
An argument says how many frames down to go.");
add_com_alias ("do", "down", class_stack, 1);
add_com ("frame", class_stack, frame_command,
"Select and print a stack frame.\n\
With no argument, print the selected stack frame. (See also \"info frame\").\n\
An argument specifies the frame to select.\n\
It can be a stack frame number or the address of the frame.\n\
With argument, nothing is printed if input is coming from\n\
a command file or a user-defined command.");
add_com_alias ("f", "frame", class_stack, 1);
add_com ("backtrace", class_stack, backtrace_command,
"Print backtrace of all stack frames, or innermost COUNT frames.\n\
With a negative argument, print outermost -COUNT frames.");
add_com_alias ("bt", "backtrace", class_stack, 0);
add_com_alias ("where", "backtrace", class_alias, 0);
add_info ("stack", backtrace_command,
"Backtrace of the stack, or innermost COUNT frames.");
add_info_alias ("s", "stack", 1);
add_info ("frame", frame_info,
"All about selected stack frame, or frame at ADDR.");
add_info_alias ("f", "frame", 1);
add_info ("locals", locals_info,
"Local variables of current stack frame.");
add_info ("args", args_info,
"Argument variables of current stack frame.");
#if 0
add_cmd ("backtrace-limit", class_stack, set_backtrace_limit_command,
"Specify maximum number of frames for \"backtrace\" to print by default.",
&setlist);
add_info ("backtrace-limit", backtrace_limit_info,
"The maximum number of frames for \"backtrace\" to print by default.");
#endif
}

584
gnu/usr.bin/gdb/symmisc.c Normal file
View file

@ -0,0 +1,584 @@
/* Do various things to symbol tables (other than lookup)), for GDB.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "symtab.h"
#include <stdio.h>
#include <obstack.h>
static void free_symtab ();
/* Free all the symtabs that are currently installed,
and all storage associated with them.
Leaves us in a consistent state with no symtabs installed. */
void
free_all_symtabs ()
{
register struct symtab *s, *snext;
/* All values will be invalid because their types will be! */
clear_value_history ();
clear_displays ();
clear_internalvars ();
clear_breakpoints ();
set_default_breakpoint (0, 0, 0, 0);
current_source_symtab = 0;
for (s = symtab_list; s; s = snext)
{
snext = s->next;
free_symtab (s);
}
symtab_list = 0;
obstack_free (symbol_obstack, 0);
obstack_init (symbol_obstack);
if (misc_function_vector)
free (misc_function_vector);
misc_function_count = 0;
misc_function_vector = 0;
}
/* Free a struct block <- B and all the symbols defined in that block. */
static void
free_symtab_block (b)
struct block *b;
{
register int i, n;
n = BLOCK_NSYMS (b);
for (i = 0; i < n; i++)
{
free (SYMBOL_NAME (BLOCK_SYM (b, i)));
free (BLOCK_SYM (b, i));
}
free (b);
}
/* Free all the storage associated with the struct symtab <- S.
Note that some symtabs have contents malloc'ed structure by structure,
while some have contents that all live inside one big block of memory,
and some share the contents of another symbol table and so you should
not free the contents on their behalf (except sometimes the linetable,
which maybe per symtab even when the rest is not).
It is s->free_code that says which alternative to use. */
static void
free_symtab (s)
register struct symtab *s;
{
register int i, n;
register struct blockvector *bv;
register struct type *type;
register struct typevector *tv;
switch (s->free_code)
{
case free_nothing:
/* All the contents are part of a big block of memory
and some other symtab is in charge of freeing that block.
Therefore, do nothing. */
break;
case free_contents:
/* Here all the contents were malloc'ed structure by structure
and must be freed that way. */
/* First free the blocks (and their symbols. */
bv = BLOCKVECTOR (s);
n = BLOCKVECTOR_NBLOCKS (bv);
for (i = 0; i < n; i++)
free_symtab_block (BLOCKVECTOR_BLOCK (bv, i));
/* Free the blockvector itself. */
free (bv);
/* Free the type vector. */
tv = TYPEVECTOR (s);
free (tv);
/* Also free the linetable. */
case free_linetable:
/* Everything will be freed either by our `free_ptr'
or by some other symbatb, except for our linetable.
Free that now. */
free (LINETABLE (s));
break;
}
/* If there is a single block of memory to free, free it. */
if (s->free_ptr)
free (s->free_ptr);
if (s->line_charpos)
free (s->line_charpos);
free (s->filename);
free (s);
}
/* Convert a raw symbol-segment to a struct symtab,
and relocate its internal pointers so that it is valid. */
/* This is how to relocate one pointer, given a name for it.
Works independent of the type of object pointed to. */
#define RELOCATE(slot) (slot ? (* (char **) &slot += relocation) : 0)
/* This is the inverse of RELOCATE. We use it when storing
a core address into a slot that has yet to be relocated. */
#define UNRELOCATE(slot) (slot ? (* (char **) &slot -= relocation) : 0)
/* During the process of relocation, this holds the amount to relocate by
(the address of the file's symtab data, in core in the debugger). */
static int relocation;
#define CORE_RELOCATE(slot) \
((slot) += (((slot) < data_start) ? text_relocation \
: ((slot) < bss_start) ? data_relocation : bss_relocation))
#define TEXT_RELOCATE(slot) ((slot) += text_relocation)
/* Relocation amounts for addresses in the program's core image. */
static int text_relocation, data_relocation, bss_relocation;
/* Boundaries that divide program core addresses into text, data and bss;
used to determine which relocation amount to use. */
static int data_start, bss_start;
static void relocate_typevector ();
static void relocate_blockvector ();
static void relocate_type ();
static void relocate_block ();
static void relocate_symbol ();
static void relocate_source ();
/* Relocate a file's symseg so that all the pointers are valid C pointers.
Value is a `struct symtab'; but it is not suitable for direct
insertion into the `symtab_list' because it describes several files. */
static struct symtab *
relocate_symtab (root)
struct symbol_root *root;
{
struct symtab *sp = (struct symtab *) xmalloc (sizeof (struct symtab));
bzero (sp, sizeof (struct symtab));
relocation = (int) root;
text_relocation = root->textrel;
data_relocation = root->datarel;
bss_relocation = root->bssrel;
data_start = root->databeg;
bss_start = root->bssbeg;
sp->filename = root->filename;
sp->ldsymoff = root->ldsymoff;
sp->language = root->language;
sp->compilation = root->compilation;
sp->version = root->version;
sp->blockvector = root->blockvector;
sp->typevector = root->typevector;
RELOCATE (TYPEVECTOR (sp));
RELOCATE (BLOCKVECTOR (sp));
RELOCATE (sp->version);
RELOCATE (sp->compilation);
RELOCATE (sp->filename);
relocate_typevector (TYPEVECTOR (sp));
relocate_blockvector (BLOCKVECTOR (sp));
return sp;
}
static void
relocate_blockvector (blp)
register struct blockvector *blp;
{
register int nblocks = BLOCKVECTOR_NBLOCKS (blp);
register int i;
for (i = 0; i < nblocks; i++)
RELOCATE (BLOCKVECTOR_BLOCK (blp, i));
for (i = 0; i < nblocks; i++)
relocate_block (BLOCKVECTOR_BLOCK (blp, i));
}
static void
relocate_block (bp)
register struct block *bp;
{
register int nsyms = BLOCK_NSYMS (bp);
register int i;
TEXT_RELOCATE (BLOCK_START (bp));
TEXT_RELOCATE (BLOCK_END (bp));
/* These two should not be recursively processed.
The superblock need not be because all blocks are
processed from relocate_blockvector.
The function need not be because it will be processed
under the block which is its scope. */
RELOCATE (BLOCK_SUPERBLOCK (bp));
RELOCATE (BLOCK_FUNCTION (bp));
for (i = 0; i < nsyms; i++)
RELOCATE (BLOCK_SYM (bp, i));
for (i = 0; i < nsyms; i++)
relocate_symbol (BLOCK_SYM (bp, i));
}
static void
relocate_symbol (sp)
register struct symbol *sp;
{
RELOCATE (SYMBOL_NAME (sp));
if (SYMBOL_CLASS (sp) == LOC_BLOCK)
{
RELOCATE (SYMBOL_BLOCK_VALUE (sp));
/* We can assume the block that belongs to this symbol
is not relocated yet, since it comes after
the block that contains this symbol. */
BLOCK_FUNCTION (SYMBOL_BLOCK_VALUE (sp)) = sp;
UNRELOCATE (BLOCK_FUNCTION (SYMBOL_BLOCK_VALUE (sp)));
}
else if (SYMBOL_CLASS (sp) == LOC_STATIC)
CORE_RELOCATE (SYMBOL_VALUE (sp));
else if (SYMBOL_CLASS (sp) == LOC_LABEL)
TEXT_RELOCATE (SYMBOL_VALUE (sp));
RELOCATE (SYMBOL_TYPE (sp));
}
static void
relocate_typevector (tv)
struct typevector *tv;
{
register int ntypes = TYPEVECTOR_NTYPES (tv);
register int i;
for (i = 0; i < ntypes; i++)
RELOCATE (TYPEVECTOR_TYPE (tv, i));
for (i = 0; i < ntypes; i++)
relocate_type (TYPEVECTOR_TYPE (tv, i));
}
/* We cannot come up with an a priori spanning tree
for the network of types, since types can be used
for many symbols and also as components of other types.
Therefore, we need to be able to mark types that we
already have relocated (or are already in the middle of relocating)
as in a garbage collector. */
static void
relocate_type (tp)
register struct type *tp;
{
register int nfields = TYPE_NFIELDS (tp);
register int i;
RELOCATE (TYPE_NAME (tp));
RELOCATE (TYPE_TARGET_TYPE (tp));
RELOCATE (TYPE_FIELDS (tp));
RELOCATE (TYPE_POINTER_TYPE (tp));
for (i = 0; i < nfields; i++)
{
RELOCATE (TYPE_FIELD_TYPE (tp, i));
RELOCATE (TYPE_FIELD_NAME (tp, i));
}
}
static void
relocate_sourcevector (svp)
register struct sourcevector *svp;
{
register int nfiles = svp->length;
register int i;
for (i = 0; i < nfiles; i++)
RELOCATE (svp->source[i]);
for (i = 0; i < nfiles; i++)
relocate_source (svp->source[i]);
}
static void
relocate_source (sp)
register struct source *sp;
{
register int nitems = sp->contents.nitems;
register int i;
RELOCATE (sp->name);
for (i = 0; i < nitems; i++)
TEXT_RELOCATE (sp->contents.item[i].pc);
}
/* Read symsegs from file named NAME open on DESC,
make symtabs from them, and return a chain of them.
These symtabs are not suitable for direct use in `symtab_list'
because each one describes a single object file, perhaps many source files.
`symbol_file_command' takes each of these, makes many real symtabs
from it, and then frees it.
We assume DESC is prepositioned at the end of the string table,
just before the symsegs if there are any. */
struct symtab *
read_symsegs (desc, name)
int desc;
char *name;
{
struct symbol_root root;
register char *data;
register struct symtab *sp, *sp1, *chain = 0;
register int len;
while (1)
{
len = myread (desc, &root, sizeof root);
if (len == 0 || root.format == 0)
break;
/* format 1 was ok for the original gdb, but since the size of the
type structure changed when C++ support was added, it can no
longer be used. Accept only format 2. */
if (root.format != 2 ||
root.length < sizeof root)
error ("\nInvalid symbol segment format code");
data = (char *) xmalloc (root.length);
bcopy (&root, data, sizeof root);
len = myread (desc, data + sizeof root,
root.length - sizeof root);
sp = relocate_symtab (data);
RELOCATE (((struct symbol_root *)data)->sourcevector);
relocate_sourcevector (((struct symbol_root *)data)->sourcevector);
sp->next = chain;
chain = sp;
sp->linetable = (struct linetable *) ((struct symbol_root *)data)->sourcevector;
}
return chain;
}
static int block_depth ();
void print_spaces ();
static void print_symbol ();
void
print_symtabs (filename)
char *filename;
{
FILE *outfile;
register struct symtab *s;
register int i, j;
int len, line, blen;
register struct linetable *l;
struct blockvector *bv;
register struct block *b;
int depth;
struct cleanup *cleanups;
extern int fclose();
if (filename == 0)
error_no_arg ("file to write symbol data in");
filename = tilde_expand (filename);
make_cleanup (free, filename);
outfile = fopen (filename, "w");
if (outfile == 0)
perror_with_name (filename);
cleanups = make_cleanup (fclose, outfile);
immediate_quit++;
for (s = symtab_list; s; s = s->next)
{
/* First print the line table. */
fprintf (outfile, "Symtab for file %s\n\n", s->filename);
fprintf (outfile, "Line table:\n\n");
l = LINETABLE (s);
len = l->nitems;
for (i = 0; i < len; i++)
fprintf (outfile, " line %d at %x\n", l->item[i].line,
l->item[i].pc);
/* Now print the block info. */
fprintf (outfile, "\nBlockvector:\n\n");
bv = BLOCKVECTOR (s);
len = BLOCKVECTOR_NBLOCKS (bv);
for (i = 0; i < len; i++)
{
b = BLOCKVECTOR_BLOCK (bv, i);
depth = block_depth (b) * 2;
print_spaces (depth, outfile);
fprintf (outfile, "block #%03d (object 0x%x) ", i, b);
fprintf (outfile, "[0x%x..0x%x]", BLOCK_START (b), BLOCK_END (b));
if (BLOCK_SUPERBLOCK (b))
fprintf (outfile, " (under 0x%x)", BLOCK_SUPERBLOCK (b));
if (BLOCK_FUNCTION (b))
fprintf (outfile, " %s", SYMBOL_NAME (BLOCK_FUNCTION (b)));
fputc ('\n', outfile);
blen = BLOCK_NSYMS (b);
for (j = 0; j < blen; j++)
{
print_symbol (BLOCK_SYM (b, j), depth + 1, outfile);
}
}
fprintf (outfile, "\n\n");
}
immediate_quit--;
do_cleanups (cleanups);
}
static void
print_symbol (symbol, depth, outfile)
struct symbol *symbol;
int depth;
FILE *outfile;
{
print_spaces (depth, outfile);
if (SYMBOL_NAMESPACE (symbol) == LABEL_NAMESPACE)
{
fprintf (outfile, "label %s at 0x%x\n", SYMBOL_NAME (symbol),
SYMBOL_VALUE (symbol));
return;
}
if (SYMBOL_NAMESPACE (symbol) == STRUCT_NAMESPACE)
{
if (TYPE_NAME (SYMBOL_TYPE (symbol)))
{
type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth);
}
else
{
fprintf (outfile, "%s %s = ",
(TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_ENUM
? "enum"
: (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_STRUCT
? "struct" : "union")),
SYMBOL_NAME (symbol));
type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth);
}
fprintf (outfile, ";\n");
}
else
{
if (SYMBOL_CLASS (symbol) == LOC_TYPEDEF)
fprintf (outfile, "typedef ");
if (SYMBOL_TYPE (symbol))
{
type_print_1 (SYMBOL_TYPE (symbol), SYMBOL_NAME (symbol),
outfile, 1, depth);
fprintf (outfile, "; ");
}
else
fprintf (outfile, "%s ", SYMBOL_NAME (symbol));
switch (SYMBOL_CLASS (symbol))
{
case LOC_CONST:
fprintf (outfile, "const %d (0x%x),",
SYMBOL_VALUE (symbol), SYMBOL_VALUE (symbol));
break;
case LOC_CONST_BYTES:
fprintf (outfile, "const %d hex bytes:",
TYPE_LENGTH (SYMBOL_TYPE (symbol)));
{
int i;
for (i = 0; i < TYPE_LENGTH (SYMBOL_TYPE (symbol)); i++)
fprintf (outfile, " %2x", SYMBOL_VALUE_BYTES (symbol) [i]);
fprintf (outfile, ",");
}
break;
case LOC_STATIC:
fprintf (outfile, "static at 0x%x,", SYMBOL_VALUE (symbol));
break;
case LOC_REGISTER:
fprintf (outfile, "register %d,", SYMBOL_VALUE (symbol));
break;
case LOC_ARG:
fprintf (outfile, "arg at 0x%x,", SYMBOL_VALUE (symbol));
break;
case LOC_REF_ARG:
fprintf (outfile, "reference arg at 0x%x,", SYMBOL_VALUE (symbol));
break;
case LOC_REGPARM:
fprintf (outfile, "parameter register %d,", SYMBOL_VALUE (symbol));
break;
case LOC_LOCAL:
fprintf (outfile, "local at 0x%x,", SYMBOL_VALUE (symbol));
break;
case LOC_TYPEDEF:
break;
case LOC_LABEL:
fprintf (outfile, "label at 0x%x", SYMBOL_VALUE (symbol));
break;
case LOC_BLOCK:
fprintf (outfile, "block (object 0x%x) starting at 0x%x,",
SYMBOL_VALUE (symbol),
BLOCK_START (SYMBOL_BLOCK_VALUE (symbol)));
break;
}
}
fprintf (outfile, "\n");
}
/* Return the nexting depth of a block within other blocks in its symtab. */
static int
block_depth (block)
struct block *block;
{
register int i = 0;
while (block = BLOCK_SUPERBLOCK (block)) i++;
return i;
}
/*
* Free all partial_symtab storage.
*/
void
free_all_psymtabs()
{
obstack_free (psymbol_obstack, 0);
obstack_init (psymbol_obstack);
partial_symtab_list = (struct partial_symtab *) 0;
}
void
_initialize_symmisc ()
{
symtab_list = (struct symtab *) 0;
partial_symtab_list = (struct partial_symtab *) 0;
add_com ("printsyms", class_obscure, print_symtabs,
"Print dump of current symbol definitions to file OUTFILE.");
}

523
gnu/usr.bin/gdb/symseg.h Normal file
View file

@ -0,0 +1,523 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
* Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
*
* @(#)symseg.h 6.3 (Berkeley) 5/8/91
*/
/* GDB symbol table format definitions.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@mcc.com)
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Format of GDB symbol table data.
There is one symbol segment for each source file or
independant compilation. These segments are simply concatenated
to form the GDB symbol table. A zero word where the beginning
of a segment is expected indicates there are no more segments.
Format of a symbol segment:
The symbol segment begins with a word containing 1
if it is in the format described here. Other formats may
be designed, with other code numbers.
The segment contains many objects which point at each other.
The pointers are offsets in bytes from the beginning of the segment.
Thus, each segment can be loaded into core and its pointers relocated
to make valid in-core pointers.
All the data objects in the segment can be found indirectly from
one of them, the root object, of type `struct symbol_root'.
It appears at the beginning of the segment.
The total size of the segment, in bytes, appears as the `length'
field of this object. This size includes the size of the
root object.
All the object data types are defined here to contain pointer types
appropriate for in-core use on a relocated symbol segment.
Casts to and from type int are required for working with
unrelocated symbol segments such as are found in the file.
The ldsymaddr word is filled in by the loader to contain
the offset (in bytes) within the ld symbol table
of the first nonglobal symbol from this compilation.
This makes it possible to match those symbols
(which contain line number information) reliably with
the segment they go with.
Core addresses within the program that appear in the symbol segment
are not relocated by the loader. They are inserted by the assembler
and apply to addresses as output by the assembler, so GDB must
relocate them when it loads the symbol segment. It gets the information
on how to relocate from the textrel, datarel, bssrel, databeg and bssbeg
words of the root object.
The words textrel, datarel and bssrel
are filled in by ld with the amounts to relocate within-the-file
text, data and bss addresses by; databeg and bssbeg can be
used to tell which kind of relocation an address needs. */
enum language {language_c};
struct symbol_root
{
int format; /* Data format version */
int length; /* # bytes in this symbol segment */
int ldsymoff; /* Offset in ld symtab of this file's syms */
int textrel; /* Relocation for text addresses */
int datarel; /* Relocation for data addresses */
int bssrel; /* Relocation for bss addresses */
char *filename; /* Name of main source file compiled */
char *filedir; /* Name of directory it was reached from */
struct blockvector *blockvector; /* Vector of all symbol-naming blocks */
struct typevector *typevector; /* Vector of all data types */
enum language language; /* Code identifying the language used */
char *version; /* Version info. Not fully specified */
char *compilation; /* Compilation info. Not fully specified */
int databeg; /* Address within the file of data start */
int bssbeg; /* Address within the file of bss start */
struct sourcevector *sourcevector; /* Vector of line-number info */
};
/* All data types of symbols in the compiled program
are represented by `struct type' objects.
All of these objects are pointed to by the typevector.
The type vector may have empty slots that contain zero. */
struct typevector
{
int length; /* Number of types described */
struct type *type[1];
};
/* Different kinds of data types are distinguished by the `code' field. */
enum type_code
{
TYPE_CODE_UNDEF, /* Not used; catches errors */
TYPE_CODE_PTR, /* Pointer type */
TYPE_CODE_ARRAY, /* Array type, lower bound zero */
TYPE_CODE_STRUCT, /* C struct or Pascal record */
TYPE_CODE_UNION, /* C union or Pascal variant part */
TYPE_CODE_ENUM, /* Enumeration type */
TYPE_CODE_FUNC, /* Function type */
TYPE_CODE_INT, /* Integer type */
TYPE_CODE_FLT, /* Floating type */
TYPE_CODE_VOID, /* Void type (values zero length) */
TYPE_CODE_SET, /* Pascal sets */
TYPE_CODE_RANGE, /* Range (integers within spec'd bounds) */
TYPE_CODE_PASCAL_ARRAY, /* Array with explicit type of index */
/* C++ */
TYPE_CODE_MEMBER, /* Member type */
TYPE_CODE_METHOD, /* Method type */
TYPE_CODE_REF, /* C++ Reference types */
};
/* This appears in a type's flags word for an unsigned integer type. */
#define TYPE_FLAG_UNSIGNED 1
/* This appears in a type's flags word
if it is a (pointer to a|function returning a)* built in scalar type.
These types are never freed. */
#define TYPE_FLAG_PERM 4
/* This appears in a type's flags word if it is a stub type (eg. if
someone referenced a type that wasn't definined in a source file
via (struct sir_not_appearing_in_this_film *)). */
#define TYPE_FLAG_STUB 8
/* Set when a class has a constructor defined */
#define TYPE_FLAG_HAS_CONSTRUCTOR 256
/* Set when a class has a destructor defined */
#define TYPE_FLAG_HAS_DESTRUCTOR 512
/* Indicates that this type is a public baseclass of another class,
i.e. that all its public methods are available in the derived
class. */
#define TYPE_FLAG_VIA_PUBLIC 1024
/* Indicates that this type is a virtual baseclass of another class,
i.e. that if this class is inherited more than once by another
class, only one set of member variables will be included. */
#define TYPE_FLAG_VIA_VIRTUAL 2048
struct type
{
/* Code for kind of type */
enum type_code code;
/* Name of this type, or zero if none.
This is used for printing only.
Type names specified as input are defined by symbols. */
char *name;
/* Length in bytes of storage for a value of this type */
int length;
/* For a pointer type, describes the type of object pointed to.
For an array type, describes the type of the elements.
For a function or method type, describes the type of the value.
For a range type, describes the type of the full range.
Unused otherwise. */
struct type *target_type;
/* Type that is a pointer to this type.
Zero if no such pointer-to type is known yet.
The debugger may add the address of such a type
if it has to construct one later. */
struct type *pointer_type;
/* C++: also need a reference type. */
struct type *reference_type;
struct type **arg_types;
/* Type that is a function returning this type.
Zero if no such function type is known here.
The debugger may add the address of such a type
if it has to construct one later. */
struct type *function_type;
/* Handling of pointers to members:
TYPE_MAIN_VARIANT is used for pointer and pointer
to member types. Normally it the value of the address of its
containing type. However, for pointers to members, we must be
able to allocate pointer to member types and look them up
from some place of reference.
NEXT_VARIANT is the next element in the chain. */
struct type *main_variant, *next_variant;
/* Flags about this type. */
short flags;
/* Number of fields described for this type */
short nfields;
/* For structure and union types, a description of each field.
For set and pascal array types, there is one "field",
whose type is the domain type of the set or array.
For range types, there are two "fields",
the minimum and maximum values (both inclusive).
For enum types, each possible value is described by one "field".
Using a pointer to a separate array of fields
allows all types to have the same size, which is useful
because we can allocate the space for a type before
we know what to put in it. */
struct field
{
/* Position of this field, counting in bits from start of
containing structure. For a function type, this is the
position in the argument list of this argument.
For a range bound or enum value, this is the value itself. */
int bitpos;
/* Size of this field, in bits, or zero if not packed.
For an unpacked field, the field's type's length
says how many bytes the field occupies. */
int bitsize;
/* In a struct or enum type, type of this field.
In a function type, type of this argument.
In an array type, the domain-type of the array. */
struct type *type;
/* Name of field, value or argument.
Zero for range bounds and array domains. */
char *name;
} *fields;
/* C++ */
int *private_field_bits;
int *protected_field_bits;
/* Number of methods described for this type */
short nfn_fields;
/* Number of base classes this type derives from. */
short n_baseclasses;
/* Number of methods described for this type plus all the
methods that it derives from. */
int nfn_fields_total;
/* For classes, structures, and unions, a description of each field,
which consists of an overloaded name, followed by the types of
arguments that the method expects, and then the name after it
has been renamed to make it distinct. */
struct fn_fieldlist
{
/* The overloaded name. */
char *name;
/* The number of methods with this name. */
int length;
/* The list of methods. */
struct fn_field
{
#if 0
/* The overloaded name */
char *name;
#endif
/* The return value of the method */
struct type *type;
/* The argument list */
struct type **args;
/* The name after it has been processed */
char *physname;
/* If this is a virtual function, the offset into the vtbl-1,
else 0. */
int voffset;
} *fn_fields;
int *private_fn_field_bits;
int *protected_fn_field_bits;
} *fn_fieldlists;
unsigned char via_protected;
unsigned char via_public;
/* For types with virtual functions, VPTR_BASETYPE is the base class which
defined the virtual function table pointer. VPTR_FIELDNO is
the field number of that pointer in the structure.
For types that are pointer to member types, VPTR_BASETYPE
ifs the type that this pointer is a member of.
Unused otherwise. */
struct type *vptr_basetype;
int vptr_fieldno;
/* If this type has a base class, put it here.
If this type is a pointer type, the chain of member pointer
types goes here.
Unused otherwise.
Contrary to all maxims of C style and common sense, the baseclasses
are indexed from 1 to N_BASECLASSES rather than 0 to N_BASECLASSES-1
(i.e. BASECLASSES points to one *before* the first element of
the array). */
struct type **baseclasses;
};
/* All of the name-scope contours of the program
are represented by `struct block' objects.
All of these objects are pointed to by the blockvector.
Each block represents one name scope.
Each lexical context has its own block.
The first two blocks in the blockvector are special.
The first one contains all the symbols defined in this compilation
whose scope is the entire program linked together.
The second one contains all the symbols whose scope is the
entire compilation excluding other separate compilations.
In C, these correspond to global symbols and static symbols.
Each block records a range of core addresses for the code that
is in the scope of the block. The first two special blocks
give, for the range of code, the entire range of code produced
by the compilation that the symbol segment belongs to.
The blocks appear in the blockvector
in order of increasing starting-address,
and, within that, in order of decreasing ending-address.
This implies that within the body of one function
the blocks appear in the order of a depth-first tree walk. */
struct blockvector
{
/* Number of blocks in the list. */
int nblocks;
/* The blocks themselves. */
struct block *block[1];
};
struct block
{
/* Addresses in the executable code that are in this block.
Note: in an unrelocated symbol segment in a file,
these are always zero. They can be filled in from the
N_LBRAC and N_RBRAC symbols in the loader symbol table. */
int startaddr, endaddr;
/* The symbol that names this block,
if the block is the body of a function;
otherwise, zero.
Note: In an unrelocated symbol segment in an object file,
this field may be zero even when the block has a name.
That is because the block is output before the name
(since the name resides in a higher block).
Since the symbol does point to the block (as its value),
it is possible to find the block and set its name properly. */
struct symbol *function;
/* The `struct block' for the containing block, or 0 if none. */
/* Note that in an unrelocated symbol segment in an object file
this pointer may be zero when the correct value should be
the second special block (for symbols whose scope is one compilation).
This is because the compiler ouptuts the special blocks at the
very end, after the other blocks. */
struct block *superblock;
/* A flag indicating whether or not the fucntion corresponding
to this block was compiled with gcc or not. If there is no
function corresponding to this block, this meaning of this flag
is undefined. (In practice it will be 1 if the block was created
while processing a file compiled with gcc and 0 when not). */
unsigned char gcc_compile_flag;
/* Number of local symbols. */
int nsyms;
/* The symbols. */
struct symbol *sym[1];
};
/* Represent one symbol name; a variable, constant, function or typedef. */
/* Different name spaces for symbols. Looking up a symbol specifies
a namespace and ignores symbol definitions in other name spaces.
VAR_NAMESPACE is the usual namespace.
In C, this contains variables, function names, typedef names
and enum type values.
STRUCT_NAMESPACE is used in C to hold struct, union and enum type names.
Thus, if `struct foo' is used in a C program,
it produces a symbol named `foo' in the STRUCT_NAMESPACE.
LABEL_NAMESPACE may be used for names of labels (for gotos);
currently it is not used and labels are not recorded at all. */
/* For a non-global symbol allocated statically,
the correct core address cannot be determined by the compiler.
The compiler puts an index number into the symbol's value field.
This index number can be matched with the "desc" field of
an entry in the loader symbol table. */
enum namespace
{
UNDEF_NAMESPACE, VAR_NAMESPACE, STRUCT_NAMESPACE, LABEL_NAMESPACE,
};
/* An address-class says where to find the value of the symbol in core. */
enum address_class
{
LOC_UNDEF, /* Not used; catches errors */
LOC_CONST, /* Value is constant int */
LOC_STATIC, /* Value is at fixed address */
LOC_REGISTER, /* Value is in register */
LOC_ARG, /* Value is at spec'd position in arglist */
LOC_REF_ARG, /* Value address is at spec'd position in */
/* arglist. */
LOC_REGPARM, /* Value is at spec'd position in register window */
LOC_LOCAL, /* Value is at spec'd pos in stack frame */
LOC_TYPEDEF, /* Value not used; definition in SYMBOL_TYPE
Symbols in the namespace STRUCT_NAMESPACE
all have this class. */
LOC_LABEL, /* Value is address in the code */
LOC_BLOCK, /* Value is address of a `struct block'.
Function names have this class. */
LOC_EXTERNAL, /* Value is at address not in this compilation.
This is used for .comm symbols
and for extern symbols within functions.
Inside GDB, this is changed to LOC_STATIC once the
real address is obtained from a loader symbol. */
LOC_CONST_BYTES /* Value is a constant byte-sequence. */
};
struct symbol
{
/* Symbol name */
char *name;
/* Name space code. */
enum namespace namespace;
/* Address class */
enum address_class class;
/* Data type of value */
struct type *type;
/* constant value, or address if static, or register number,
or offset in arguments, or offset in stack frame. */
union
{
long value;
struct block *block; /* for LOC_BLOCK */
char *bytes; /* for LOC_CONST_BYTES */
}
value;
};
struct partial_symbol
{
/* Symbol name */
char *name;
/* Name space code. */
enum namespace namespace;
/* Address class (for info_symbols) */
enum address_class class;
/* Associated partial symbol table */
struct partial_symtab *pst;
/* Value (only used for static functions currently). Done this
way so that we can use the struct symbol macros.
Note that the address of a function is SYMBOL_VALUE (pst)
in a partial symbol table, but BLOCK_START (SYMBOL_BLOCK_VALUE (st))
in a symbol table. */
union
{
long value;
}
value;
};
/*
* Vectors of all partial symbols read in from file; actually declared
* and used in dbxread.c.
*/
extern struct psymbol_allocation_list {
struct partial_symbol *list, *next;
int size;
} global_psymbols, static_psymbols;
/* Source-file information.
This describes the relation between source files and line numbers
and addresses in the program text. */
struct sourcevector
{
int length; /* Number of source files described */
struct source *source[1]; /* Descriptions of the files */
};
/* Each item represents a line-->pc (or the reverse) mapping. This is
somewhat more wasteful of space than one might wish, but since only
the files which are actually debugged are read in to core, we don't
waste much space.
Each item used to be an int; either minus a line number, or a
program counter. If it represents a line number, that is the line
described by the next program counter value. If it is positive, it
is the program counter at which the code for the next line starts. */
struct linetable_entry
{
int line;
CORE_ADDR pc;
};
struct linetable
{
int nitems;
struct linetable_entry item[1];
};
/* All the information on one source file. */
struct source
{
char *name; /* Name of file */
struct linetable contents;
};

2473
gnu/usr.bin/gdb/symtab.c Normal file

File diff suppressed because it is too large Load diff

384
gnu/usr.bin/gdb/symtab.h Normal file
View file

@ -0,0 +1,384 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
* Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
*
* @(#)symtab.h 6.3 (Berkeley) 5/8/91
*/
/* Symbol table definitions for GDB.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <obstack.h>
/* An obstack to hold objects that should be freed
when we load a new symbol table.
This includes the symbols made by dbxread
and the types that are not permanent. */
extern struct obstack *symbol_obstack;
extern struct obstack *psymbol_obstack;
/* Some definitions and declarations to go with use of obstacks. */
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
extern char *xmalloc ();
extern void free ();
/* gdb can know one or several symbol tables at the same time;
the ultimate intent is to have one for each separately-compiled module.
Each such symbol table is recorded by a struct symtab, and they
are all chained together. */
/* In addition, gdb can record any number of miscellaneous undebuggable
functions' addresses. In a system that appends _ to function names,
the _'s are removed from the names stored in this table. */
/* Actually, the misc function list is used to store *all* of the
global symbols (text, data, bss, and abs). It is sometimes used
to figure out what symtabs to read in. The "type" field appears
never to be used. */
enum misc_function_type {mf_unknown = 0, mf_text, mf_data, mf_bss, mf_abs};
struct misc_function
{
char *name;
CORE_ADDR address;
int next; /* index of next in this hash bucket */
unsigned char type; /* Really enum misc_function_type. */
};
/* Address and length of the vector recording all misc function names/addresses. */
struct misc_function *misc_function_vector;
int misc_function_count;
#define MISC_FUNC_HASH_SIZE (2048)
int misc_function_hash_tab[MISC_FUNC_HASH_SIZE];
#include "symseg.h"
/* Each source file is represented by a struct symtab. */
/* These objects are chained through the `next' field. */
struct symtab
{
/* Chain of all existing symtabs. */
struct symtab *next;
/* List of all symbol scope blocks for this symtab. */
struct blockvector *blockvector;
/* Table mapping core addresses to line numbers for this file. */
struct linetable *linetable;
/* Vector containing all types defined for this symtab. */
struct typevector *typevector;
/* Name of this source file. */
char *filename;
/* This component says how to free the data we point to:
free_contents => do a tree walk and free each object.
free_nothing => do nothing; some other symtab will free
the data this one uses.
free_linetable => free just the linetable. */
enum free_code {free_nothing, free_contents, free_linetable}
free_code;
/* Pointer to one block of storage to be freed, if nonzero. */
char *free_ptr;
/* Total number of lines found in source file. */
int nlines;
/* Array mapping line number to character position. */
int *line_charpos;
/* Language of this source file. */
enum language language;
/* String of version information. May be zero. */
char *version;
/* String of compilation information. May be zero. */
char *compilation;
/* Offset within loader symbol table
of first local symbol for this file. */
int ldsymoff;
/* Full name of file as found by searching the source path.
0 if not yet known. */
char *fullname;
};
/*
* Each source file that has not been fully read in is represented by
* a partial_symtab. This contains the information on where in the
* executable the debugging symbols for a specific file are, and a
* list of names of global symbols which are located in this file.
*/
struct partial_symtab
{
/* Chain of all existing partial symtabs. */
struct partial_symtab *next;
/* Name of the source file which this partial_symtab defines */
char *filename;
/* Offset within loader symbol table of first local symbol for this
file and length (in bytes) of the section of the symbol table
devoted to this file's symbols (actually, the section bracketed
may contain more than just this files symbols
If ldsymlen is 0, the only reason for this things existence is
the dependency list below. Nothing else will happen when it is
read in. */
int ldsymoff, ldsymlen;
/* Range of text addresses covered by this file; texthigh is the
beginning of the next section. */
int textlow, texthigh;
/* Non-zero if the symtab corresponding to this psymtab has been
readin */
unsigned char readin;
/* Array of pointers to all of the partial_symtab s which this one
depends one. Since this array can only be set to previous or
the current (?) psymtab, this dependency tree is guarranteed not
to have any loops. */
struct partial_symtab **dependencies;
int number_of_dependencies;
/* Global symbol list. This list will be sorted after readin to
improve access. Binary search will be the usual method of
finding a symbol within it. globals_offset is an integer offset
within ps_globals */
int globals_offset, n_global_syms;
/* Static symbol list. This list will *not* be sorted after readin;
to find a symbol in it, exhaustive search must be used. This is
reasonable because searches through this list will eventually
lead to either the read in of a files symbols for real (assumed
to take a *lot* of time; check) or an error (and we don't care
how long errors take). */
int statics_offset, n_static_syms;
};
/* This is the list of struct symtab's that gdb considers current. */
struct symtab *symtab_list;
/* This is the list of struct partial_symtab's that gdb may need to access */
struct partial_symtab *partial_symtab_list;
/* This symtab variable specifies the current file for printing source lines */
struct symtab *current_source_symtab;
/* This is the next line to print for listing source lines. */
int current_source_line;
#define BLOCKLIST(symtab) (symtab)->blockvector
#define BLOCKVECTOR(symtab) (symtab)->blockvector
#define TYPEVECTOR(symtab) (symtab)->typevector
#define LINELIST(symtab) (symtab)->linetable
#define LINETABLE(symtab) (symtab)->linetable
/* Macros normally used to access components of symbol table structures. */
#define BLOCKLIST_NBLOCKS(blocklist) (blocklist)->nblocks
#define BLOCKLIST_BLOCK(blocklist,n) (blocklist)->block[n]
#define BLOCKVECTOR_NBLOCKS(blocklist) (blocklist)->nblocks
#define BLOCKVECTOR_BLOCK(blocklist,n) (blocklist)->block[n]
#define TYPEVECTOR_NTYPES(typelist) (typelist)->length
#define TYPEVECTOR_TYPE(typelist,n) (typelist)->type[n]
#define BLOCK_START(bl) (bl)->startaddr
#define BLOCK_END(bl) (bl)->endaddr
#define BLOCK_NSYMS(bl) (bl)->nsyms
#define BLOCK_SYM(bl, n) (bl)->sym[n]
#define BLOCK_FUNCTION(bl) (bl)->function
#define BLOCK_SUPERBLOCK(bl) (bl)->superblock
#define BLOCK_GCC_COMPILED(bl) (bl)->gcc_compile_flag
/* Nonzero if symbols of block BL should be sorted alphabetically. */
#define BLOCK_SHOULD_SORT(bl) ((bl)->nsyms >= 40)
#define SYMBOL_NAME(symbol) (symbol)->name
#define SYMBOL_NAMESPACE(symbol) (symbol)->namespace
#define SYMBOL_CLASS(symbol) (symbol)->class
#define SYMBOL_VALUE(symbol) (symbol)->value.value
#define SYMBOL_VALUE_BYTES(symbol) (symbol)->value.bytes
#define SYMBOL_BLOCK_VALUE(symbol) (symbol)->value.block
#define SYMBOL_TYPE(symbol) (symbol)->type
/* Some macros for bitfields. */
#define B_SET(a,x) (a[x>>5] |= (1 << (x&31)))
#define B_CLR(a,x) (a[x>>5] &= ~(1 << (x&31)))
#define B_TST(a,x) (a[x>>5] & (1 << (x&31)))
#define TYPE_NAME(thistype) (thistype)->name
#define TYPE_TARGET_TYPE(thistype) (thistype)->target_type
#define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type
#define TYPE_REFERENCE_TYPE(thistype) (thistype)->reference_type
#define TYPE_FUNCTION_TYPE(thistype) (thistype)->function_type
#define TYPE_MAIN_VARIANT(thistype) (thistype)->main_variant
#define TYPE_NEXT_VARIANT(thistype) (thistype)->next_variant
#define TYPE_LENGTH(thistype) (thistype)->length
#define TYPE_FLAGS(thistype) (thistype)->flags
#define TYPE_UNSIGNED(thistype) ((thistype)->flags & TYPE_FLAG_UNSIGNED)
#define TYPE_CODE(thistype) (thistype)->code
#define TYPE_NFIELDS(thistype) (thistype)->nfields
#define TYPE_FIELDS(thistype) (thistype)->fields
/* C++ */
#define TYPE_VPTR_BASETYPE(thistype) (thistype)->vptr_basetype
#define TYPE_DOMAIN_TYPE(thistype) (thistype)->vptr_basetype
#define TYPE_VPTR_FIELDNO(thistype) (thistype)->vptr_fieldno
#define TYPE_FN_FIELDS(thistype) (thistype)->fn_fields
#define TYPE_NFN_FIELDS(thistype) (thistype)->nfn_fields
#define TYPE_NFN_FIELDS_TOTAL(thistype) (thistype)->nfn_fields_total
#define TYPE_BASECLASSES(thistype) (thistype)->baseclasses
#define TYPE_ARG_TYPES(thistype) (thistype)->arg_types
#define TYPE_BASECLASS(thistype,index) (thistype)->baseclasses[index]
#define TYPE_N_BASECLASSES(thistype) (thistype)->n_baseclasses
#define TYPE_VIA_PUBLIC(thistype) ((thistype)->flags & TYPE_FLAG_VIA_PUBLIC)
#define TYPE_VIA_VIRTUAL(thistype) ((thistype)->flags & TYPE_FLAG_VIA_VIRTUAL)
#define TYPE_FIELD(thistype, n) (thistype)->fields[n]
#define TYPE_FIELD_TYPE(thistype, n) (thistype)->fields[n].type
#define TYPE_FIELD_NAME(thistype, n) (thistype)->fields[n].name
#define TYPE_FIELD_VALUE(thistype, n) (* (int*) &(thistype)->fields[n].type)
#define TYPE_FIELD_BITPOS(thistype, n) (thistype)->fields[n].bitpos
#define TYPE_FIELD_BITSIZE(thistype, n) (thistype)->fields[n].bitsize
#define TYPE_FIELD_PACKED(thistype, n) (thistype)->fields[n].bitsize
#define TYPE_FIELD_PRIVATE_BITS(thistype) (thistype)->private_field_bits
#define TYPE_FIELD_PROTECTED_BITS(thistype) (thistype)->protected_field_bits
#define SET_TYPE_FIELD_PRIVATE(thistype, n) B_SET ((thistype)->private_field_bits, (n))
#define SET_TYPE_FIELD_PROTECTED(thistype, n) B_SET ((thistype)->protected_field_bits, (n))
#define TYPE_FIELD_PRIVATE(thistype, n) B_TST((thistype)->private_field_bits, (n))
#define TYPE_FIELD_PROTECTED(thistype, n) B_TST((thistype)->protected_field_bits, (n))
#define TYPE_HAS_DESTRUCTOR(thistype) ((thistype)->flags & TYPE_FLAG_HAS_DESTRUCTOR)
#define TYPE_HAS_CONSTRUCTOR(thistype) ((thistype)->flags & TYPE_FLAG_HAS_CONSTRUCTOR)
#define TYPE_FIELD_STATIC(thistype, n) ((thistype)->fields[n].bitpos == -1)
#define TYPE_FIELD_STATIC_PHYSNAME(thistype, n) ((char *)(thistype)->fields[n].bitsize)
#define TYPE_FN_FIELDLISTS(thistype) (thistype)->fn_fieldlists
#define TYPE_FN_FIELDLIST(thistype, n) (thistype)->fn_fieldlists[n]
#define TYPE_FN_FIELDLIST1(thistype, n) (thistype)->fn_fieldlists[n].fn_fields
#define TYPE_FN_FIELDLIST_NAME(thistype, n) (thistype)->fn_fieldlists[n].name
#define TYPE_FN_FIELDLIST_LENGTH(thistype, n) (thistype)->fn_fieldlists[n].length
#define TYPE_FN_FIELD(thistype, n) (thistype)[n]
#define TYPE_FN_FIELD_NAME(thistype, n) (thistype)[n].name
#define TYPE_FN_FIELD_TYPE(thistype, n) (thistype)[n].type
#define TYPE_FN_FIELD_ARGS(thistype, n) (thistype)[n].args
#define TYPE_FN_FIELD_PHYSNAME(thistype, n) (thistype)[n].physname
#define TYPE_FN_FIELD_VIRTUAL_P(thistype, n) ((thistype)[n].voffset < 0)
#define TYPE_FN_FIELD_STATIC_P(thistype, n) ((thistype)[n].voffset > 0)
#define TYPE_FN_FIELD_VOFFSET(thistype, n) ((thistype)[n].voffset-1)
#define TYPE_FN_PRIVATE_BITS(thistype) (thistype).private_fn_field_bits
#define TYPE_FN_PROTECTED_BITS(thistype) (thistype).protected_fn_field_bits
#define SET_TYPE_FN_PRIVATE(thistype, n) B_SET ((thistype).private_fn_field_bits, n)
#define SET_TYPE_FN_PROTECTED(thistype, n) B_SET ((thistype).protected_fn_field_bits, n)
#define TYPE_FN_PRIVATE(thistype, n) B_TST ((thistype).private_fn_field_bits, n)
#define TYPE_FN_PROTECTED(thistype, n) B_TST ((thistype).protected_fn_field_bits, n)
/* Functions that work on the objects described above */
extern struct symtab *lookup_symtab ();
extern struct symbol *lookup_symbol ();
extern struct type *lookup_typename ();
extern struct type *lookup_unsigned_typename ();
extern struct type *lookup_struct ();
extern struct type *lookup_union ();
extern struct type *lookup_enum ();
extern struct type *lookup_struct_elt_type ();
extern struct type *lookup_pointer_type ();
extern struct type *lookup_function_type ();
extern struct type *lookup_basetype_type ();
extern struct type *create_array_type ();
extern struct symbol *block_function ();
extern struct symbol *find_pc_function ();
extern int find_pc_partial_function ();
extern struct partial_symtab *find_pc_psymtab ();
extern struct symtab *find_pc_symtab ();
extern struct partial_symbol *find_pc_psymbol ();
extern int find_pc_misc_function ();
/* C++ stuff. */
extern struct type *lookup_reference_type ();
extern struct type *lookup_member_type ();
extern struct type *lookup_class ();
/* end of C++ stuff. */
extern struct type *builtin_type_void;
extern struct type *builtin_type_char;
extern struct type *builtin_type_short;
extern struct type *builtin_type_int;
extern struct type *builtin_type_long;
extern struct type *builtin_type_unsigned_char;
extern struct type *builtin_type_unsigned_short;
extern struct type *builtin_type_unsigned_int;
extern struct type *builtin_type_unsigned_long;
extern struct type *builtin_type_float;
extern struct type *builtin_type_double;
#ifdef LONG_LONG
extern struct type *builtin_type_long_long;
extern struct type *builtin_type_unsigned_long_long;
#ifndef BUILTIN_TYPE_LONGEST
#define BUILTIN_TYPE_LONGEST builtin_type_long_long
#endif
#ifndef BUILTIN_TYPE_UNSIGNED_LONGEST
#define BUILTIN_TYPE_UNSIGNED_LONGEST builtin_type_unsigned_long_long
#endif
#else /* LONG_LONG */
#ifndef BUILTIN_TYPE_LONGEST
#define BUILTIN_TYPE_LONGEST builtin_type_long
#endif
#ifndef BUILTIN_TYPE_UNSIGNED_LONGEST
#define BUILTIN_TYPE_UNSIGNED_LONGEST builtin_type_unsigned_long
#endif
#endif
struct symtab_and_line
{
struct symtab *symtab;
int line;
CORE_ADDR pc;
CORE_ADDR end;
};
struct symtabs_and_lines
{
struct symtab_and_line *sals;
int nelts;
};
/* Given a pc value, return line number it is in.
Second arg nonzero means if pc is on the boundary
use the previous statement's line number. */
struct symtab_and_line find_pc_line ();
/* Given a string, return the line specified by it.
For commands like "list" and "breakpoint". */
struct symtabs_and_lines decode_line_spec ();
struct symtabs_and_lines decode_line_spec_1 ();
struct symtabs_and_lines decode_line_1 ();

1096
gnu/usr.bin/gdb/utils.c Normal file

File diff suppressed because it is too large Load diff

690
gnu/usr.bin/gdb/valarith.c Normal file
View file

@ -0,0 +1,690 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
* Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
*/
#ifndef lint
static char sccsid[] = "@(#)valarith.c 6.3 (Berkeley) 5/8/91";
#endif /* not lint */
/* Perform arithmetic and other operations on values, for GDB.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "param.h"
#include "symtab.h"
#include "value.h"
#include "expression.h"
value value_x_binop ();
value value_subscripted_rvalue ();
value
value_add (arg1, arg2)
value arg1, arg2;
{
register value val, valint, valptr;
register int len;
COERCE_ARRAY (arg1);
COERCE_ARRAY (arg2);
if ((TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR
|| TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_PTR)
&&
(TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT
|| TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_INT))
/* Exactly one argument is a pointer, and one is an integer. */
{
if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR)
{
valptr = arg1;
valint = arg2;
}
else
{
valptr = arg2;
valint = arg1;
}
len = TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (valptr)));
if (len == 0) len = 1; /* For (void *) */
val = value_from_long (builtin_type_long,
value_as_long (valptr)
+ (len * value_as_long (valint)));
VALUE_TYPE (val) = VALUE_TYPE (valptr);
return val;
}
return value_binop (arg1, arg2, BINOP_ADD);
}
value
value_sub (arg1, arg2)
value arg1, arg2;
{
register value val;
COERCE_ARRAY (arg1);
COERCE_ARRAY (arg2);
if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR
&&
TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_INT)
{
val = value_from_long (builtin_type_long,
value_as_long (arg1)
- TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) * value_as_long (arg2));
VALUE_TYPE (val) = VALUE_TYPE (arg1);
return val;
}
if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR
&&
VALUE_TYPE (arg1) == VALUE_TYPE (arg2))
{
val = value_from_long (builtin_type_long,
(value_as_long (arg1) - value_as_long (arg2))
/ TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))));
return val;
}
return value_binop (arg1, arg2, BINOP_SUB);
}
/* Return the value of ARRAY[IDX]. */
value
value_subscript (array, idx)
value array, idx;
{
if (TYPE_CODE (VALUE_TYPE (array)) == TYPE_CODE_ARRAY
&& VALUE_LVAL (array) != lval_memory)
return value_subscripted_rvalue (array, idx);
else
return value_ind (value_add (array, idx));
}
/* Return the value of EXPR[IDX], expr an aggregate rvalue
(eg, a vector register) */
value
value_subscripted_rvalue (array, idx)
value array, idx;
{
struct type *elt_type = TYPE_TARGET_TYPE (VALUE_TYPE (array));
int elt_size = TYPE_LENGTH (elt_type);
int elt_offs = elt_size * value_as_long (idx);
value v;
if (elt_offs >= TYPE_LENGTH (VALUE_TYPE (array)))
error ("no such vector element");
if (TYPE_CODE (elt_type) == TYPE_CODE_FLT)
{
if (elt_size == sizeof (float))
v = value_from_double (elt_type, (double) *(float *)
(VALUE_CONTENTS (array) + elt_offs));
else
v = value_from_double (elt_type, *(double *)
(VALUE_CONTENTS (array) + elt_offs));
}
else
{
int offs;
union {int i; char c;} test;
test.i = 1;
if (test.c == 1)
offs = 0;
else
offs = sizeof (LONGEST) - elt_size;
v = value_from_long (elt_type, *(LONGEST *)
(VALUE_CONTENTS (array) + elt_offs - offs));
}
if (VALUE_LVAL (array) == lval_internalvar)
VALUE_LVAL (v) = lval_internalvar_component;
else
VALUE_LVAL (v) = not_lval;
VALUE_ADDRESS (v) = VALUE_ADDRESS (array);
VALUE_OFFSET (v) = VALUE_OFFSET (array) + elt_offs;
VALUE_BITSIZE (v) = elt_size * 8;
return v;
}
/* Check to see if either argument is a structure. This is called so
we know whether to go ahead with the normal binop or look for a
user defined function instead.
For now, we do not overload the `=' operator. */
int
binop_user_defined_p (op, arg1, arg2)
enum exp_opcode op;
value arg1, arg2;
{
if (op == BINOP_ASSIGN)
return 0;
return (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_STRUCT
|| TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_STRUCT
|| (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF
&& TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) == TYPE_CODE_STRUCT)
|| (TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_REF
&& TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) == TYPE_CODE_STRUCT));
}
/* Check to see if argument is a structure. This is called so
we know whether to go ahead with the normal unop or look for a
user defined function instead.
For now, we do not overload the `&' operator. */
int unop_user_defined_p (op, arg1)
enum exp_opcode op;
value arg1;
{
if (op == UNOP_ADDR)
return 0;
return (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_STRUCT
|| (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF
&& TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) == TYPE_CODE_STRUCT));
}
/* We know either arg1 or arg2 is a structure, so try to find the right
user defined function. Create an argument vector that calls
arg1.operator @ (arg1,arg2) and return that value (where '@' is any
binary operator which is legal for GNU C++). */
value
value_x_binop (arg1, arg2, op, otherop)
value arg1, arg2;
int op, otherop;
{
value * argvec;
char *ptr;
char tstr[13];
int static_memfuncp;
COERCE_ENUM (arg1);
COERCE_ENUM (arg2);
/* now we know that what we have to do is construct our
arg vector and find the right function to call it with. */
if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_STRUCT)
error ("friend functions not implemented yet");
argvec = (value *) alloca (sizeof (value) * 4);
argvec[1] = value_addr (arg1);
argvec[2] = arg2;
argvec[3] = 0;
/* make the right function name up */
strcpy(tstr, "operator __");
ptr = tstr+9;
switch (op)
{
case BINOP_ADD: strcpy(ptr,"+"); break;
case BINOP_SUB: strcpy(ptr,"-"); break;
case BINOP_MUL: strcpy(ptr,"*"); break;
case BINOP_DIV: strcpy(ptr,"/"); break;
case BINOP_REM: strcpy(ptr,"%"); break;
case BINOP_LSH: strcpy(ptr,"<<"); break;
case BINOP_RSH: strcpy(ptr,">>"); break;
case BINOP_LOGAND: strcpy(ptr,"&"); break;
case BINOP_LOGIOR: strcpy(ptr,"|"); break;
case BINOP_LOGXOR: strcpy(ptr,"^"); break;
case BINOP_AND: strcpy(ptr,"&&"); break;
case BINOP_OR: strcpy(ptr,"||"); break;
case BINOP_MIN: strcpy(ptr,"<?"); break;
case BINOP_MAX: strcpy(ptr,">?"); break;
case BINOP_ASSIGN: strcpy(ptr,"="); break;
case BINOP_ASSIGN_MODIFY:
switch (otherop)
{
case BINOP_ADD: strcpy(ptr,"+="); break;
case BINOP_SUB: strcpy(ptr,"-="); break;
case BINOP_MUL: strcpy(ptr,"*="); break;
case BINOP_DIV: strcpy(ptr,"/="); break;
case BINOP_REM: strcpy(ptr,"%="); break;
case BINOP_LOGAND: strcpy(ptr,"&="); break;
case BINOP_LOGIOR: strcpy(ptr,"|="); break;
case BINOP_LOGXOR: strcpy(ptr,"^="); break;
default:
error ("Invalid binary operation specified.");
}
break;
case BINOP_SUBSCRIPT: strcpy(ptr,"[]"); break;
case BINOP_EQUAL: strcpy(ptr,"=="); break;
case BINOP_NOTEQUAL: strcpy(ptr,"!="); break;
case BINOP_LESS: strcpy(ptr,"<"); break;
case BINOP_GTR: strcpy(ptr,">"); break;
case BINOP_GEQ: strcpy(ptr,">="); break;
case BINOP_LEQ: strcpy(ptr,"<="); break;
default:
error ("Invalid binary operation specified.");
}
argvec[0] = value_struct_elt (arg1, argvec+1, tstr, &static_memfuncp, "structure");
if (argvec[0])
{
if (static_memfuncp)
{
argvec[1] = argvec[0];
argvec++;
}
return call_function (argvec[0], 2 - static_memfuncp, argvec + 1);
}
error ("member function %s not found", tstr);
}
/* We know that arg1 is a structure, so try to find a unary user
defined operator that matches the operator in question.
Create an argument vector that calls arg1.operator @ (arg1)
and return that value (where '@' is (almost) any unary operator which
is legal for GNU C++). */
value
value_x_unop (arg1, op)
value arg1;
int op;
{
value * argvec;
char *ptr;
char tstr[13];
int static_memfuncp;
COERCE_ENUM (arg1);
/* now we know that what we have to do is construct our
arg vector and find the right function to call it with. */
if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_STRUCT)
error ("friend functions not implemented yet");
argvec = (value *) alloca (sizeof (value) * 3);
argvec[1] = value_addr (arg1);
argvec[2] = 0;
/* make the right function name up */
strcpy(tstr,"operator __");
ptr = tstr+9;
switch (op)
{
case UNOP_PREINCREMENT: strcpy(ptr,"++"); break;
case UNOP_PREDECREMENT: strcpy(ptr,"++"); break;
case UNOP_POSTINCREMENT: strcpy(ptr,"++"); break;
case UNOP_POSTDECREMENT: strcpy(ptr,"++"); break;
case UNOP_ZEROP: strcpy(ptr,"!"); break;
case UNOP_LOGNOT: strcpy(ptr,"~"); break;
case UNOP_NEG: strcpy(ptr,"-"); break;
default:
error ("Invalid binary operation specified.");
}
argvec[0] = value_struct_elt (arg1, argvec+1, tstr, &static_memfuncp, "structure");
if (argvec[0])
{
if (static_memfuncp)
{
argvec[1] = argvec[0];
argvec++;
}
return call_function (argvec[0], 1 - static_memfuncp, argvec + 1);
}
error ("member function %s not found", tstr);
}
/* Perform a binary operation on two integers or two floats.
Does not support addition and subtraction on pointers;
use value_add or value_sub if you want to handle those possibilities. */
value
value_binop (arg1, arg2, op)
value arg1, arg2;
int op;
{
register value val;
COERCE_ENUM (arg1);
COERCE_ENUM (arg2);
if ((TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_FLT
&&
TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_INT)
||
(TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_FLT
&&
TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_INT))
error ("Argument to arithmetic operation not a number.");
if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_FLT
||
TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_FLT)
{
double v1, v2, v;
v1 = value_as_double (arg1);
v2 = value_as_double (arg2);
switch (op)
{
case BINOP_ADD:
v = v1 + v2;
break;
case BINOP_SUB:
v = v1 - v2;
break;
case BINOP_MUL:
v = v1 * v2;
break;
case BINOP_DIV:
v = v1 / v2;
break;
default:
error ("Integer-only operation on floating point number.");
}
val = allocate_value (builtin_type_double);
*(double *) VALUE_CONTENTS (val) = v;
}
else
/* Integral operations here. */
{
/* Should we promote to unsigned longest? */
if ((TYPE_UNSIGNED (VALUE_TYPE (arg1))
|| TYPE_UNSIGNED (VALUE_TYPE (arg2)))
&& (TYPE_LENGTH (VALUE_TYPE (arg1)) >= sizeof (unsigned LONGEST)
|| TYPE_LENGTH (VALUE_TYPE (arg2)) >= sizeof (unsigned LONGEST)))
{
unsigned LONGEST v1, v2, v;
v1 = (unsigned LONGEST) value_as_long (arg1);
v2 = (unsigned LONGEST) value_as_long (arg2);
switch (op)
{
case BINOP_ADD:
v = v1 + v2;
break;
case BINOP_SUB:
v = v1 - v2;
break;
case BINOP_MUL:
v = v1 * v2;
break;
case BINOP_DIV:
v = v1 / v2;
break;
case BINOP_REM:
v = v1 % v2;
break;
case BINOP_LSH:
v = v1 << v2;
break;
case BINOP_RSH:
v = v1 >> v2;
break;
case BINOP_LOGAND:
v = v1 & v2;
break;
case BINOP_LOGIOR:
v = v1 | v2;
break;
case BINOP_LOGXOR:
v = v1 ^ v2;
break;
case BINOP_AND:
v = v1 && v2;
break;
case BINOP_OR:
v = v1 || v2;
break;
case BINOP_MIN:
v = v1 < v2 ? v1 : v2;
break;
case BINOP_MAX:
v = v1 > v2 ? v1 : v2;
break;
default:
error ("Invalid binary operation on numbers.");
}
val = allocate_value (BUILTIN_TYPE_UNSIGNED_LONGEST);
*(unsigned LONGEST *) VALUE_CONTENTS (val) = v;
}
else
{
LONGEST v1, v2, v;
v1 = value_as_long (arg1);
v2 = value_as_long (arg2);
switch (op)
{
case BINOP_ADD:
v = v1 + v2;
break;
case BINOP_SUB:
v = v1 - v2;
break;
case BINOP_MUL:
v = v1 * v2;
break;
case BINOP_DIV:
v = v1 / v2;
break;
case BINOP_REM:
v = v1 % v2;
break;
case BINOP_LSH:
v = v1 << v2;
break;
case BINOP_RSH:
v = v1 >> v2;
break;
case BINOP_LOGAND:
v = v1 & v2;
break;
case BINOP_LOGIOR:
v = v1 | v2;
break;
case BINOP_LOGXOR:
v = v1 ^ v2;
break;
case BINOP_AND:
v = v1 && v2;
break;
case BINOP_OR:
v = v1 || v2;
break;
case BINOP_MIN:
v = v1 < v2 ? v1 : v2;
break;
case BINOP_MAX:
v = v1 > v2 ? v1 : v2;
break;
default:
error ("Invalid binary operation on numbers.");
}
val = allocate_value (BUILTIN_TYPE_LONGEST);
*(LONGEST *) VALUE_CONTENTS (val) = v;
}
}
return val;
}
/* Simulate the C operator ! -- return 1 if ARG1 contains zeros. */
int
value_zerop (arg1)
value arg1;
{
register int len;
register char *p;
COERCE_ARRAY (arg1);
len = TYPE_LENGTH (VALUE_TYPE (arg1));
p = VALUE_CONTENTS (arg1);
while (--len >= 0)
{
if (*p++)
break;
}
return len < 0;
}
/* Simulate the C operator == by returning a 1
iff ARG1 and ARG2 have equal contents. */
int
value_equal (arg1, arg2)
register value arg1, arg2;
{
register int len;
register char *p1, *p2;
enum type_code code1;
enum type_code code2;
COERCE_ARRAY (arg1);
COERCE_ARRAY (arg2);
code1 = TYPE_CODE (VALUE_TYPE (arg1));
code2 = TYPE_CODE (VALUE_TYPE (arg2));
if (code1 == TYPE_CODE_INT && code2 == TYPE_CODE_INT)
return value_as_long (arg1) == value_as_long (arg2);
else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT)
&& (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT))
return value_as_double (arg1) == value_as_double (arg2);
else if ((code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_INT)
|| (code2 == TYPE_CODE_PTR && code1 == TYPE_CODE_INT))
return (char *) value_as_long (arg1) == (char *) value_as_long (arg2);
else if (code1 == code2
&& ((len = TYPE_LENGTH (VALUE_TYPE (arg1)))
== TYPE_LENGTH (VALUE_TYPE (arg2))))
{
p1 = VALUE_CONTENTS (arg1);
p2 = VALUE_CONTENTS (arg2);
while (--len >= 0)
{
if (*p1++ != *p2++)
break;
}
return len < 0;
}
else
error ("Invalid type combination in equality test.");
}
/* Simulate the C operator < by returning 1
iff ARG1's contents are less than ARG2's. */
int
value_less (arg1, arg2)
register value arg1, arg2;
{
register enum type_code code1;
register enum type_code code2;
COERCE_ARRAY (arg1);
COERCE_ARRAY (arg2);
code1 = TYPE_CODE (VALUE_TYPE (arg1));
code2 = TYPE_CODE (VALUE_TYPE (arg2));
if (code1 == TYPE_CODE_INT && code2 == TYPE_CODE_INT)
return value_as_long (arg1) < value_as_long (arg2);
else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT)
&& (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT))
return value_as_double (arg1) < value_as_double (arg2);
else if ((code1 == TYPE_CODE_PTR || code1 == TYPE_CODE_INT)
&& (code2 == TYPE_CODE_PTR || code2 == TYPE_CODE_INT))
return (char *) value_as_long (arg1) < (char *) value_as_long (arg2);
else
error ("Invalid type combination in ordering comparison.");
}
/* The unary operators - and ~. Both free the argument ARG1. */
value
value_neg (arg1)
register value arg1;
{
register struct type *type;
COERCE_ENUM (arg1);
type = VALUE_TYPE (arg1);
if (TYPE_CODE (type) == TYPE_CODE_FLT)
return value_from_double (type, - value_as_double (arg1));
else if (TYPE_CODE (type) == TYPE_CODE_INT)
return value_from_long (type, - value_as_long (arg1));
else
error ("Argument to negate operation not a number.");
}
value
value_lognot (arg1)
register value arg1;
{
COERCE_ENUM (arg1);
if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_INT)
error ("Argument to complement operation not an integer.");
return value_from_long (VALUE_TYPE (arg1), ~ value_as_long (arg1));
}

1418
gnu/usr.bin/gdb/valops.c Normal file

File diff suppressed because it is too large Load diff

1430
gnu/usr.bin/gdb/valprint.c Normal file

File diff suppressed because it is too large Load diff

212
gnu/usr.bin/gdb/value.h Normal file
View file

@ -0,0 +1,212 @@
/* Definitions for values of C expressions, for GDB.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* The structure which defines the type of a value. It should never
* be possible for a program lval value to survive over a call to the inferior
* (ie to be put into the history list or an internal variable).
*/
enum lval_type {
/* Not an lval. */
not_lval,
/* In memory. Could be a saved register. */
lval_memory,
/* In a register. */
lval_register,
/* In a gdb internal variable. */
lval_internalvar,
/* Part of a gdb internal variable (structure field). */
lval_internalvar_component,
/* In a register series in a frame not the current one, which may have been
partially saved or saved in different places (otherwise would be
lval_register or lval_memory). */
lval_reg_frame_relative,
};
struct value
{
/* Type of value; either not an lval, or one of the various
different possible kinds of lval. */
enum lval_type lval;
/* Location of value (if lval). */
union
{
/* Address in inferior or byte of registers structure. */
CORE_ADDR address;
/* Pointer to interrnal variable. */
struct internalvar *internalvar;
/* Number of register. Only used with
lval_reg_frame_relative. */
int regnum;
} location;
/* Describes offset of a value within lval a structure in bytes. */
int offset;
/* Only used for bitfields; number of bits contained in them. */
int bitsize;
/* Only used for bitfields; position of start of field. */
int bitpos;
/* Frame value is relative to. In practice, this address is only
used if the value is stored in several registers in other than
the current frame, and these registers have not all been saved
at the same place in memory. This will be described in the
lval enum above as "lval_reg_frame_relative". */
CORE_ADDR frame_addr;
/* Type of the value. */
struct type *type;
/* Values are stored in a chain, so that they can be deleted
easily over calls to the inferior. Values assigned to internal
variables or put into the value history are taken off this
list. */
struct value *next;
/* If an lval is forced to repeat, a new value is created with
these fields set. The new value is not an lval. */
short repeated;
short repetitions;
/* Register number if the value is from a register. Is not kept
if you take a field of a structure that is stored in a
register. Shouldn't it be? */
short regno;
/* Actual contents of the value. For use of this value; setting
it uses the stuff above. */
long contents[1];
};
typedef struct value *value;
#define VALUE_TYPE(val) (val)->type
#define VALUE_CONTENTS(val) ((char *) (val)->contents)
#define VALUE_LVAL(val) (val)->lval
#define VALUE_ADDRESS(val) (val)->location.address
#define VALUE_INTERNALVAR(val) (val)->location.internalvar
#define VALUE_FRAME_REGNUM(val) ((val)->location.regnum)
#define VALUE_FRAME(val) ((val)->frame_addr)
#define VALUE_OFFSET(val) (val)->offset
#define VALUE_BITSIZE(val) (val)->bitsize
#define VALUE_BITPOS(val) (val)->bitpos
#define VALUE_NEXT(val) (val)->next
#define VALUE_REPEATED(val) (val)->repeated
#define VALUE_REPETITIONS(val) (val)->repetitions
#define VALUE_REGNO(val) (val)->regno
/* If ARG is an array, convert it to a pointer.
If ARG is an enum, convert it to an integer.
References are dereferenced. */
#define COERCE_ARRAY(arg) \
{ if (TYPE_CODE ( VALUE_TYPE (arg)) == TYPE_CODE_REF) \
arg = value_ind (arg); \
if (VALUE_REPEATED (arg) \
|| TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ARRAY) \
arg = value_coerce_array (arg); \
if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM) \
arg = value_cast (builtin_type_unsigned_int, arg); \
}
/* If ARG is an enum, convert it to an integer. */
#define COERCE_ENUM(arg) \
{ if (TYPE_CODE ( VALUE_TYPE (arg)) == TYPE_CODE_REF) \
arg = value_ind (arg); \
if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM) \
arg = value_cast (builtin_type_unsigned_int, arg); \
}
/* Internal variables (variables for convenience of use of debugger)
are recorded as a chain of these structures. */
struct internalvar
{
struct internalvar *next;
char *name;
value value;
};
LONGEST value_as_long ();
double value_as_double ();
LONGEST unpack_long ();
double unpack_double ();
long unpack_field_as_long ();
value value_from_long ();
value value_from_double ();
value value_at ();
value value_from_register ();
value value_of_variable ();
value value_of_register ();
value read_var_value ();
value locate_var_value ();
value allocate_value ();
value allocate_repeat_value ();
value value_string ();
value value_binop ();
value value_add ();
value value_sub ();
value value_coerce_array ();
value value_ind ();
value value_addr ();
value value_assign ();
value value_neg ();
value value_lognot ();
value value_struct_elt (), value_struct_elt_for_address ();
value value_field ();
value value_cast ();
value value_zero ();
value value_repeat ();
value value_subscript ();
value call_function ();
value value_being_returned ();
int using_struct_return ();
value evaluate_expression ();
value evaluate_type ();
value parse_and_eval ();
value parse_to_comma_and_eval ();
value access_value_history ();
value value_of_internalvar ();
struct internalvar *lookup_internalvar ();
int value_equal ();
int value_less ();
int value_zerop ();
/* C++ */
value value_of_this ();
value value_static_field ();
value value_x_binop ();
value value_x_unop ();
int binop_user_defined_p ();
int unop_user_defined_p ();
void read_register_bytes ();
void modify_field ();
void type_print ();
void type_print_1 ();
/* Possibilities for prettyprint parameters to routines which print
things. */
enum val_prettyprint {
Val_no_prettyprint = 0,
Val_prettyprint,
/* Use the default setting which the user has specified. */
Val_pretty_default
};

1059
gnu/usr.bin/gdb/values.c Normal file

File diff suppressed because it is too large Load diff

20
gnu/usr.bin/gdb/version.c Normal file
View file

@ -0,0 +1,20 @@
/* Define the current version number of GDB.
Copyright (C) 1989, Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
char *version = "3.5";

81
gnu/usr.bin/gdb/wait.h Normal file
View file

@ -0,0 +1,81 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Van Jacobson and Steven McCanne of Lawrence Berkeley Laboratory.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)wait.h 6.3 (Berkeley) 5/8/91
*/
/* Define how to access the structure that the wait system call stores.
On many systems, there is a structure defined for this.
But on vanilla-ish USG systems there is not. */
#ifndef HAVE_WAIT_STRUCT
#define WAITTYPE int
#define WIFSTOPPED(w) (((w)&0377) == 0177)
#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
#define WIFEXITED(w) (((w)&0377) == 0)
#define WEXITSTATUS(w) ((w) >> 8)
#define WSTOPSIG(w) ((w) >> 8)
#define WCOREDUMP(w) (((w)&0200) != 0)
#define WTERMSIG(w) ((w) & 0177)
#define WSETEXIT(w, status) ((w) = (status))
#define WSETSTOP(w,sig) ((w) = (0177 | ((sig) << 8)))
#else
#include <sys/wait.h>
#define WAITTYPE union wait
#ifndef WEXITSTATUS
#define WEXITSTATUS(w) (w).w_retcode
#endif
#ifndef WSTOPSIG
#define WSTOPSIG(w) (w).w_stopsig
#endif
#ifndef WCOREDUMP
#define WCOREDUMP(w) (w).w_coredump
#endif
#ifndef WTERMSIG
#define WTERMSIG(w) (w).w_termsig
#endif
#ifndef WSETEXIT
#define WSETEXIT(w, status) ((w).w_status = (status))
#endif
#ifndef WSETSTOP
#define WSETSTOP(w,sig) \
((w).w_stopsig = (sig), (w).w_coredump = 0, (w).w_termsig = 0177)
#endif
#endif

View file

@ -0,0 +1,33 @@
# %W% (Berkeley) %G%
.include "../config/Makefile.$(MACHINE)"
PROG= xgdb
SRCS= xgdb.c xgdbinit.c
GDBOBJS+= $(CONFIGSRCS:R:S/$/.o/g) \
blockframe.o breakpoint.o command.o copying.o core.o \
cplus-dem.o dbxread.o environ.o eval.o expprint.o \
expread.o findvar.o infcmd.o inflow.o infrun.o \
main.o obstack.o printcmd.o regex.o remote.o \
remote-sl.o source.o stack.o symmisc.o symtab.o \
utils.o valarith.o valops.o valprint.o values.o \
version.o \
funmap.o history.o keymaps.o readline.o
CFLAGS+= -I.. -I$(.CURDIR)/.. -I$(.CURDIR)/../config \
-DHAVE_VPRINTF -DVI_MODE -DKERNELDEBUG
LDFLAGS+= -L/usr/lib/X11
LDADD+= $(GDBOBJS:S/^/..\//g) -lXaw -lXmu -lXt -lXext -lX11 -ltermcap
NOMAN= noman
.include "../../Makefile.inc"
.include <bsd.prog.mk>
#
# Generate the constructor
#
xgdbinit.c: ../init.c xgdb.c
-(sed -e '/^}$$/d' ../init.c; \
egrep -h '^_initialize_[^ ]* *\(\)' $(.CURDIR)/xgdb.c; \
echo ';}') > xgdbinit.c
CLEANFILES+= xgdbinit.c

700
gnu/usr.bin/gdb/xgdb/xgdb.c Normal file
View file

@ -0,0 +1,700 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
* Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
*
* static char rcsid[] = "$Header: /home/cvs/386BSD/src/usr.bin/gdb/xgdb/xgdb.c,v 1.1.1.1 1993/06/12 14:52:36 rgrimes Exp $";
*/
#ifndef lint
static char sccsid[] = "@(#)xgdb.c 6.3 (Berkeley) 5/8/91";
#endif /* not lint */
/*
* Interface from GDB to X windows. Copyright (C) 1987 Free Software
* Foundation, Inc.
*
* GDB is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY. No author or distributor accepts responsibility to anyone for
* the consequences of using it or for whether it serves any particular
* purpose or works at all, unless he says so in writing. Refer to the GDB
* General Public License for full details.
*
* Everyone is granted permission to copy, modify and redistribute GDB, but only
* under the conditions described in the GDB General Public License. A copy
* of this license is supposed to have been given to you along with GDB so
* you can know your rights and responsibilities. It should be in a file
* named COPYING. Among other things, the copyright notice and this notice
* must be preserved on all copies.
*
* In other words, go ahead and share GDB, but don't try to stop anyone else
* from sharing it farther. Help stamp out software hoarding!
*/
/*
* Original version was contributed by Derek Beatty, 30 June 87.
* This version is essentially a re-write of the original by Van
* Jacobson (van@helios.ee.lbl.gov), Nov, 90.
*/
#include "defs.h"
#include "param.h"
#include "symtab.h"
#include "frame.h"
extern int stop_breakpoint;
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/AsciiSink.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/Paned.h>
#include <X11/Xaw/Text.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/file.h>
#include <sys/errno.h>
extern int errno;
extern char *getenv();
extern char *malloc();
extern void bcopy();
extern int select();
extern int get_filename_and_charpos();
extern int source_line_charpos();
extern int source_charpos_line();
extern void execute_command();
extern void error_no_arg();
extern void add_com();
/* The X display where the window appears. */
static char *displayname;
static Display *display;
static XtAppContext app_context;
/* Windows manipulated by this package. */
static Widget main_widget;
static Widget containing_widget;
static Widget source_name_widget;
static Widget source_text_widget;
static Widget button_box_widget;
/* Source text display. */
static struct frame_info *last_fi;
static CORE_ADDR last_pc;
static struct symtab *last_cur_symtab;
static int last_cur_line;
static int source_window_line;
static char *source_window_file;
static struct symtab *source_window_symtab;
static char version_label[64];
extern char *version;
/* Forward declarations */
static Widget create_text_widget();
static int
safe_strcmp(a, b)
register char *a, *b;
{
register int i;
if (a == b)
return (0);
if (!a && b)
return (1);
if (a && !b)
return (-1);
return (strcmp(a, b));
}
/* Display an appropriate piece of source code in the source window. */
void
xgdb_display_source()
{
char *filename = NULL;
struct symtab_and_line get_selected_frame_sal();
struct symtab_and_line sal;
struct frame_info *fi;
/* Do nothing if called before we are initialized */
if (!containing_widget)
return;
/*
* Figure out what to display (the appropriate hooks to tell
* us don't exist so we guess): If there's a current frame
* and it or its pc changed from the last time we were here,
* display appropriate source line. Otherwise if the current
* source symtab or line is different, display that line.
* Otherwise nothing changed so leave the display alone.
*/
fi = get_frame_info(selected_frame);
if (fi && (fi != last_fi || fi->pc != last_pc)) {
last_fi = fi;
last_pc = fi->pc;
sal = find_pc_line(fi->pc, fi->next_frame);
if (sal.symtab == NULL) { /* XXX */
sal.symtab = current_source_symtab;
sal.line = current_source_line;
}
current_source_symtab = sal.symtab;
current_source_line = sal.line;
} else if (current_source_symtab != last_cur_symtab ||
current_source_line != last_cur_line) {
sal.symtab = last_cur_symtab = current_source_symtab;
sal.line = last_cur_line = current_source_line;
} else
return;
/*
* Do a path search and get the exact filename of this source file.
* Also scan it and find its source lines if not already done.
*/
if (sal.symtab && filename == NULL) {
if (get_filename_and_charpos(sal.symtab, sal.line, &filename))
/* line numbers may have changed - force highlight */
source_window_line = -1;
}
/*
* If the source window is wrong, destroy it and make a new one.
*/
if (safe_strcmp(filename, source_window_file)) {
Arg args[1];
Widget src = XawTextGetSource(source_text_widget);
if (filename) {
XtSetArg(args[0], XtNstring, filename);
XtSetValues(src, args, XtNumber(args));
args[0].name = XtNlabel;
XtSetValues(source_name_widget, args, XtNumber(args));
} else {
XtSetArg(args[0], XtNstring, "/dev/null");
XtSetValues(src, args, XtNumber(args));
XtSetArg(args[0], XtNlabel, "");
XtSetValues(source_name_widget, args, XtNumber(args));
}
if (source_window_file)
free(source_window_file);
source_window_file = filename;
source_window_line = sal.line + 1; /* force highlight */
}
if (sal.symtab && source_window_line != sal.line) {
/*
* Update display and cursor positions as necessary.
* Cursor should be placed on line sal.line.
*/
XawTextPosition l, r;
source_window_symtab = sal.symtab;
source_window_line = sal.line;
l = source_line_charpos(source_window_symtab, sal.line);
r = source_line_charpos(source_window_symtab, sal.line + 1);
if (r < l)
r = l + 1;
XawTextSetSelection(source_text_widget, l, r);
XawTextScrollToLine(source_text_widget, l, 10, 3);
XawTextSetInsertionPoint(source_text_widget, l);
}
}
/*
* Handlers for buttons.
*/
static int
current_lineno()
{
XawTextPosition start, finish;
XawTextGetSelectionPos(source_text_widget, &start, &finish);
if (start >= finish)
start = XawTextGetInsertionPoint(source_text_widget);
return (source_charpos_line(source_window_symtab, start));
}
static char *
append_selection(cp)
char *cp;
{
int len;
XawTextPosition l, r;
XawTextGetSelectionPos(source_text_widget, &l, &r);
if ((len = r - l) > 0) {
Widget src = XawTextGetSource(source_text_widget);
while (len > 0) {
XawTextBlock tb;
XawTextSourceRead(src, l, &tb, len);
bcopy(tb.ptr, cp, tb.length);
cp += tb.length;
len -= tb.length;
}
if (cp[-1] == 0)
--cp;
}
return (cp);
}
static char *
append_selection_word(cp)
register char *cp;
{
register int len;
XawTextPosition l, r;
XawTextBlock tb;
register char c;
register Widget src = XawTextGetSource(source_text_widget);
XawTextGetSelectionPos(source_text_widget, &l, &r);
if ((len = r - l) <= 0) {
l = XawTextGetInsertionPoint(source_text_widget);
len = 128; /* XXX */
/* might have clicked in middle of word -- back up to start */
for ( ; l > 0; --l) {
XawTextSourceRead(src, l - 1, &tb, 1);
c = tb.ptr[0];
if (! isalnum(c) && c != '_' && c != '$')
break;
}
}
while (len > 0) {
char *sp;
int i;
XawTextSourceRead(src, l, &tb, len);
for (sp = tb.ptr, i = tb.length; --i >= 0; ) {
c = *sp++;
if (!isalnum(c) && c != '_' && c != '$')
return (cp);
*cp++ = c;
}
len -= tb.length;
}
return (cp);
}
static char *
append_selection_expr(cp)
char *cp;
{
int len;
XawTextPosition l, r;
Widget src = XawTextGetSource(source_text_widget);
XawTextBlock tb;
char *sp;
char c;
XawTextGetSelectionPos(source_text_widget, &l, &r);
if (r > l)
return (append_selection(cp));
l = XawTextGetInsertionPoint(source_text_widget);
/* might have clicked in middle of word -- back up to start */
for ( ; l > 0; --l) {
XawTextSourceRead(src, l - 1, &tb, 1);
c = tb.ptr[0];
if (! isalnum(c) && c != '_' && c != '$')
break;
}
len = 128; /* XXX */
while (len > 0) {
int i;
char pstack[64];
int pcnt = 0;
XawTextSourceRead(src, l, &tb, len);
for (sp = tb.ptr, i = tb.length; --i >= 0; ) {
switch (c = *sp++) {
case '\n':
case ';':
return (cp);
case '=':
if (cp[-1] != '=')
return (cp - 1);
if (len == 128)
return (cp);
break;
case ',':
if (pcnt <= 0)
return (cp);
break;
case '(':
pstack[pcnt] = ')';
if (++pcnt >= sizeof(pstack))
return (cp);
break;
case '[':
pstack[pcnt] = ']';
if (++pcnt >= sizeof(pstack))
return (cp);
break;
case ')':
case ']':
if (--pcnt < 0 || pstack[pcnt] != c)
return (cp);
break;
}
*cp++ = c;
}
len -= tb.length;
}
return (cp);
}
static int input_avail; /* XXX kluge: do_command sets this when command
* data from button is avaialble to force top level
* to break out of its loop. */
/*
* Handle a button by running the command COMMAND.
*/
static void
do_command(w, command, call_data)
Widget w;
register char *command;
caddr_t call_data;
{
char cmd_line[256];
char buf[256];
register char *out = cmd_line;
char *cp;
register char c;
extern char *finish_command_input();
while (c = *command++) {
if (c == '%') {
switch (*command++) {
case 's': /* current selection */
out = append_selection(out);
break;
case 'S': /* 1st selected "word" at curor */
out = append_selection_word(out);
break;
case 'e': /* echo cmd before executing */
break;
case 'E': /* 1st selected expression at curor */
out = append_selection_expr(out);
break;
case 'l': /* current line number */
(void) sprintf(buf, "%d", current_lineno());
for (cp = buf; c = *cp++; *out++ = c)
;
break;
case 'L': /* line we're stopped at */
(void) sprintf(buf, "%d", source_window_line);
for (cp = buf; c = *cp++; *out++ = c)
;
break;
case 'f': /* current file name */
for (cp = source_window_symtab->filename;
c = *cp++; *out++ = c)
;
break;
case 'b': /* break # we're stopped at */
if (stop_breakpoint <= 0)
/* if no breakpoint, don't do cmd */
return;
(void) sprintf(buf, "%d", stop_breakpoint);
for (cp = buf; c = *cp++; *out++ = c)
;
break;
}
} else
*out++ = c;
}
*out = 0;
reinitialize_more_filter();
/* have to exit via readline or tty modes stay messed up */
for (cp = cmd_line; c = *cp++; )
rl_stuff_char(c);
rl_stuff_char('\n');
input_avail = 1;
}
/*
* Define and display all the buttons.
*/
static void
addbutton(parent, name, function, closure)
Widget parent;
char *name;
void (*function) ();
caddr_t closure;
{
static XtCallbackRec Callback[] = {
{NULL, (caddr_t) NULL},
{NULL, (caddr_t) NULL},
};
static Arg commandArgs[] = {
{XtNlabel, (XtArgVal) NULL},
{XtNcallback, (XtArgVal) Callback},
};
Widget w;
char wname[128];
register char *cp;
strcpy(wname, name);
while ((cp = index(wname, '*')) || (cp = index(wname, '.')))
*cp -= 0x10;
if (w = XtNameToWidget(parent, wname))
XtDestroyWidget(w);
Callback[0].callback = (XtCallbackProc) function;
Callback[0].closure = (caddr_t) closure;
commandArgs[0].value = (XtArgVal) name;
XtCreateManagedWidget(wname, commandWidgetClass, parent,
commandArgs, XtNumber(commandArgs));
}
/*
* Create the button windows and store them in `buttons'.
*/
static void
create_buttons(parent)
Widget parent;
{
addbutton(parent, "quit", do_command, "quit");
}
static void
button_command(arg)
char *arg;
{
char *label;
unsigned int len;
if (! arg)
error_no_arg("button label and command");
for (len = strlen(arg); len > 0 && isspace(arg[len - 1]); --len)
;
if (len == 0)
error_no_arg("button label and command");
arg[len] = 0;
/* make a copy of button label & command for toolkit to use */
label = malloc(len + 1);
strcpy(label, arg);
/* find the end of the label */
if (*label == '"') {
if ((arg = index(++label, '"')) == 0) {
printf("button label missing closing quote\n");
return;
}
*arg++ = 0;
} else if (arg = index(label, ' '))
*arg++ = 0;
else
arg = label;
while (*arg && isspace(*arg))
++arg;
addbutton(button_box_widget, label, do_command, arg);
}
static void
button_delete_command(arg)
char *arg;
{
unsigned int len;
Widget w;
register char *cp;
if (! arg)
error_no_arg("button name");
for (len = strlen(arg); len > 0 && isspace(arg[len - 1]); --len)
;
if (len == 0)
error_no_arg("button name");
arg[len] = 0;
/* find the end of the label */
if (*arg == '"') {
if ((cp = index(++arg, '"')) == 0) {
printf("button label missing closing quote\n");
return;
}
*cp++ = 0;
}
while ((cp = index(arg, '*')) || (cp = index(arg, '.')))
*cp -= 0x10;
if (w = XtNameToWidget(button_box_widget, arg))
XtDestroyWidget(w);
}
/*
* Create a "label window" that just displays the string LABEL.
*/
static Widget
create_label(name, label)
char *name, *label;
{
Arg args[1];
Widget w;
XtSetArg(args[0], XtNlabel, label);
w = XtCreateManagedWidget(name, labelWidgetClass, containing_widget,
args, XtNumber(args));
return (w);
}
/*
* Create a subwindow of PARENT that displays and scrolls the contents of
* file FILENAME.
*/
static Widget
create_text_widget(parent, filename)
Widget parent;
char *filename;
{
static Arg arg[] = {
{XtNstring, NULL},
{XtNtype, XawAsciiFile},
{XtNcursor, None},
};
Widget text_widget;
arg[0].value = (XtArgVal)filename;
text_widget = XtCreateManagedWidget("src", asciiTextWidgetClass,
parent, arg, XtNumber(arg));
return (text_widget);
}
/*
* Entry point to create the widgets representing our display.
*/
void
xgdb_create_window()
{
/* initialize toolkit, setup defaults */
#ifdef notyet
main_widget = XtAppInitialize(&app_context, "Xgdb", NULL, 0,
argcptr, argv, NULL, NULL, 0);
#else
char *dummy_argv[] = { "xgdb", 0 };
int dummy_argc = 1;
main_widget = XtAppInitialize(&app_context, "Xgdb", NULL, 0,
&dummy_argc, dummy_argv, NULL, NULL, 0);
#endif
display = XtDisplay(main_widget);
containing_widget = XtCreateManagedWidget("frame", panedWidgetClass,
main_widget, NULL, 0);
sprintf(version_label, "XGDB %s", version);
button_box_widget = XtCreateManagedWidget("buttons", boxWidgetClass,
containing_widget, NULL, 0);
create_buttons(button_box_widget);
source_name_widget = create_label("srcLabel", "No source file yet.");
source_text_widget = create_text_widget(containing_widget, "/dev/null");
XtRealizeWidget(main_widget);
XFlush(display);
}
/*
* If we use an X window, the readline input loop is told to call
* this function before reading a character from stdin.
*/
/*ARGSUSED*/
static void
xgdb_window_hook()
{
register int inmask = 1 << fileno(stdin);
register int xmask = 1 << ConnectionNumber(display);
register int nfds, pend;
int input_rfds;
XEvent ev;
/*
* Display our current idea of the `interesting' source file then
* loop, dispatching window events until data is available on
* stdin. Then return so the input data can be processed.
*/
input_avail = 0;
xgdb_display_source();
input_rfds = 0;
while (input_avail == 0 && (input_rfds & inmask) == 0) {
pend = XPending(display);
if (!pend) {
input_rfds = inmask | xmask;
nfds = select(32, &input_rfds, 0, 0,
(struct timeval *)0);
if (nfds == -1 && errno == EINTR)
continue;
}
if (pend || (input_rfds & xmask)) {
XNextEvent(display, &ev);
XtDispatchEvent(&ev);
}
}
}
void
_initialize_xgdb()
{
extern void (*window_hook) ();
extern int inhibit_windows;
extern struct cmd_list_element *deletelist;
if (inhibit_windows)
return;
if (! displayname) {
displayname = getenv("DISPLAY");
if (! displayname) {
fprintf(stderr, "xgdb: no display name\n");
inhibit_windows = 1;
return;
}
}
xgdb_create_window();
window_hook = xgdb_window_hook;
add_com("button", class_support, button_command,
"Add command button to xgdb window. First argument is button\n\
label, second is command associated with button. Command can\n\
include printf-like escapes:\n\
%s for current selection,\n\
%S for first 'word' of current selection,\n\
%e for current selection or expression at insertion pt,\n\
%E for current selection or expression at insertion pt,\n\
%l for current line number,\n\
%L for line program stopped at,\n\
%f for current file name,\n\
%b for current breakpoint number.");
add_cmd("button", class_support, button_delete_command,
"Delete a button from the xgdb window.\n\
Argument is name of button to be deleted.",
&deletelist);
}