mirror of
https://github.com/opnsense/src.git
synced 2026-06-08 16:22:46 -04:00
Added GNU gdb to src/gnu
This commit is contained in:
parent
c579b1a9ed
commit
3edf564a32
82 changed files with 60574 additions and 0 deletions
249
gnu/usr.bin/gdb/COPYING
Normal file
249
gnu/usr.bin/gdb/COPYING
Normal 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
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
15
gnu/usr.bin/gdb/Gdbinit
Normal 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
38
gnu/usr.bin/gdb/Makefile
Normal 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
|
||||
371
gnu/usr.bin/gdb/Makefile.dist
Normal file
371
gnu/usr.bin/gdb/Makefile.dist
Normal 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
114
gnu/usr.bin/gdb/Projects
Normal 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
142
gnu/usr.bin/gdb/README.gnu
Normal 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.
|
||||
|
||||
15
gnu/usr.bin/gdb/XGdbinit.samp
Normal file
15
gnu/usr.bin/gdb/XGdbinit.samp
Normal 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
8
gnu/usr.bin/gdb/Xgdb.ad
Normal 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
|
||||
622
gnu/usr.bin/gdb/blockframe.c
Normal file
622
gnu/usr.bin/gdb/blockframe.c
Normal 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
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
856
gnu/usr.bin/gdb/command.c
Normal 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
77
gnu/usr.bin/gdb/command.h
Normal 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 ();
|
||||
6
gnu/usr.bin/gdb/config/Makefile.i386
Normal file
6
gnu/usr.bin/gdb/config/Makefile.i386
Normal 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
|
||||
585
gnu/usr.bin/gdb/config/default-dep.c
Normal file
585
gnu/usr.bin/gdb/config/default-dep.c
Normal 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);
|
||||
}
|
||||
1275
gnu/usr.bin/gdb/config/i386-dep.c
Normal file
1275
gnu/usr.bin/gdb/config/i386-dep.c
Normal file
File diff suppressed because it is too large
Load diff
1812
gnu/usr.bin/gdb/config/i386-pinsn.c
Normal file
1812
gnu/usr.bin/gdb/config/i386-pinsn.c
Normal file
File diff suppressed because it is too large
Load diff
1867
gnu/usr.bin/gdb/config/i386bsd-dep.c
Normal file
1867
gnu/usr.bin/gdb/config/i386bsd-dep.c
Normal file
File diff suppressed because it is too large
Load diff
28
gnu/usr.bin/gdb/config/m-i386-sv32.h
Normal file
28
gnu/usr.bin/gdb/config/m-i386-sv32.h
Normal 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
|
||||
394
gnu/usr.bin/gdb/config/m-i386.h
Normal file
394
gnu/usr.bin/gdb/config/m-i386.h
Normal 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
|
||||
374
gnu/usr.bin/gdb/config/m-i386bsd.h
Normal file
374
gnu/usr.bin/gdb/config/m-i386bsd.h
Normal 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
|
||||
28
gnu/usr.bin/gdb/config/m-i386g-sv32.h
Normal file
28
gnu/usr.bin/gdb/config/m-i386g-sv32.h
Normal 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
|
||||
37
gnu/usr.bin/gdb/config/m-i386gas.h
Normal file
37
gnu/usr.bin/gdb/config/m-i386gas.h
Normal 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
215
gnu/usr.bin/gdb/copying.c
Normal 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
581
gnu/usr.bin/gdb/core.c
Normal 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
996
gnu/usr.bin/gdb/cplus-dem.c
Normal 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
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
122
gnu/usr.bin/gdb/defs.h
Normal 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
185
gnu/usr.bin/gdb/environ.c
Normal 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
39
gnu/usr.bin/gdb/environ.h
Normal 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
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
324
gnu/usr.bin/gdb/expprint.c
Normal 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
1782
gnu/usr.bin/gdb/expread.y
Normal file
File diff suppressed because it is too large
Load diff
191
gnu/usr.bin/gdb/expression.h
Normal file
191
gnu/usr.bin/gdb/expression.h
Normal 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
579
gnu/usr.bin/gdb/findvar.c
Normal 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 (®isters[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, ®isters[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 *) ®isters[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 *) ®isters[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, ®isters[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
115
gnu/usr.bin/gdb/frame.h
Normal 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
3
gnu/usr.bin/gdb/gdb.1
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
.\" %W% (Berkeley) %G%
|
||||
.\"
|
||||
.\" placeholder, until we can produce the manual page
|
||||
25
gnu/usr.bin/gdb/getpagesize.h
Normal file
25
gnu/usr.bin/gdb/getpagesize.h
Normal 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
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
142
gnu/usr.bin/gdb/inferior.h
Normal 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
569
gnu/usr.bin/gdb/inflow.c
Normal 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, <c_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, <c_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, <c_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 *)<c_inferior)[i]);
|
||||
printf_filtered ("\n");
|
||||
ioctl (0, TIOCSLTC, <c_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, <c_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
1459
gnu/usr.bin/gdb/infrun.c
Normal file
File diff suppressed because it is too large
Load diff
63
gnu/usr.bin/gdb/kgdb_proto.h
Normal file
63
gnu/usr.bin/gdb/kgdb_proto.h
Normal 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
2240
gnu/usr.bin/gdb/main.c
Normal file
File diff suppressed because it is too large
Load diff
27
gnu/usr.bin/gdb/ngdb.i386/Makefile
Normal file
27
gnu/usr.bin/gdb/ngdb.i386/Makefile
Normal 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
313
gnu/usr.bin/gdb/obstack.c
Normal 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
372
gnu/usr.bin/gdb/obstack.h
Normal 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
1867
gnu/usr.bin/gdb/printcmd.c
Normal file
File diff suppressed because it is too large
Load diff
98
gnu/usr.bin/gdb/readline/ChangeLog
Normal file
98
gnu/usr.bin/gdb/readline/ChangeLog
Normal 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.
|
||||
|
||||
|
||||
114
gnu/usr.bin/gdb/readline/Makefile.gnu
Normal file
114
gnu/usr.bin/gdb/readline/Makefile.gnu
Normal 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
|
||||
50
gnu/usr.bin/gdb/readline/chardefs.h
Normal file
50
gnu/usr.bin/gdb/readline/chardefs.h
Normal 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_ */
|
||||
472
gnu/usr.bin/gdb/readline/emacs_keymap.c
Normal file
472
gnu/usr.bin/gdb/readline/emacs_keymap.c
Normal 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 */
|
||||
};
|
||||
217
gnu/usr.bin/gdb/readline/funmap.c
Normal file
217
gnu/usr.bin/gdb/readline/funmap.c
Normal 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 */
|
||||
1462
gnu/usr.bin/gdb/readline/history.c
Normal file
1462
gnu/usr.bin/gdb/readline/history.c
Normal file
File diff suppressed because it is too large
Load diff
108
gnu/usr.bin/gdb/readline/history.h
Normal file
108
gnu/usr.bin/gdb/readline/history.h
Normal 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 ();
|
||||
|
||||
|
||||
172
gnu/usr.bin/gdb/readline/keymaps.c
Normal file
172
gnu/usr.bin/gdb/readline/keymaps.c
Normal 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 */
|
||||
53
gnu/usr.bin/gdb/readline/keymaps.h
Normal file
53
gnu/usr.bin/gdb/readline/keymaps.h
Normal 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_ */
|
||||
|
||||
|
||||
5557
gnu/usr.bin/gdb/readline/readline.c
Normal file
5557
gnu/usr.bin/gdb/readline/readline.c
Normal file
File diff suppressed because it is too large
Load diff
161
gnu/usr.bin/gdb/readline/readline.h
Normal file
161
gnu/usr.bin/gdb/readline/readline.h
Normal 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_ */
|
||||
|
||||
484
gnu/usr.bin/gdb/readline/vi_keymap.c
Normal file
484
gnu/usr.bin/gdb/readline/vi_keymap.c
Normal 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 */
|
||||
};
|
||||
875
gnu/usr.bin/gdb/readline/vi_mode.c
Normal file
875
gnu/usr.bin/gdb/readline/vi_mode.c
Normal 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
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
185
gnu/usr.bin/gdb/regex.h
Normal 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
|
||||
10
gnu/usr.bin/gdb/remote-sl.c
Normal file
10
gnu/usr.bin/gdb/remote-sl.c
Normal 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
626
gnu/usr.bin/gdb/remote.c
Normal 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,
|
||||
®_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(®s[off], ®_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(®s[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
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
115
gnu/usr.bin/gdb/stab.def
Normal 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
960
gnu/usr.bin/gdb/stack.c
Normal 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
584
gnu/usr.bin/gdb/symmisc.c
Normal 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
523
gnu/usr.bin/gdb/symseg.h
Normal 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
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
384
gnu/usr.bin/gdb/symtab.h
Normal 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
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
690
gnu/usr.bin/gdb/valarith.c
Normal 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
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
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
212
gnu/usr.bin/gdb/value.h
Normal 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
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
20
gnu/usr.bin/gdb/version.c
Normal 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
81
gnu/usr.bin/gdb/wait.h
Normal 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
|
||||
33
gnu/usr.bin/gdb/xgdb/Makefile
Normal file
33
gnu/usr.bin/gdb/xgdb/Makefile
Normal 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
700
gnu/usr.bin/gdb/xgdb/xgdb.c
Normal 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);
|
||||
}
|
||||
Loading…
Reference in a new issue