From 4187119d59afd156703cfcbc6be287c5085f1867 Mon Sep 17 00:00:00 2001 From: "gdb-3.3" Date: Sat, 30 Sep 1989 00:00:00 +0000 Subject: [PATCH] gdb-3.3 --- gdb/.gdbinit | 2 + gdb/COPYING | 353 +- gdb/ChangeLog | 2805 ++++++++++- gdb/Convex.notes | 163 + gdb/Makefile | 240 - gdb/Makefile.dist | 351 ++ gdb/Projects | 114 + gdb/RCS/Makefile,v | 367 -- gdb/RCS/blockframe.c,v | 606 --- gdb/RCS/coffread.c,v | 2047 -------- gdb/RCS/config.gdb,v | 229 - gdb/RCS/core.c,v | 651 --- gdb/RCS/dbxread.c,v | 4610 ------------------ gdb/RCS/findvar.c,v | 584 --- gdb/RCS/gdb.texinfo,v | 3009 ------------ gdb/RCS/gdbcore.h,v | 105 - gdb/RCS/inflow.c,v | 636 --- gdb/RCS/infrun.c,v | 1855 -------- gdb/RCS/m-aux.h,v | 591 --- gdb/RCS/m-sparc.h,v | 747 --- gdb/RCS/m68k-pinsn.c,v | 824 ---- gdb/RCS/main.c,v | 1348 ------ gdb/RCS/munch,v | 75 - gdb/RCS/printcmd.c,v | 1707 ------- gdb/RCS/remote.c,v | 662 --- gdb/RCS/source.c,v | 990 ---- gdb/RCS/sparc-dep.c,v | 1091 ----- gdb/RCS/stack.c,v | 882 ---- gdb/RCS/utils.c,v | 726 --- gdb/RCS/valprint.c,v | 1117 ----- gdb/RCS/values.c,v | 1047 ---- gdb/README | 141 +- gdb/TAGS | 2089 ++++++++ gdb/XGDB-README | 57 + gdb/a.out.encap.h | 28 +- gdb/a.out.gnu.h | 15 +- gdb/alloca.o | Bin 2584 -> 0 bytes gdb/{RCS/default-dep.c,v => altos-dep.c} | 272 +- gdb/blockframe.c | 384 +- gdb/breakpoint.c | 127 +- gdb/coffread.c | 124 +- gdb/command.c | 482 +- gdb/command.h | 123 +- gdb/config.gdb | 219 +- gdb/config.status | 1 - gdb/convex-dep.c | 2177 +++++++-- gdb/convex-opcode.h | 1674 +++++++ gdb/convex-pinsn.c | 314 ++ gdb/copying.awk | 53 + gdb/copying.c | 215 + gdb/core.c | 107 +- gdb/createtags | 5 +- gdb/dbxread.c | 2008 +++++--- gdb/default-dep.c | 123 +- gdb/defs.h | 54 +- gdb/dep.c | 1 - gdb/environ.c | 109 +- gdb/environ.h | 16 + gdb/eval.c | 197 +- gdb/expprint.c | 41 +- gdb/expread.tab.c | 2420 ++++++---- gdb/expread.y | 460 +- gdb/expression.h | 35 +- gdb/findvar.c | 81 +- gdb/frame.h | 30 +- gdb/gdb.texinfo | 1765 ++++--- gdb/gdbcore.h | 68 - gdb/gld-pinsn.c | 35 +- gdb/gould-dep.c | 38 +- gdb/hp-include/a.out.h | 185 +- gdb/hp-include/stab.def | 115 + gdb/hp-include/stab.h | 55 +- gdb/hp-include/sys/fcntl.h | 77 +- gdb/hp300bsd-dep.c | 556 +++ gdb/hp9k320-dep.c | 134 +- gdb/i386-dep.c | 45 +- gdb/i386-pinsn.c | 35 +- gdb/infcmd.c | 193 +- gdb/inferior.h | 35 +- gdb/inflow.c | 120 +- gdb/infrun.c | 315 +- gdb/kdb-start.c | 19 + gdb/{RCS/m-hp9k320.h,v => m-altos.h} | 546 ++- gdb/m-convex.h | 603 +++ gdb/{m-aux.h => m-hp300bsd.h} | 177 +- gdb/m-hp9k320.h | 65 +- gdb/m-i386-sysv3.2.h | 28 + gdb/m-i386.h | 56 +- gdb/m-i386gas-sysv3.2.h | 28 + gdb/m-i386gas.h | 38 +- gdb/m-isi.h | 137 +- gdb/m-merlin.h | 49 +- gdb/m-news.h | 262 +- gdb/m-newsos3.h | 117 + gdb/m-npl.h | 39 +- gdb/m-pn.h | 39 +- gdb/m-sparc.h | 89 +- gdb/m-sun2.h | 49 +- gdb/m-sun2os4.h | 19 + gdb/m-sun3.h | 99 +- gdb/m-sun3os4.h | 24 + gdb/m-sun4os4.h | 21 + gdb/m-symmetry.h | 614 +++ gdb/m-umax.h | 50 +- gdb/m-vax.h | 78 +- gdb/m68k-opcode.h | 489 +- gdb/m68k-pinsn.c | 283 +- gdb/main.c | 1126 +++-- gdb/malloc.c | 67 +- gdb/munch | 15 +- gdb/news-dep.c | 158 +- gdb/npl-opcode.h | 35 +- gdb/ns32k-opcode.h | 21 +- gdb/ns32k-pinsn.c | 83 +- gdb/obstack.c | 125 +- gdb/obstack.h | 108 +- gdb/opcode.h | 1 - gdb/param.h | 1 - gdb/pinsn.c | 1 - gdb/pn-opcode.h | 29 +- gdb/printcmd.c | 719 +-- gdb/readline/ChangeLog | 70 + gdb/readline/Makefile | 114 + gdb/readline/chardefs.h | 50 + gdb/readline/emacs_keymap.c | 472 ++ gdb/readline/funmap.c | 212 + gdb/readline/history.c | 1462 ++++++ gdb/readline/history.h | 108 + gdb/readline/inc-history.texinfo | 187 + gdb/readline/inc-readline.texinfo | 494 ++ gdb/readline/keymaps.c | 172 + gdb/readline/keymaps.h | 53 + gdb/readline/readline.c | 5559 ++++++++++++++++++++++ gdb/readline/readline.h | 161 + gdb/readline/vi_keymap.c | 474 ++ gdb/readline/vi_mode.c | 859 ++++ gdb/regex.c | 126 +- gdb/regex.h | 112 +- gdb/remote-multi.shar | 1313 +++++ gdb/remote-sa.m68k.shar | 893 ++++ gdb/remote.c | 250 +- gdb/source.c | 247 +- gdb/sparc-dep.c | 239 +- gdb/sparc-opcode.h | 716 ++- gdb/sparc-pinsn.c | 975 ++-- gdb/stab.def | 116 +- gdb/stack.c | 234 +- gdb/standalone.c | 35 +- gdb/stuff.c | 35 +- gdb/sun3-dep.c | 75 +- gdb/symmetry-dep.c | 1285 +++++ gdb/symmisc.c | 39 +- gdb/symseg.h | 73 +- gdb/symtab.c | 761 ++- gdb/symtab.h | 79 +- gdb/tags | 799 ---- gdb/umax-dep.c | 37 +- gdb/utils.c | 442 +- gdb/valarith.c | 330 +- gdb/valops.c | 171 +- gdb/valprint.c | 936 ++-- gdb/value.h | 40 +- gdb/values.c | 173 +- gdb/vax-opcode.h | 23 +- gdb/vax-pinsn.c | 35 +- gdb/version.c | 21 +- gdb/xgdb.c | 50 +- 167 files changed, 40111 insertions(+), 35990 deletions(-) create mode 100644 gdb/Convex.notes delete mode 100644 gdb/Makefile create mode 100644 gdb/Makefile.dist create mode 100644 gdb/Projects delete mode 100644 gdb/RCS/Makefile,v delete mode 100644 gdb/RCS/blockframe.c,v delete mode 100644 gdb/RCS/coffread.c,v delete mode 100755 gdb/RCS/config.gdb,v delete mode 100644 gdb/RCS/core.c,v delete mode 100644 gdb/RCS/dbxread.c,v delete mode 100644 gdb/RCS/findvar.c,v delete mode 100644 gdb/RCS/gdb.texinfo,v delete mode 100644 gdb/RCS/gdbcore.h,v delete mode 100644 gdb/RCS/inflow.c,v delete mode 100644 gdb/RCS/infrun.c,v delete mode 100644 gdb/RCS/m-aux.h,v delete mode 100644 gdb/RCS/m-sparc.h,v delete mode 100644 gdb/RCS/m68k-pinsn.c,v delete mode 100644 gdb/RCS/main.c,v delete mode 100755 gdb/RCS/munch,v delete mode 100644 gdb/RCS/printcmd.c,v delete mode 100644 gdb/RCS/remote.c,v delete mode 100644 gdb/RCS/source.c,v delete mode 100644 gdb/RCS/sparc-dep.c,v delete mode 100644 gdb/RCS/stack.c,v delete mode 100644 gdb/RCS/utils.c,v delete mode 100644 gdb/RCS/valprint.c,v delete mode 100644 gdb/RCS/values.c,v create mode 100644 gdb/TAGS create mode 100644 gdb/XGDB-README delete mode 100644 gdb/alloca.o rename gdb/{RCS/default-dep.c,v => altos-dep.c} (72%) delete mode 100644 gdb/config.status create mode 100644 gdb/convex-opcode.h create mode 100644 gdb/convex-pinsn.c create mode 100644 gdb/copying.awk create mode 100644 gdb/copying.c delete mode 120000 gdb/dep.c delete mode 100644 gdb/gdbcore.h create mode 100644 gdb/hp-include/stab.def create mode 100644 gdb/hp300bsd-dep.c rename gdb/{RCS/m-hp9k320.h,v => m-altos.h} (54%) create mode 100644 gdb/m-convex.h rename gdb/{m-aux.h => m-hp300bsd.h} (82%) create mode 100644 gdb/m-i386-sysv3.2.h create mode 100644 gdb/m-i386gas-sysv3.2.h create mode 100644 gdb/m-newsos3.h create mode 100644 gdb/m-symmetry.h delete mode 120000 gdb/opcode.h delete mode 120000 gdb/param.h delete mode 120000 gdb/pinsn.c create mode 100644 gdb/readline/ChangeLog create mode 100644 gdb/readline/Makefile create mode 100644 gdb/readline/chardefs.h create mode 100644 gdb/readline/emacs_keymap.c create mode 100644 gdb/readline/funmap.c create mode 100644 gdb/readline/history.c create mode 100644 gdb/readline/history.h create mode 100644 gdb/readline/inc-history.texinfo create mode 100644 gdb/readline/inc-readline.texinfo create mode 100644 gdb/readline/keymaps.c create mode 100644 gdb/readline/keymaps.h create mode 100644 gdb/readline/readline.c create mode 100644 gdb/readline/readline.h create mode 100644 gdb/readline/vi_keymap.c create mode 100644 gdb/readline/vi_mode.c create mode 100644 gdb/remote-multi.shar create mode 100644 gdb/remote-sa.m68k.shar create mode 100644 gdb/symmetry-dep.c delete mode 100644 gdb/tags diff --git a/gdb/.gdbinit b/gdb/.gdbinit index c9e6296243..bcacd5dc7e 100644 --- a/gdb/.gdbinit +++ b/gdb/.gdbinit @@ -1,3 +1,5 @@ +echo Setting up the environment for debugging gdb.\n + b fatal b info_command diff --git a/gdb/COPYING b/gdb/COPYING index eb1bf4f189..9a17037581 100644 --- a/gdb/COPYING +++ b/gdb/COPYING @@ -1,86 +1,106 @@ - GDB GENERAL PUBLIC LICENSE - (Clarified 11 Feb 1988) + GNU GENERAL PUBLIC LICENSE + Version 1, February 1989 - Copyright (C) 1988 Richard M. Stallman + 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, but changing it is not allowed. You can also - use this wording to make the terms for other programs. - - The license agreements of most software companies keep you at the -mercy of those companies. By contrast, our general public license is -intended to give everyone the right to share GDB. To make sure that -you get the rights we want you to have, we need to make restrictions -that forbid anyone to deny you these rights or to ask you to surrender -the rights. Hence this license agreement. - - Specifically, we want to make sure that you have the right to give -away copies of GDB, that you receive source code or else can get it -if you want it, that you can change GDB or use pieces of it in new -free programs, and that you know you can do these things. - - To make sure that everyone has such rights, we have to forbid you to -deprive anyone else of these rights. For example, if you distribute -copies of GDB, you must give the recipients all the rights that you -have. You must make sure that they, too, receive or can get the + 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. - Also, for our own protection, we must make certain that everyone -finds out that there is no warranty for GDB. If GDB is modified by -someone else and passed on, we want its recipients to know that what -they have is not what we distributed, so that any problems introduced -by others will not reflect on our reputation. - - Therefore we (Richard Stallman and the Free Software Foundation, -Inc.) make the following terms which say what you must do to be -allowed to distribute or change GDB. - - - COPYING POLICIES - - 1. You may copy and distribute verbatim copies of GDB source code as -you receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy a valid copyright notice "Copyright -(C) 1988 Free Software Foundation, Inc." (or with whatever year is -appropriate); keep intact the notices on all files that refer to this -License Agreement and to the absence of any warranty; and give any -other recipients of the GDB program a copy of this License Agreement -along with the program. You may charge a distribution fee for the -physical act of transferring a copy. - - 2. You may modify your copy or copies of GDB 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 or is a derivative of GDB or any - part thereof, to be licensed at no charge to all third parties on - terms identical to those contained in this License Agreement - (except that you may choose to grant more extensive warranty - protection to third parties, at your option). - - c) if the modified program serves as a debugger, cause it when - started running in the simplest and usual way, to print an - announcement including a valid copyright notice "Copyright (C) - 1988 Free Software Foundation, Inc." (or with the year that is - appropriate), saying 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 License Agreement. - - d) You may charge a distribution 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 unrelated program with this program (or its + 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 program under the scope of these terms. - - 3. You may copy and distribute GDB (or a portion or derivative of it, -under Paragraph 2) in object code or executable form under the terms of +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 @@ -88,8 +108,8 @@ Paragraphs 1 and 2 above provided that you also do one of the following: 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 - shipping charge) a complete machine-readable copy of the + 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, @@ -98,49 +118,132 @@ Paragraphs 1 and 2 above provided that you also do one of the following: allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) -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. - - 4. You may not copy, sublicense, distribute or transfer GDB -except as expressly provided under this License Agreement. Any attempt -otherwise to copy, sublicense, distribute or transfer GDB is void and -your rights to use the program under this License agreement shall be -automatically terminated. However, parties who have received computer -software programs from you with this License Agreement will not have -their licenses terminated so long as such parties remain in full compliance. - - 5. If you wish to incorporate parts of GDB into other free programs -whose distribution conditions are different, write to the Free -Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not -yet worked out a simple rule that can be stated here, but we will -often permit this. We 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. - -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! - - NO WARRANTY - - BECAUSE GDB IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO -WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT -WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, -RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE GDB "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 GDB IS WITH YOU. SHOULD GDB PROVE DEFECTIVE, YOU -ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. -STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY -WHO MAY MODIFY AND REDISTRIBUTE GDB AS PERMITTED ABOVE, BE LIABLE TO -YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER -SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR -INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA -BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A -FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GDB, EVEN -IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR -ANY CLAIM BY ANY OTHER PARTY. +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. + + + Copyright (C) 19yy + + 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. + + , 1 April 1989 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8a68eed096..7bef1f0d9d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,2704 @@ +Sat Sep 30 12:50:16 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * version.c: Change version number to 3.3. + + * Makefile.dist (READLINE): Add vi_mode.c + + * config.gdb (i386): Change /dev/null to m-i386.h + + * config.gdb: Add ';;' before 'esac'. + + * Makefile.dist (gdb.tar.Z): Move comment above dependency. + + * dbxread.c (read_ofile_symtab): Check symbol before start + of source file for GCC_COMPILED_FLAG_SYMBOL. + (start_symtab): Don't clear processing_gcc_compilation. + +Thu Sep 28 22:30:23 1989 Roland McGrath (roland at hobbes.ai.mit.edu) + + * valprint.c (print_string): If LENGTH is zero, print "". + +Wed Sep 27 10:15:10 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * config.gdb: "rm tmp.c" -> "rm -f tmp.c". + +Tue Sep 26 13:02:10 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * utils.c (_initialize_utils): Use termcap to set lines_per_page + and chars_per_line. + +Mon Sep 25 10:06:43 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * dbxread.c (read_dbx_symtab, N_SOL): Do not add the same file + more than once. + +Thu Sep 21 12:43:18 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * infcmd.c (unset_environment_command): Delete all variables + if called with no arg. + + * remote.c, inferior.h (remote_{read,write}_inferior_memory): + New functions. + core.c ({read,write}_memory): Use remote_{read,write}_inferior_memory. + + * valops.c (call_function): When reserving stack space for + arguments, call value_arg_coerce. + + * m-hp9k320.h: define BROKEN_LARGE_ALLOCA. + + * breakpoint.c (delete_command): Ask for confirmation only + when there are breakpoints. + + * dbxread.c (read_struct_type): If lookup_basetype_type has + copied a stub type, call add_undefined_type. + + * sparc_pinsn.c (compare_opcodes): Check for "1+i" anywhere + in args. + + * val_print.c (type_print_base): Print stub types as + "". + +Wed Sep 20 07:32:00 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * sparc-opcode.h (swapa): Remove i bit from match. + (all alternate space instructions): Delete surplus "foo rs1+0" + patterns. + + * Makefile.dist (LDFLAGS): Set to $(CFLAGS). + + * remote-multi.shar (remote_utils.c, putpkt): Change csum to unsigned. + +Tue Sep 19 14:15:16 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * sparc-opcode.h: Set i bit in lose for many instructions which + aren't immediate. + + * stack.c (print_frame_info): add "func = 0". + +Mon Sep 18 16:19:48 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * sparc-opcode.h (mov): Add mov to/from %tbr, %psr, %wim. + + * sparc-opcode.h (rett): Fix notation to use suggested assembler + syntax from architecture manual. + + * symmetry-dep.c (I386_REGNO_TO_SYMMETRY): New macro. + (i386_frame_find_saved_regs): Use I386_REGNO_TO_SYMMETRY. + +Sat Sep 16 22:21:17 1989 Jim Kingdon (kingdon at spiff) + + * remote.c (remote_close): Set remote_desc to -1. + + * gdb.texinfo (Output): Fix description of echo to match + reality and ANSI C. + +Fri Sep 15 14:28:59 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * symtab.c (lookup_symbol): Add comment about "asm". + + * sparc-pinsn.c: Use NUMOPCODES. + + * sparc-opcode.h (NUMOPCODES): Use sparc_opcodes[0] not *sparc_opcodes. + +Thu Sep 14 15:25:20 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * dbxread.c (xxmalloc): Print error message before calling abort(). + + * infrun.c (wait_for_inferior): Check for {stop,prev}_func_name + null before passing to strcmp. + +Wed Sep 13 12:34:15 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * sparc-opcode.h: New field delayed. + sparc-pinsn.c (is_delayed_branch): New function. + (print_insn): Check for delayed branches. + + * stack.c (print_frame_info): Use misc_function_vector in + case where ar truncates file names. + +Tue Sep 12 00:16:14 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * convex-dep.c (psw_info): Move "struct pswbit *p" with declarations. + +Mon Sep 11 14:59:57 1989 Jim Kingdon (kingdon at spiff) + + * convex-dep.c (core_file_command): Delete redundant printing + of "Program %s". + + * m-convex.h (ENTRY_POINT): New macro. + + * m-convex.h (FRAME_CHAIN_VALID): Change outside_first_object_file + to outside_startup_file + + * main.c: #if 0 out catch_termination and related code. + + * command.c (lookup_cmd_1): Consider underscores part of + command names. + +Sun Sep 10 09:20:12 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * printcmd.c: Change asdump_command to disassemble_command + (_initialize_printcmd): Change asdump to diassemble. + + * main.c (main): Exit with code 0 if we hit the end of a batch + file. + + * Makefile.dist (libreadline.a): Fix syntax of "CC=${CC}". + +Sat Sep 9 01:07:18 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * values.c (history_info): Renamed to value_history_info. + Command renamed to "info value" (with "info history" still + accepted). + + * sparc-pinsn.c (print_insn): Extend symbolic address printing + to cover "sethi" following by an insn which uses 1+i. + +Fri Sep 8 14:24:01 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * m-hp9k320.h, m-hp300bsd.h, m-altos.h, m-sparc.h, m-sun3.h + (READ_GDB_SYMSEGS): Remove. + dbxread.c [READ_GDB_SYMSEGS]: Remove code to read symsegs. + + * sparc-pinsn.c (print_insn): Detect "sethi-or" pairs and + print symbolic address. + + * sparc-opcode.h (sethi, set): Change lose from 0xc0000000 to + 0xc0c00000000. + + * remote.c (remote_desc): Initialize to -1. + + * Makefile.dist (libreadline.a): Pass CC='${CC}' to readline makefile. + +Thu Sep 7 00:07:17 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * dbxread.c (read_struct_type): Check for static member functions. + values.c, eval.c, valarith.c, valprint.c, valops.c: Merge changes + from Tiemann for static member functions. + + * sparc-opcode.h (tst): Fix all 3 patterns. + + * Makefile.dist (gdb1): New rule. + + * sparc-opcode.h: Change comment about what the disassembler + does with the order of the opcodes. + + * sparc-pinsn.c (compare_opcodes): Put 1+i before i+1. + Also fix mistaken comment about preserving order of original table. + + * sparc-opcode.h (clr, mov): Fix incorrect lose entries. + + * m-symmetry.h (FRAME_NUM_ARGS): Add check to deal with code that + GCC sometimes generates. + + * config.gdb: Change all occurances of "skip" to "/dev/null". + + * README (about languages other than C): Update comments about + Pascal and FORTRAN. + + * sparc-opcode.h (nop): Change lose from 0xae3fffff to 0xfe3fffff. + + * values.c (value_virtual_fn_field): #if 0-out assignment to + VALUE_TYPE(vtbl). + +Wed Sep 6 12:19:22 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * utils.c (fatal_dump_core): New function. + Makefile.dist (MALLOC_FLAGS): use -Dbotch=fatal_dump_core + +Tue Sep 5 15:47:18 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * breakpoint.c (enable_command): With no arg, enable all bkpts. + + * Makefile.dist (Makefile): Remove \"'s around $(MD). + + * Makefile.dist: In "cd readline; make . . ." change first + SYSV_DEFINE to SYSV. + + * m68k-pinsn.c (_initialize_pinsn): Use alternate assembler + syntax #ifdef HPUX_ASM + +Sat Sep 2 23:24:43 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * values.c (history_info): Don't check num_exp[0] if num_exp + is nil (just like recent editing_info change). + +Fri Sep 1 19:19:01 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * gdb.texinfo (inc-history, inc-readline): Copy in the inc-* files + because people might not have makeinfo. + + * README (xgdb): Strengthen nasty comments. + + * gdb.texinfo: Change @setfilename to "gdb.info". + +Thu Aug 31 17:23:50 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * main.c (editing_info): Don't check arg[0] if arg is null. + + * m-vax.h: Add comment about known sigtramp bug. + + * sun3-dep.c, sparc-dep.c (IS_OBJECT_FILE, exec_file_command): + Get right text & data addresses for .o files. + +Wed Aug 30 13:54:19 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * utils.c (tilde_expand): Remove function (it's in readline). + + * sparc-opcode.h (call): Change "8" to "9" in first two + patterns (%g7->%o7). + +Tue Aug 29 16:44:41 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * printcmd.c (whatis_command): Change 4th arg to type_print + from 1 to -1. + +Mon Aug 28 12:22:41 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * dbxread.c (psymtab_to_symtab_1): In "and %s ..." change + pst->filename to pst->dependencies[i]->filename. + + * blockframe.c (FRAMELESS_LOOK_FOR_PROLOGUE): New macro + made from FRAMELESS_FUNCTION_INVOCATION from m-sun3.h except + that it checks for zero return from get_pc_function_start. + m-hp9k320.h, m-hp300bsd.h, m-i386.h, m-isi.h, m-altos.h, + m-news.h, m-sparc.h, m-sun2.h, m-sun3.h, m-symmetry.h + (FRAMELESS_FUNCTION_INVOCATION): Use FRAMELESS_LOOK_FOR_PROLOGUE. + + * dbxread.c (read_struct_type): Give warning and ignore field + if bitpos and bitsize are zero. + +Sun Aug 27 04:55:20 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * dbxread.c (psymtab_to_symtab{,_1}): Print message about + reading in symbols before reading stringtab, not after. + +Sat Aug 26 02:01:53 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * dbxread.c (IS_OBJECT_FILE, ADDR_OF_TEXT_SEGMENT): New macros. + (read_dbx_symtab): Use text_addr & text_size to set end_of_text_addr. + (symbol_file_command): pass text_addr & text_size to read_dbx_symtab. + +Fri Aug 25 23:08:13 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * valprint.c (value_print): Try to give the name of function + pointed to when printing a function pointer. + +Thu Aug 24 23:18:40 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * core.c (xfer_core_file): In cases where MEMADDR is above the + largest address that makes sense, set i to len. + +Thu Aug 24 16:04:17 1989 Roland McGrath (roland at hobbes.ai.mit.edu) + + * valprint.c (print_string): New function to print a character + string, doing array-max limiting and repeat count processing. + (val_print, value_print): Use print_string. + (REPEAT_COUNT_THRESHOLD): New #define, the max number of elts to print + without using a repeat count. Set to ten. + (value_print, val_print): Use REPEAT_COUNT_THRESHOLD. + + * utils.c (printchar): Use {fputs,fprintf}_filtered. + + * valprint.c (val_print): Pass the repeat count arg to the + fprintf_filtered call for "" messages. + +Wed Aug 23 22:53:47 1989 Roland McGrath (roland at hobbes.ai.mit.edu) + + * utils.c: Include . + + * main.c: Declare free. + +Wed Aug 23 05:05:59 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * utils.c, defs.h: Add tilde_expand. + source.c (directory_command), + main.c (cd_command), + main.c (set_history_filename), + dbxread.c (symbol_file_command), + coffread.c (symbol_file_command), + dbxread.c (add_file_command), + symmisc.c (print_symtabs), + *-dep.c (exec_file_command, core_file_command), + main.c (source_command): Use tilde_expand. + + * dbxread.c (read_type): When we get a cross-reference, resolve + it immediately if possible, only calling add_undefined_type if + necessary. + + * gdb.texinfo: Uncomment @includes and put comment at start + of file telling people to use makeinfo. + + * valprint.c (type_print_base): Print the right thing for + bitfields. + + * config.gdb (sun3os3): Set paramfile and depfile. + +Tue Aug 22 05:38:36 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * dbxread.c (symbol_file_command): Pass string table size to + read_dbx_symtab(). + (read_dbx_symtab): Before indexing into string table, check + string table index for reasonableness. + (psymtab_to_symtab{,_1}, read_ofile_symtab): Same. + +Tue Aug 22 04:04:39 1989 Roland McGrath (roland at hobbes.ai.mit.edu) + + * m68k-pinsn.c: Replaced many calls to fprintf and fputs with + calls to fprintf_filtered and fputs_filtered. + (print_insn_arg): Use normal MIT 68k syntax for postincrement, + predecrement, and register indirect addressing modes. + +Mon Aug 21 10:08:02 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * main.c (initialize_signals): Set signal handler for SIGQUIT + and SIGHUP to do_nothing. + + * ns32k-opcode.h (ord): Change 1D1D to 1D2D. + + * ns32k-pinsn.c (print_insn_arg, print_insn): Handle index + bytes correctly. + + * ns32k-opcode.h: Add comments. + + * dbxread.c (read_type): Put enum fields in type.fields in order + that they were found in the debugging symbols (not reverse order). + +Sun Aug 20 21:17:13 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * main.c (source_command): Read .gdbinit if run without argument. + + * source.c (directory_command): Only print "foo already in path" + if from_tty. + + * version.c: Change version number to 3.2.xxx + +Sat Aug 19 00:24:08 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * m-news.h: Define HAVE_WAIT_STRUCT. + + * m-isi.h, isi-dep.c: Replace with new version from Adam de Boor. + config.gdb: Remove isibsd43. + + * main.c (catch_termination): Don't say we have written + .gdb_history until after we really have. + + * convex-dep.c (attach): Add "sleep (1)". + (write_vector_register): Use "LL" with long long constant. + (wait): Close comment. + (wait): Change "unix 7.1 bug" to "unix 7.1 feature" & related + changes in comment. + (scan_stack): And fp with 0x80000000 in while loop test. + (core_file_command): Move code to set COREFILE. + (many places): Change printf to printf_filtered. + (psw_info): Allow argument giving value to print as a psw. + (_initialize_convex_dep): Update docstrings. + + * m-convex.h (WORDS_BIG_ENDIAN): Correct typo ("WRODS") + define NO_SIGINTERRUPT. + define SET_STACK_LIMIT_HUGE. + add "undef BUILTIN_TYPE_LONGEST" before defining it. + Use "LL" after constants in CALL_DUMMY. + + * dbxread.c: In the 3 places it says error "ridiculous string + table size"... delete extra parameter to error. + + * dbxread.c (scan_file_globals): Check for FORTRAN common block. + Allow multiple references for the sake of common blocks. + + * main.c (initialize_main): Set history_filename to include + current directory. + + * valprint.c (decode_format): Don't return a defaulted size + field if osize is zero. + + * gdb.texinfo (Compilation): Update information on -gg symbols. + Document problem with ar. + +Fri Aug 18 19:45:20 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * valprint.c (val_print, value_print): Add "" code. + Also put "..." outside quotes for strings. + + * main.c (initialize_main): Add comment about history output file + being different from history input file. + + * m-newsos3.h: Undefine NO_SIGINTERRUPT. Rearrange a few comments. + + * m-newsos3.h (REGISTER_U_ADDR): Use new version from Hikichi. + + * sparc-opcode.h: Add comment clarifying meaning of the order of + the entries in sparc_opcodes. + + * eval.c (evaluate_subexp, case UNOP_IND): Deal with deferencing + things that are not pointers. + + * valops.c (value_ind): Make dereferencing an int give a LONGEST. + + * expprint.c (print_subexp): Add (int) cast in OP_LAST case. + + * dbxread.c (read_array_type): Set lower and upper if adjustable. + + * symtab.c (lookup_symbol): Don't abort if symbol found in psymtab + but not in symtab. + +Thu Aug 17 15:51:20 1989 Randy Smith (randy at hobbes.ai.mit.edu) + + * config.gdb: Changed "Makefile.c" to "Makefile.dist". + +Thu Aug 17 01:58:04 1989 Roland McGrath (roland at apple-gunkies.ai.mit.edu) + + * sparc-opcode.h (or): Removed incorrect lose bit 0x08000000. + [many]: Changed many `lose' entries to have the 0x10 bit set, so + they don't think %l0 is %g0. + +Wed Aug 16 00:30:44 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * m-symmetry.h (STORE_STRUCT_RETURN): Also write reg 0. + (EXTRACT_RETURN_VALUE): Call symmetry_extract_return_value. + symmetry-dep.c (symmetry_extract_return_value): New fn. + + * main.c (symbol_completion_function): Deal with changed + result_list from lookup_cmd_1 for ambiguous return. + command.c (lookup_cmd): Same. + + * inflow.c [TIOCGETC]: Move #include "param.h" back before + system #includes. Change all #ifdef TIOCGETC to + #if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) + m-i386-sysv3.2.h, m-i386gas-sysv3.2.h: Remove "#undef TIOCGETC" + and add "#define TIOCGETC_BROKEN". + + * command.c (lookup_cmd_1): Give the correct result_list in the + case of an ambiguous return where there is a partial match + (e.g. "info a"). Add comment clarifying what is the correct + result_list. + + * gdb.texinfo (GDB History): Document the two changes below. + + * main.c (command_line_input): Make history expansion not + just occur at the beginning of a line. + + * main.c (initialize_main): Make history expansion off by default. + + * inflow.c: Move #include "param.h" after system #includes. + + * i386-dep.c (i386_float_info): Use U_FPSTATE macro. + + * m-i386-sysv3.2.h, m-i386gas-sysv3.2.h: New files. + Makefile.dist, config.gdb: Know about these new files. + +Tue Aug 15 21:36:11 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * symtab.c (lookup_struct_elt_type): Use type_print rather + than assuming type has a name. + +Tue Aug 15 02:25:43 1989 Roland McGrath (roland at apple-gunkies.ai.mit.edu) + + * sparc-opcode.h (mov): Removed bogus "or i,0,d" pattern. + + * sparc-opcode.h (mov, or): Fixed incorrect `lose' members. + + * sparc-dep.c: Don't include "sparc-opcode.h". + (skip_prologue, isanulled): Declare special types to recognize + instructions, and use them. + + * sparc-pinsn.c (print_insn): Sign-extend 13-bit immediate args. + If they are less than +9, print them in signed decimal instead + of unsigned hex. + + * sparc-opcode.h, sparc-pinsn.c: Completely rewritten to share an + opcode table with gas, and thus produce disassembly that looks + like what the assembler accepts. + +Tue Aug 15 16:20:52 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * symtab.c (find_pc_psymbol): Move best_pc=psymtab->textlow-1 + after test for psymtab null. + + * main.c (editing_info): Remove variable retval. + + * config.gdb (sun3, isi): Comment out obsolete message about telling + it whether you have an FPU (now that it detects it). + + * config.gdb (sun3): Accept sun3os3. + + * m68k-insn.h: Include . + + * m68k-pinsn.h (convert_{to,from}_68881): Add have_fpu code + + * m-newsos3.h: Undefine USE_PCB. That code didn't seem to work. + + * sparc-dep.c: Put in insn_fmt and other stuff from the old + sparc-opcode.h. + + * sparc-opcode.h, sparc-pinsn.c: Correct copyright notice. + + * sparc-opcode.h, sparc-pinsn.c: Replace the old ones with the new + ones by roland. + +Tue Aug 15 02:25:43 1989 Roland McGrath (roland at apple-gunkies.ai.mit.edu) + + * Makefile.dist: Don't define CC at all. + + * Makefile.dist (Makefile): Remove tmp.c after preprocessing. + Use $(MD) instead of M_MAKEDEFINE in the cc command. + + * Makefile.dist: Don't define RL_LIB as + "${READLINE}/libreadline.a", since READLINE is a list of files. + +Mon Aug 14 23:49:29 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * main.c (print_version): Change 1988 to 1989. + + * main.c (copying_info, initialize_main): Remove #if 0'd code. + +Tue Aug 1 14:44:56 1989 Hikichi (hikichi at sran203) + + * m-newsos3.h + (NO_SIGINTERRUPT): have SIGINTERRUPT on NEWS os 3. + + * m-news.h(FRAME_FIND_SAVED_REGS): use the sun3's instead of old + one. + +Mon Aug 14 15:27:01 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * m-news.h, m-newsos3.h, news-dep.c: Merge additional changes + by Hikichi (ChangeLog entries above). + + * Makefile.dist (READLINE): List readline files individually + so we don't accidently get random files from the readline + directory. + + * m-news.h (STORE_RETURN_VALUE, EXTRACT_RETURN_VALUE): + Expect floating point returns to be in fp0. + + * gdb.texinfo (Format options): New node. + + * gdb.texinfo: Comment out "@include"s until bfox fixes the + readline & history docs. + + * dbxread.c (read_addl_syms): Set startup_file_* if necessary at + the end (as well as when we hit ".o"). + + * printcmd.c (decode_format): Set val.format & val.size to '?' at + start and set defaults at end. + + * symtab.c (decode_line_1): Check for class_name null. + + * valops.c: Each place where it compares against field names, + check for null field names. (new t_field_name variables). + + * utils.c (fputs_filtered): Check for linebuffer null before + checking whether to call fputs. Remove later check for linebuffer + null. + +Sun Aug 13 15:56:50 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * m-isi.h, m-sun3.h ({PUSH,POP}_FP_REGS): New macros. + m-sun3.h (NUM_REGS): Conditionalize on FPU. + config.gdb (sun3, isi): Add message about support for machines + without FPU. + + * main.c (catch_termination, initialize_signals): new functions. + + * main.c (editing_info): Add "info editing n" and "info editing +". + Rewrite much of this function. + gdb.texinfo (GDB Readline): Document it. + + * values.c (history_info): Add "info history +". Also add code to + do "info history +" when command is repeated. + gdb.texinfo (Value History): Document "info history +". + + * expprint.c (print_subexp): Add OP_THIS to case stmt. + + * config.gdb (sun4os4): Put quotes around make define. + + * config.gdb: Canonicalize machine name at beginning. + +Sat Aug 12 00:50:59 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * config.gdb: define M_MAKEDEFINE + Makefile (Makefile, MD): Be able to re-make Makefile. + + * main.c (command_line_input): Add comments to + the command history. + + * Makefile.dist (Makefile): Add /bin/false. + +Fri Aug 11 14:35:33 1989 Jim Kingdon (kingdon at spiff) + + * Makefile.dist: Comment out .c.o rule and add TARGET_ARCH. + + * m-altos.h: Include sys/page.h & sys/net.h + + * m-altos.h (FRAME_CHAIN{,_VALID}): Use outside_startup_file. + + * config.gdb (altos, altosgas): Add M_SYSV & M_BSD_NM and remove + M_ALLOCA=alloca.o from makedefine. + + * coffread.c (complete_symtab): Change a_entry to entry. + + * m-altosgas.h: New file. + + * m-symmetry (REGISTER_BYTE): Fix dumb mistake. + +Fri Aug 11 06:39:49 1989 Roland McGrath (roland at hobbes.ai.mit.edu) + + * utils.c (set_screensize_command): Check for ARG being nil, since + that's what execute_command will pass if there's no argument. + + * expread.y (yylex): Recognize "0x" or "0X" as the beginning of a + number. + +Thu Aug 10 15:43:12 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * config.gdb, Makefile.dist: Rename Makefile.c to Makefile.dist. + + * m-altos.h: Add comment about porting to USGR2. + + * config.gdb (sparc): Add -Usparc. + +Wed Aug 9 14:20:39 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * m-sun3os4.h: Define BROKEN_LARGE_ALLOCA. + + * values.c (modify_field): Check for value too large to fit in + bitfield. + + * utils.c (fputs_filtered): Allow LINEBUFFER to be NULL. + + * breakpoint.c (condition_command): Check for attempt to specify + non-numeric breakpoint number. + + * config.gdb, Makefile, m-altos.h, altos-dep.c: Merge Altos + port. + + * README: Change message about editing Makefile. + + * config.gdb: Edit Makefile. + Copied Makefile to Makefile.c and changed to let config.gdb + run us through the C preprocessor. + + * expread.y (yylex): Test correctly for definition of number. + +Wed Aug 9 11:56:05 1989 Randy Smith (randy at hobbes.ai.mit.edu) + + * dbxread.c (read_dbx_symtab): Put bracketing of entry point in + test case for .o symbols so that it will be correct even without + debugging symbols. + (end_psymtab): Took bracketing out. + + * blockframe.c (outside_startup_file): Reverse the sense of the + return value to make the functionality implied by the name + correct. + +Tue Aug 8 11:48:38 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * coffread.c (symbol_file_command): Do not assume presence of a.out + header. + + * blockframe.c: Replace first_object_file_end with + startup_file_{start,end} + (outside_startup_file): New function. + dbxread.c (read_addl_syms, read_dbx_symtab, end_psymbol): set + startup_file_*. Delete first_object_file_end code. + Add entry_point and ENTRY_POINT + coffread.c (complete_symtab): Set startup_file_*. + (first_object_file_end): Add as static. + m-*.h (FRAME_CHAIN, FRAME_CHAIN_VALID): Call outside_startup_file + instead of comparing with first_object_file_end. + + * breakpoint.c (breakpoint_1): Change -1 to (CORE_ADDR)-1. + + * config.gdb (i386, i386gas): Add missing quotes at end of "echo" + + * source.c (directory_command): Add dont_repeat (); + +Mon Aug 7 18:03:51 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * dbxread.c (read_addl_syms): Change strcmp to strncmp and put 3rd + arg back. + + * command.h (struct cmd_list_element): Add comment clarifying + purpose of abbrev_flag. + +Mon Aug 7 12:51:03 1989 Randy Smith (randy at hobbes.ai.mit.edu) + + * printcmd.c (_initialize_printcmd): Changed "undisplay" not to + have abbrev flag set; it isn't an abbreviation of "delete + display", it's an alias. + +Mon Aug 7 00:25:15 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * symtab.c (lookup_symtab_1): Remove filematch (never used). + + * expread.y [type]: Add second argument to 2 calls to + lookup_member_type which were missing them. + + * dbxread.c (symbol_file_command): Add from_tty arg. + Check it before calling query. + + * infcmd.c (tty_command): Add from_tty arg. + + * eval.c (evaluate_subexp): Remove 3rd argument from + calls to value_x_unop. + + * dbxread.c (read_addl_syms): Remove 3rd argument from + call to strcmp. + + * gdb.texinfo (Command editing): @include inc-readline.texinfo + and inc-history.texinfo and reorganize GDB-specific stuff. + + * Makefile: Add line MAKE=make. + + * README (second paragraph): Fix trivial errors. + + * dbxread.c (read_struct_type): Make sure p is initialized. + + * main.c (symbol_completion_function): Complete correctly + on the empty string. + +Sun Aug 6 21:01:59 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * symmetry-dep.c: Remove "long" from definition of i386_follow_jump. + + * gdb.texinfo (Backtrace): Document "where" and "info stack". + + * dbxread.c (cleanup_undefined_types): Strip off "struct " + or "union " from type names before doing comparison + +Sat Aug 5 02:05:36 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * config.gdb (i386, i386gas): Improve makefile editing instructions. + + * Makefile: Fix typo in CLIBS for SYSV. + + * dbxread.c (read_dbx_symtab): Deal with N_GSYM typedefs. + + * dbxread.c (add_file_command): Do not free name. We didn't + allocate it; it just points into arg_string. + + * Makefile, m-*.h: Change LACK_VPRINTF to HAVE_VPRINTF. + +Fri Jul 28 00:07:48 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * valprint.c (val_print): Made sure that all returns returned a + value (usually 0, indicating no memory printed). + + * core.c (read_memory): Changed "return" to "return 0". + + * expread.y (parse_number): Handle scientific notation when the + string does not contain a '.'. + +Thu Jul 27 15:14:03 1989 Randy Smith (randy at hobbes.ai.mit.edu) + + * infrun.c (signals_info): Error if signal number passed is out of + bounds. + + * defs.h: Define alloca to be __builtin_alloca if compiling with + gcc and localized inclusion of alloca.h on the sparc with the + other alloca stuff. + * command.c: Doesn't need to include alloca.h on the sparc; defs.h + does it for you. + + * printcmd.c (print_frame_args): Changed test for call to + print_frame_nameless_args to check i to tell if any args had been + printed. + +Thu Jul 27 04:40:56 1989 Roland McGrath (roland at hobbes.ai.mit.edu) + + * blockframe.c (find_pc_partial_function): Always check that NAME + and/or ADDRESS are not nil before storing into them. + +Wed Jul 26 23:41:21 1989 Roland McGrath (roland at hobbes.ai.mit.edu) + + * m-newsos3.h: Define BROKEN_LARGE_ALLOCA. + * dbxread.c (symbol_file_command, psymtab_to_symtab): + Use xmalloc #ifdef BROKEN_LARGE_ALLOCA. + +Tue Jul 25 16:28:18 1989 Jay Fenlason (hack at apple-gunkies.ai.mit.edu) + + * m68k-opcode.h: moved some of the fmovem entries so they're + all consecutive. This way the assembler doesn't bomb. + +Mon Jul 24 22:45:54 1989 Randy Smith (randy at hobbes.ai.mit.edu) + + * symtab.c (lookup_symbol): Changed error to an informational (if + not very comforting) message about internal problems. This will + get a null symbol returned to decode_line_1, which should force + things to be looked up in the misc function vector. + +Wed Jul 19 13:47:34 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * symtab.c (lookup_symbol): Changed "fatal" to "error" in + external symbol not found in symtab in which it was supposed to be + found. This can be reached because of a bug in ar. + +Tue Jul 18 22:57:43 1989 Randy Smith (roland at hobbes.ai.mit.edu) + + * m-news.h [REGISTER_U_ADDR]: Decreased the assumed offset of fp0 + by 4 to bring it into (apparently) appropriate alignment with + reality. + +Tue Jul 18 18:14:42 1989 Randy Smith (randy at hobbes.ai.mit.edu) + + * Makefile: pinsn.o should depend on opcode.h + + * m68k-opcode.h: Moved fmovemx with register lists to before other + fmovemx. + +Tue Jul 18 11:21:42 1989 Jim Kingdon (kingdon at susie) + + * Makefile, m*.h: Only #define vprintf (to _doprnt or printf, + depends on the system) if the library lacks it (controlled by + LACK_VPRINTF_DEFINE in makefile). Unpleasant, but necessary to + make this work with the GNU C library. + +Mon Jul 17 15:17:48 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * breakpoint.c (breakpoint_1): Change addr-b->address to + b->address-addr. + +Sun Jul 16 16:23:39 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * eval.c (evaluate_subexp): Change error message printed when + right operand of '@' is not an integer to English. + + * infcmd.c (registers_info): Fix call to print_spaces_filtered + to specify right # of arguments. + + * gdb.texinfo (Command Editing): Document info editing command. + + * coffread.c (read_file_hdr): Add MC68MAGIC. + + * source.c (select_source_symtab): Change MAX to max. + +Fri Jul 14 21:19:11 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * infcmd.c (registers_info): Clean up display to look good with long + register names, to say "register" instead of "reg", and to put the + "relative to selected stack frame" bit at the top. + +Fri Jul 14 18:23:09 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * dbxread.c (record_misc_function): Put parens around | to force + correct evaluation. + +Wed Jul 12 12:25:53 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * m-newsos3, m-news, infrun.c, Makefile, config.gdb, news-dep.c: + Merge in Hikichi's changes for Sony/News-OS 3 support. + +Tue Jul 11 21:41:32 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * utils.c (fputs_filtered): Don't do any filtering if output is + not to stdout, or if stdout is not a tty. + (fprintf_filtered): Rely on fputs_filtered's check for whether to + do filtering. + +Tue Jul 11 00:33:58 1989 Randy Smith (randy at hobbes.ai.mit.edu) + + * GDB 3.2 Released. + + * valprint.h: Deleted. + + * utils.c (fputs_filtered): Don't do any filtering if filtering is + disabled (lines_per_page == 0). + +Mon Jul 10 22:27:53 1989 Randy Smith (roland at hobbes.ai.mit.edu) + + * expread.y [typebase]: Added "unsigned long int" and "unsigned + short int" to specs. + +Mon Jul 10 21:44:55 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * main.c (main): Make -cd use cd_command to avoid + current_directory with non-absolute pathname. + +Mon Jul 10 00:34:29 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * dbxread.c (symbol_file_command): Catch errors from stat (even + though they should never happen). + + * source.c (openp): If the path is null, use the current + directory. + + * dbxread.c (read_dbx_symtab): Put N_SETV symbols into the misc + function vector ... + (record_misc_function): ... as data symbols. + + * utils.c (fprintf_filtered): Return after printing if we aren't + going to do filtering. + + * Makefile: Added several things for make clean to take care of. + + * expread.y: Lowered "@" in precedence below +,-,*,/,%. + + * eval.c (evaluate_subexp): Return an error if the rhs of "@" + isn't integral. + + * Makefile: Added removal of core and gdb[0-9] files to clean + target. + + * Makefile: Made a new target "distclean", which cleans things up + correctly for making a distribution. + +Sun Jul 9 23:21:27 1989 Randy Smith (randy at hobbes.ai.mit.edu) + + * dbxread.c: Surrounded define of gnu symbols with an #ifndef + NO_GNU_STABS in case you don't want them on some machines. + * m-npl.h, m-pn.h: Defined NO_GNU_STABS. + +Sun Jul 9 19:25:22 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * utils.c (fputs_filtered): New function. + (fprintf_filtered): Use fputs_filtered. + utils.c (print_spaces_filtered), + command.c (help_cmd,help_cmd_list), + printcmd.c (print_frame_args), + stack.c (print_block_frame_locals, print_frame_arg_vars), + valprint.c (many functions): Use fputs_filtered instead of + fprintf_filtered to avoid arbitrary limit. + + * utils.c (fprintf_filtered): Fix incorrect comment. + +Sat Jul 8 18:12:01 1989 Randy Smith (randy at hobbes.ai.mit.edu) + + * valprint.c (val_print): Changed assignment of pretty to use + prettyprint as a conditional rather than rely on values of the + enum. + + * Projects: Cleaned up a little for release. + + * main.c (initialize_main): Initialize + rl_completion_entry_function instead of completion_entry_function. + + * Makefile: Modified to use the new readline library setup. + + * breakpoint.c (break_command_1, delete_breakpoint, + enable_breakpoint, disable_breakpoint): Put in new printouts for + xgdb usage triggered off of xgdb_verbose. + * main.c (main): Added check for flag to set xgdb_verbose. + * stack.c (frame_command): Set frame_changed when frame command + used. + +Fri Jul 7 16:20:58 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * Remove valprint.h and move contents to value.h (more logical). + +Fri Jul 7 02:28:06 1989 Randall Smith (randy at rice-chex) + + * m68k-pinsn.c (print_insn): Included a check for register list; + if there is one, make sure to start p after it. + + * breakpoint.c (break_command_1, delete_breakpoint, + enable_breakpoint, disable_breakpoint): #ifdef'd out changes + below; they produce unwanted output in gdb mode in gnu-emacs. + + * gdb.texinfo: Spelled. Also removed index references from + command editing section; the relevance/volume ratio was too low. + Removed all references to the function index. + + * ns32k-opcode.h, ns32k-pinsn.c: Backed out changes of June 24th; + haven't yet received legal papers. + + * .gdbinit: Included message telling the user what it is doing. + + * symmetry-dep.c: Added static decls for i386_get_frame_setup, + i386_follow_jump. + * values.c (unpack_double): Added a return (double)0 at the end to + silence a compiler warning. + + * printcmd.c (containing_function_bounds, asdump_command): Created + to dump the assembly code of a function (support for xgdb and a + useful hack). + (_initialize_printcmd): Added this to command list. + * gdb.texinfo [Memory]: Added documentation for the asdump + command. + * breakpoint.c (break_command_1, delete_breakpoint, + enable_breakpoint, disable_breakpoint): Added extra verbosity for + xgdb conditionalized on the new external frame_full_file_name. + * source.c (identify_source_line): Increase verbosity of fullname + prointout to include pc value. + * stack.c: Added a new variable; "frame_changed" to indicate when + a frame has been changed so that gdb can print out a frame change + message when the frame only changes implicitly. + (print_frame_info): Check the new variable in determining when to + print out a new message and set it to zero when done. + (up_command): Increment it. + (down_command): Decrement it. + + * m68k-pinsn.c (print_insn_arg [lL]): Modified cases for register + lists to reset the point to point to after the word from which the + list is grabbed *if* that would cause point to point farther than + it currently is. + +Thu Jul 6 14:28:11 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * valprint.c (val_print, value_print): Add parameter to control + prettyprinting. + valprint.h: New file containing constants used for passing + prettyprinting parameter to val{,ue}_print. + expprint.c, infcmd.c, printcmd.c, valprint.c, values.c: + Change all calls to val{,ue}_print to use new parameter. + +Mon Jul 3 22:38:11 1989 Randy Smith (randy at apple-gunkies.ai.mit.edu) + + * dbxread.c (,process_one_symbol): Moved extern declaration for + index out of function to beginning of file. + +Mon Jul 3 18:40:14 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu) + + * gdb.texinfo (Registers): Add "ps" to list of standard registers. + +Sun Jul 2 23:13:03 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * printcmd.c (enable_display): Change d->next to d = d->next so + that "enable display" without args works. + +Fri Jun 30 23:42:04 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * source.c (list_command): Made error message given when no + symtab is loaded clearer. + + * valops.c (value_assign): Make it so that when assigning to an + internal variable, the type of the assignment exp is the type of + the value being assigned. + +Fri Jun 30 12:12:43 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * main.c (verbose_info): Created. + (initialize_main): Put "info verbose" into command list. + + * utils.c (screensize_info): Created. + (_initialize_utils): Defined "info screensize" as a normal command. + + * valprint.c (format_info): Added information about maximum number + of array elements to function. + + * blockframe.c (find_pc_partial_function): Again. + + * blockframe.c (find_pc_partial_function): Replaced a "shouldn't + happen" (which does) with a zero return. + + * main.c (dont_repeat): Moved ahead of first use. + +Thu Jun 29 19:15:08 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * vax-opcode.h: Made minor modifications (moved an instruction and + removed a typo) to bring this into accord with gas' table; also + changed copyright to reflect it being part of both gdb and gas. + + * m68k-opcode.h: Added whole scads and bunches of new stuff for + the m68851 and changed the coptyrightto recognize that the file + was shared between gdb and gas. + + * main.c (stop_sig): Use "dont_repeat ()" instead of *line = 0; + + * core.c (read_memory): Don't do anything if length is 0. + + * Makefile: Added readline.c to the list of files screwed by + having the ansi ioctl.h compilation with gcc. + + * config.gdb: Added sun4os3 & sun4-os3 as availible options. + +Wed Jun 28 02:01:26 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu) + + * command.c (lookup_cmd): Add ignore_help_classes argument. + (lookup_cmd_1): Add ignore_help_classes argument. + command.c, main.c: Change callers of lookup_cmd{,_1} to supply + value for ignore_help_classes. + +Tue Jun 27 18:01:31 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * utils.c (print_spaces_filtered): Made more efficient. + * defs.h: Declaration. + * valprint.c (val_print): Used in a couple of new places. + +Mon Jun 26 18:27:28 1989 Randall Smith (randy at gluteus.ai.mit.edu) + + * m68k-pinsn.c (print_insn_arg ['#', '^']): Combined them into one + case which always gets the argument from the word immediately + following the instruction. + (print_insn_arg ["[lL]w"]): Make sure to always get the register + mask from the word immediately following the instruction. + +Sun Jun 25 19:14:56 1989 Randall Smith (randy at galapas.ai.mit.edu) + + * Makefile: Added hp-include back in as something to distribute. + + * stack.c (print_block_frame_locals): Return value changed from + void to int; return 1 if values printed. Use _filtered. + (print_frame_local_vars): Use return value from + print_block_frame_locals to mention if nothing printed; mention + lack of symbol table, use _filtered. + (print_frame_arg_vars): Tell the user if no symbol table + or no values printed. Use fprintf_filtered instead of fprintf. + * blockframe.c (get_prev_frame_info): Check for no inferior or + core file before crashing. + + * inflow.c (inferior_died): Set current frame to zero to keep from + looking like we're in start. + +Sat Jun 24 15:50:53 1989 Randall Smith (randy at gluteus.ai.mit.edu) + + * stack.c (frame_command): Added a check to make sure that there + was an inferior or a core file. + + * expread.y (yylex): Allow floating point numbers of the form ".5" + to be parsed. + + Changes by David Taylor at TMC: + * ns32k-pinsn.c: Added define for ?floating point coprocessor? and + tables for register names to be used for each of the possibilities. + (list_search): Created; searches a list of options for a specific + value. + (print_insn_arg): Added 'Q', 'b', 'M', 'P', 'g', and 'G' options + to the value location switch. + * ns32k-opcode.h: Added several new location flags. + [addr, enter, exit, ext[bwd], exts[bwd], lmr, lpr[bwd], restore, + rett, spr[bwd], smr]: Improved insn format output. + + * symtab.c (list_symbols): Rearrange printing to produce readable + output for "info types". + + * eval.c (evaluate_subexp_for_address): Fixed typo. + + * dbxread.c (read_type): Don't output an error message when + there isn't a ',' after a cross-reference. + + * dbxread.c (read_dbx_symtab): #if'd out N_FN case in + read_dbx_symtab if it has the EXT bit set (otherwise multiple + cases with the same value). + +Fri Jun 23 13:12:08 1989 Randall Smith (randy at plantaris.ai.mit.edu) + + * symmisc.c: Changed decl of print_spaces from static to extern + (since it's defined in utils.c). + + * remote.c (remote_open): Close remote_desc if it's already been + opened. + + * Remote_Makefile, remote_gutils.c, remote_inflow.c, + remote_server.c, remote_utils.c: Combined into remote-multi.shar. + * remote-multi.shar: Created (Vikram Koka's remote stub). + * remote-sa.m68k.shar: Created (Glenn Engel's remcom.c). + * README: Updated to reflect new organization of remote stubs. + + * dbxread.c (read_dbx_symtab): Put an N_FN in with N_FN | N_EXT to + account for those machines which don't use the external bit here. + Sigh. + + * m-symmetry.h: Defined NO_SIGINTERRUPT. + +Thu Jun 22 12:51:37 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * printcmd.c (decode_format): Make sure characters are printed + using a byte size. + + * utils.c (error): Added a terminal_ours here. + + * stack.c (locals_info): Added check for selected frame. + + * dbxread.c (read_type): Checked to make sure that a "," was + actually found in the symbol to end a cross reference. + +Wed Jun 21 10:30:01 1989 Randy Smith (randy at tartarus.uchicago.edu) + + * expread.y (parse_number, [exp]): Allowed for the return of a + number marked as unsigned; this will allow inclusion of unsigned + constants. + + * symtab.h: Put in default definitions for BUILTIN_TYPE_LONGEST + and BUILTIN_TYPE_UNSIGNED_LONGEST. + + * expread.y (parse_number): Will now accept integers suffixed with + a 'u' (though does nothing special with it). + + * valarith.c (value_binop): Added cases to deal with unsigned + arithmetic correctly. + +Tue Jun 20 14:25:54 1989 Randy Smith (randy at tartarus.uchicago.edu) + + * dbxread.c (psymtab_to_symtab_1): Changed reading in info message + to go through printf_filtered. + + * symtab.c (list_symbols): Placed header message after all calls + to psymtab_to_symtab. + + * symtab.c (smash_to_{function, reference, pointer}_type): Carried + attribute of permanence for the type being smashed over the bzero + and allowed any type to point at this one if it is permanent. + + * symtab.c (smash_to_{function, reference, pointer}_type): Fix + typo: check flags of to_type instead of type. + + * m-hp9k320.h: Changed check on __GNU__ predefine to __GNUC__. + + * Makefile: Made MUNCH_DEFINE seperate and based on SYSV_DEFINE; + they aren't the same on hp's. + +Mon Jun 19 17:10:16 1989 Randy Smith (randy at tartarus.uchicago.edu) + + * Makefile: Fixed typo. + + * valops.c (call_function): Error if the inferior has not been + started. + + * ns32k-opcode.h [check[wc], cmpm[bwd], movm[bwd], skpsb]: Fixed + typos. + +Fri Jun 9 16:23:04 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * m-news.h [NO_SIGINTERRUPT]: Defined. + + * dbxread.c (read_type): Start copy of undefined structure name + past [sue] defining type of cross ref. + + * dbxread.c (process_one_symbol): Changed strchr to index. + + * ns32k-opcode.h, ns32k-pinsn.c: More changes to number of + operands, addition of all of the set condition opcodes, addition + of several flag letters, all patterned after the gas code. + + * ns32k-opcode.h [mov{su,us}[bwd], or[bwd]]: Changed number of + operands from 1 to 2. + +Wed Jun 7 15:04:24 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * symseg.h [TYPE_FLAG_STUB]: Created. + * dbxread.c (read_type): Set flag bit if type is stub. + (cleanup_undefined_types): Don't mark it as a stub if it's been + defined since we first learned about it. + * valprint.c (val_print): Print out a message to that effect if + this type is encountered. + + * symseg.h, symtab.h: Moved the definition of TYPE_FLAG_PERM over + to symseg.h so that all such definitions would be in the same place. + + * valprint.c (val_print): Print out for a + structure if there aren't any. + + * dbxread.c (read_type): Set type name of a cross reference type + to "struct whatever" or something. + +Tue Jun 6 19:40:52 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * breakpoint.c (breakpoint_1): Print out symbolic location of + breakpoints for which there are no debugging symbols. + +Mon Jun 5 15:14:51 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * command.c (help_cmd_list): Made line_size static. + +Sat Jun 3 17:33:45 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * Makefile: Don't include the binutils hp-include directory in the + distribution anymore; refer the users to the binutils distribution. + +Thu Jun 1 16:33:07 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * printcmd.c (disable_display_command): Fixed loop iteration for + no arg case. + + * printcmd.c (disable_display_command): Added from_tty parameter + to function. + + * valops.c (value_of_variable): Call read_var_value with 0 cast to + FRAME instead of CORE_ADDR. + + * eval.c (evaluate_subexp): Corrected number of args passed to + value_subscript (to 2). + + * infrun.c (wait_for_inferior), symtab.c (decode_line_1), + m-convex.h: Changed name of FIRSTLINE_DEBUG_BROKEN to + PROLOGUE_FIRSTLINE_OVERLAP. + + * m-merlin.h: Fixed typo. + * ns32k-opcode.h: Added ns32381 opcodes and "cinv" insn, and fixed + errors in movm[wd], rett, and sfsr. + + * eval.c (evaluate_subexp, evaluate_subexp_for_address), valops.c + (value_zero): Change value_zero over to taking two arguments + instead of three. + + * eval.c (evaluate_subexp) + [OP_VAR_VALUE]: Get correct lval type for AVOID_SIDE_EFFECTS for + all types of symbols. + [BINOP_DIV]: Don't divide if avoiding side effects; just return + an object of the correct type. + [BINOP_REPEAT]: Don't call value_repeat, just allocate a + repeated value. + (evaluete_subexp_for_address) [OP_VAR_VALUE]: Just return a thing + of the right type (after checking to make sure that we are allowed + to take the address of whatever variable has been passed). + +Mon May 29 11:01:02 1989 Randall Smith (randy at galapas.ai.mit.edu) + + * breakpoint.c (until_break_command): Set the breakpoint with a + frame specification so that it won't trip in inferior calls to the + function. Also set things up so that it works based on selected + frame, not current one. + +Sun May 28 15:05:33 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * eval.c (evalue_subexp): Change subscript case to use value_zero + in EVAL_AVOID_SIDE_EFFECTS case. + +Fri May 26 12:03:56 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * dbxread.c (read_addl_syms, psymtab_to_symtab): Removed + cleanup_undefined_types; this needs to be done on a symtab basis. + (end_symtab): Called cleanup_undefined_types from here. + (cleanup_undefined_types): No longer uses lookup_symbol (brain + dead idea; oh, well), now it searches through file_symbols. + +Wed May 24 15:52:43 1989 Randall Smith (randy at galapas) + + * source.c (select_source_symtab): Only run through + partial_symtab_list if it exists. + + * coffread.c (read_coff_symtab): Don't unrecord a misc function + when a function symbol is seen for it. + + * expread.y [variable]: Make sure to write a type for memvals if + you don't get a mft you recognize. + +Tue May 23 12:15:57 1989 Randall Smith (randy at plantaris.ai.mit.edu) + + * dbxread.c (read_ofile_symtab, psymtab_to_symtab): Moved cleanup + of undefined types to psymtab_to_symtab. That way it will be + called once for all readins (which will, among other things, + help reduce infinite loops). + + * symtab.h [misc_function_type]: Forced mf_unknown to 0. + * dbxread.c (record_misc_function): Cast enum to unsigned char (to + fit). + * expread.y [variable]: Cast unsigned char back to enum to test. + +Mon May 22 13:08:25 1989 Randall Smith (randy at gluteus.ai.mit.edu) + + Patches by John Gilmore for dealing well with floating point: + * findvar.c (value_from_register, locate_var_value): Used + BYTES_BIG_ENDIAN instead of an inline test. + * m-sparc.h [IEEE_FLOAT]: Created to indicate that the sparc is + IEEE compatible. + * printcmd.c (print_scalar_formatted): Use BYTES_BIG_ENDIAN and + the stream argument for printing; also modify default type for + 'f'. Change handling of invalid floats; changed call syntax for + is_nan. + (print_command): Don't print out anything indicating that + something was recorded on the history list if it wasn't. + * valprint.c (val_print): Fixed to deal properley with new format + of is_nan and unpacking doubles without errors occuring. + (is_nan): Changed argument list and how it figures big endianness + (uses macros). + * values.c (record_latest_value): Return -1 and don't record if + it's an invalid float. + (value_as_double): Changed to use new unpack_double calling + convention. + (unpack_double): Changed not to call error if the float was + invalid; simply to set invp and return. Changed calling syntax. + (unpack_field_as_long, modify_field): Changed to use + BITS_BIG_ENDIAN to determine correct action. + + * m-hp9k320.h [HP_OS_BUG]: Created; deals with problem where a + trap happens after a continue. + * infrun.c (wait_for_inferior): Used. + + * m-convex.h [FIRSTLINE_DEBUG_BROKEN]: Defined a flag to indicate + that the debugging symbols output by the compiler for the first + line of a function were broken. + * infrun.c (wait_for_inferior), symtab.c (decode_line_1): Used. + + * gdb.texinfo [Data, Memory]: Minor cleanups of phrasing. + +Fri May 19 00:16:59 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * dbxread.c (add_undefined_type, cleanup_undefined_types): Created + to keep a list of cross references to as yet undefined types. + (read_type): Call add_undefined_type when we run into such a case. + (read_addl_syms, read_ofile_symtab): Call cleanup_undefined_types + when we're done. + + * dbxread.c (psymtab_to_symtab, psymtab_to_symtab_1): Broke + psymtab_to_symtab out into two routines; made sure the string + table was only readin once and the globals were only scanned once, + for any number of dependencies. + +Thu May 18 19:59:18 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * m-*.h: Defined (or not, as appropriate per machine) + BITS_BIG_ENDIAN, BYTES_BIG_ENDIAN, and WORDS_BIG_ENDIAN. + +Wed May 17 13:37:45 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * main.c (symbol_completion_function): Always complete on result + command list, even if exact match found. If it's really an exact + match, it'll find it again; if there's something longer than it, + it'll get the right result. + + * symtab.c (make_symbol_completion_function): Fixed typo; strcmp + ==> strncmp. + + * dbxread.c (read_dbx_symtab): Change 'G' case to mark symbols as + LOC_EXTERNAL. + + * expread.y [variables]: Changed default type of text symbols to + function returning int so that one can use, eg. strcmp. + + * infrun.c (wait_for_inferior): Include a special flag indicating + that one shouldn't insert the breakpoints on the next step for + returning from a sigtramp and forcing at least one move forward. + + * infrun.c (wait_for_inferior): Change test for nexting into a + function to check for current stack pointer inner than previous + stack pointer. + + * infrun.c (wait_for_inferior): Check for step resume break + address before dealing with normal breakpoints. + + * infrun.c (wait_for_inferior): Added a case to deal with taking + and passing along a signal when single stepping past breakpoints + before inserting breakpoints. + + * infrun.c (wait_for_inferior): Inserted special case to keep + going after taking a signal we are supposed to be taking. + +Tue May 16 12:49:55 1989 Randall Smith (randy at gluteus.ai.mit.edu) + + * inflow.c (terminal_ours_1): Cast result of signal to (int + (*)()). + + * gdb.texinfo: Made sure that references to the program were in + upper case. Modify description of the "set prompt" command. + [Running]: Cleaned up introduction. + [Attach]: Cleaned up. + [Stepping]: Change "Proceed" to "Continue running" or "Execute". + Minor cleanup. + [Source Path]: Cleaned up intro. Cleared up distinction between + the executable search path and the source path. Restated effect + of the "directory" command with no arguments. + [Data]: Fixed typos and trivial details. + [Stepping]: Fixed up explanation of "until". + + * source.c (print_source_lines): Print through filter. + + * printcmd.c (x_command): If the format with which to print is + "i", use the address of anything that isn't a pointer instead of + the value. This is for, eg. "x/10i main". + + * gdb.texinfo: Updated last modification date on manual. + +Mon May 15 12:11:33 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * symtab.c (lookup_symtab): Fixed typo (name ==> copy) in call to + lookup_symtab_1. + + * gdb.texinfo: Added documentation for "break [+-]n" and for new + actions of "directory" command (taking multiple directory names at + the same time). + + * m68k-opcode.h: Replaced the version in gdb with an up-to-date + version from the assembler directory. + * m68k-pinsn.c (print_insn_arg): Added cases 'l' & 'L' to switch + to print register lists for movem instructions. + + * dbxread.c, m-convex.h: Moved convex dependent include files over + from dbxread.c to m-convex.h. + + * printcmd.c (disable_display, disable_display_command): Changed + name of first to second, and created first which takes an int as + arg rather than a char pointer. Changed second to use first. + (_initialize_printcmd): Changed to use second as command to call. + (delete_current_display, disable_current_display): Changed name of + first to second, and changed functionality to match. + * infrun.c (normal_stop), main.c (return_to_top_level): Changed to + call disable_current_display. + + * dbxread.c (process_one_symbol, read_dbx_symtab): Changed N_FN to + be N_FN | N_EXT to deal with new Berkeley define; this works with + either the old or the new. + + * Remote_Makefile, remote_gutils.c, remote_inflow.c, + remote_server.c, remote_utils.c: Created. + * Makefile: Included in tag and tar files. + * README: Included a note about them. + + * printcmd.c (print_address): Use find_pc_partial_function to + remove need to readin symtabs for symbolic addresses. + + * source.c (directory_command): Replaced function with new one + that can accept lists of directories seperated by spaces or :'s. + + * inflow.c (new_tty): Replaced calls to dup2 with calls to dup. + +Sun May 14 12:33:16 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * stack.c (args_info): Make sure that you have an inferior or core + file before taking action. + + * ns32k-opcode.h [deiw, deid]: Fixed machine code values for these + opcodes. + + * dbxread.c (scan_file_globals): Modified to use misc function + vector instead of file itself. Killed all arguments to the + funciton; no longer needed. + (psymtab_to_symtab): Changed call for above to reflect new (void) + argument list. + + * dbxread.c (read_dbx_symtab, ): Moved HASH_OFFSET define out of + read_dbx_symtab. + + * expread.y [variable]: Changed default type of misc function in + text space to be (void ()). + + * Makefile: Modified for proper number of s/r conflicts (order is + confusing; the mod that necessitated this change was on May 12th, + not today). + + * expread.y (yylex): Added SIGNED, LONG, SHORT, and INT keywords. + [typename]: Created. + [typebase]: Added rules for LONG, LONG INT, SHORT, SHORT INT, + SIGNED name, and UNSIGNED name (a good approximation of ansi + standard). + + * Makefile: Included .c.o rule to avoid sun's make from throwing + any curves at us. + + * blockframe.c: Included + + * command.c (lookup_cmd): Clear out trailing whitespace. + + * command.c (lookup_cmd_1): Changed malloc to alloca. + +Fri May 12 12:13:12 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * printcmd.c (print_frame_args): Only print nameless args when you + know how many args there are supposed to be and when you've + printed fewer than them. Don't print nameless args between + printed args. + + * symtab.c (make_symbol_completion_function): Fixed typo (= ==> + ==). + + * remote.c (remote_open): ifdef'd out siginterrupt call by #ifndef + NO_SIGINTERRUPT. + * m-umax.h: Defined NO_SIGINTERRUPT. + + * expread.y [ptype, array_mod, func_mod, direct_abs_decl, + abs_decl]: Added rules for parsing and creating arbitrarily + strange types for casts and sizeofs. + + * symtab.c, symtab.h (create_array_type): Created. Some minor + misfeatures; see comments for details (main one being that you + might end up creating two arrays when you only needed one). + +Thu May 11 13:11:49 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * valops.c (value_zero): Add an argument for type of lval. + * eval.c (evaluate_subexp_for_address): Take address properly in + the avoid side affects case (ie. keep track of whether we have an + lval in memory and we can take the address). + (evaluate_subexp): Set the lval type of expressions created with + value_zero properley. + + * valops.c, value.h (value_zero): Created--will return a value of + any type with contents filled with zero. + * symtab.c, symtab.h (lookup_struct_elt_type): Created. + * eval.c (evaluate_subexp): Modified to not read memory when + called with EVAL_AVOID_SIDE_EFFECTS. + + * Makefile: Moved dbxread.c ahead of coffread.c in the list of + source files. + +Wed May 10 11:29:19 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * munch: Make sure that sysv version substitutes for the whole + line. + + * symtab.h: Created an enum misc_function_type to hold the type of + the misc function being recorded. + * dbxread.c (record_misc_function): Branched on dbx symbols to + decide which type to assign to a misc function. + * coffread.c (record_misc_function): Always assign type unknown. + * expread.y [variable]: Now tests based on new values. + +Tue May 9 13:03:54 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * symtab.c: Changed inclusion of (doesn't work on + SYSV) to declaration of index. + + * Makefile: Changed last couple of READLINE_FLAGS SYSV_DEFINE + + * source.c ({forward, reverse}_search_command): Made a default + search file similar to for the list command. + +Mon May 8 18:07:51 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * printcmd.c (print_frame_args): If we don't know how many + arguments there are to this function, don't print the nameless + arguments. We don't know enough to find them. + + * printcmd.c (print_frame_args): Call print_frame_nameless_args + with proper arguments (start & end as offsets from addr). + + * dbxread.c (read_addl_syms): Removed cases to deal with global + symbols; this should all be done in scan_global_symbols. + +Sun May 7 11:36:23 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * Makefile: Added copying.awk to ${OTHERS}. + +Fri May 5 16:49:01 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * valprint.c (type_print_varspec_prefix): Don't pass + passed_a_pointer onto children. + + * valprint.c (type_print_varspec_suffix): Print "array of" with + whatever the "of" is after tha array brackets. + + * valprint.c (type_print_varspec_{prefix,suffix}): Arrange to + parenthesisze pointers to arrays as well as pointers to other + objects. + + * valprint.c (type_print_varspec_suffix): Make sure to print + subscripts of multi-dimensional arrays in the right order. + + * infcmd.c (run_command): Fixed improper usages of variables + within remote debugging branch. + + * Makefile: Added Convex.notes to the list of extra files to carry + around. + + * dbxread.c (symbol_file_command): Made use of alloca or malloc + dependent on macro define. + +Thu May 4 15:47:04 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * Makefile: Changed READLINE_FLAGS to SYSV_DEFINE and called munch + with it also. + * munch: Check first argument for -DSYSV and be looser about + picking up init routines if you find it. + + * coffread.c: Made fclose be of type int. + + * breakpoint.c (_initialize_breakpoint): Put "unset" into class + alias. + +Wed May 3 14:09:12 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * m-sparc.h [STACK_END_ADDR]: Parameterized off of + machine/vmparam.h (as per John Gilmore's suggestion). + + * blockframe.c (get_prev_frame_info): Changed this function back + to checking frameless invocation first before checking frame + chain. This means that a backtrace up from start will produce the + wrong value, but that a backtrace from a frameless function called + in main will show up correctly. + + * breakpoint.c (_initialize_breakpoint): Added entry in help for + delete that indicates that unset is an alias for it. + + * main.c (symbol_completion_function): Modified recognition of + being within a single command. + +Tue May 2 15:13:45 1989 Randy Smith (randy at gnu) + + * expread.y [variable]: Add some parens to get checking of the + misc function vector right. + +Mon May 1 13:07:03 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * default-dep.c (core_file_command): Made reg_offset unsigned. + + * default-dep.c (core_file_command): Improved error messages for + reading in registers. + + * expread.y: Allowed a BLOCKNAME to be ok for a variable name (as + per C syntax). + + * dbxread.c (psymtab_to_symtab): Flushed stdout after printing + starting message about reading in symbols. + + * printcmd.c (print_frame_args): Switched starting place for + printing of frameless args to be sizeof int above last real arg + printed. + + * printcmd.c (print_frame_args): Modified final call to + print_nameless_args to not use frame slots used array if none had + been used. + + * infrun.c (wait_for_inferior): Take FUNCTION_START_OFFSET into + account when dealing with comparison of pc values to function + addresses. + + * Makefile: Added note about compiling gdb on a Vax running 4.3. + +Sun Apr 30 12:59:46 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * command.c (lookup_cmd): Got correct error message on bad + command. + + * m-sun3.h [ABOUT_TO_RETURN]: Modified to allow any of the return + instructions, including trapv and return from interupt. + + * command.c (lookup_cmd): If a command is found, use it's values + for error reporting and determination of needed subcommands. + + * command.c (lookup_cmd): Use null string for error if cmdtype is + null; pass *line to error instead of **. + + * command.c (lookup_cmd_1): End of command marked by anything but + alpha numeric or '-'. Included ctype.h. + +Fri Apr 28 18:30:49 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * source.c (select_source_symtab): Kept line number from ever + being less than 1 in main decode. + +Wed Apr 26 13:03:20 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * default-dep.c (core_file_command): Fixed typo. + + * utils.c (fprintf_filtered): Don't use return value from + numchars. + + * main.c, command.c (complete_on_cmdlist): Moved function to + command.c. + + * command.c (lookup_cmd): Modified to use my new routine. Old + version is still there, ifdef'd out. + + * command.c, command.h (lookup_cmd_1): Added a routine to do all + of the work of lookup_cmd with no error reporting and full return + of information garnered in search. + +Tue Apr 25 12:37:54 1989 Randall Smith (randy at gluteus.ai.mit.edu) + + * breakpoint.c (_initialize_breakpoint): Change "delete + breakpionts" to be in class alias and not have the abbrev flag + set. + + * main.c (symbol_completion_function): Fix to correctly complete + things that correspond to multiword aliases. + + * main.c (complete_on_cmdlist): Don't complete on something if it + isn't a command or prefix (ie. if it's just a help topic). + + * main.c (symbol_completion_function): Set list index to be 0 if + creating a list with just one element. + + * main.c (complete_on_cmdlist): Don't allow things with + abbrev_flag set to be completion values. + (symbol_completion_function): Don't accept an exact match if the + abbrev flag is set. + + * dbxread.c (read_type): Fixed typo in comparision to check if + type number existed. + + * dbxread.c (read_type): Made sure to only call dbx_lookup_type on + typenums if typenums were not -1. + +Mon Apr 24 17:52:12 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * symtab.c: Added strings.h as an include file. + +Fri Apr 21 15:28:38 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * symtab.c (lookup_partial_symtab): Changed to only return a match + if the name match is exact (which is what I want in all cases in + which this is currently used. + +Thu Apr 20 11:12:34 1989 Randall Smith (randy at gluteus.ai.mit.edu) + + * m-isi.h [REGISTER_U_ADDR]: Installed new version from net. + * default-dep.c: Deleted inclusion of fcntl.h; apparently not + necessary. + * Makefile: Added comment about compiling on isi under 4.3. + + * breakpoint.c (break_command_1): Only give decode_line_1 the + default_breakpoint_defaults if there's nothing better (ie. make + the default be off of the current_source notes if at all + possible). + + * blockframe.c (get_prev_frame_info): Clean up comments and + delete code ifdefed out around FRAMELESS_FUNCTION_INVOCATION test. + + * remote.c: Added a "?" message to protocol. + (remote_open): Used at startup. + (putpkt): Read whatever garbage comes over the line until we see a + '+' (ie. don't treat garbage as a timeout). + + * valops.c (call_function): Eliminated no longer appropriate + comment. + + * infrun.c (wait_for_inferior): Changed several convex conditional + compilations to be conditional on CANNOT_EXECUTE_STACK. + +Wed Apr 19 10:18:17 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * printcmd.c (print_frame_args): Added code to attempt to deal + with arguments that are bigger than an int. + + Continuation of Convex/Fortran changes: + * printcmd.c (print_scalar_formatted): Added leading zeros to + printing of large integers. + (address_info, print_frame_args): Added code to deal with + LOC_REF_ARG. + (print_nameless_args): Allow param file to specify a routine with + which to print typeless integers. + (printf_command): Deal with long long values well. + * stack.c (print_frame_arg_vars): Change to deal with LOC_REF_ARG. + * symmisc.c (print_symbol): Change to deal with LOC_REF_ARG. + * symseg.h: Added LOC_REF_ARG to enum address_class. + * symtab.c (lookup_block_symbol): Changed to deal with + LOC_REF_ARG. + * valarith.c (value_subscripted_rvalue): Created. + (value_subscript): Used above when app. + (value_less, value_equal): Change to cast to (char *) before doing + comparison, for machines where that casting does something. + * valops.c (call_function): Setup to deal with machines where you + cannot execute code on the stack segment. + * valprint.c (val_print): Make sure that array element size isn't + zero before printing. Set address of default array to address of + first element. Put in a couple of int cast. Removed some convex + specific code. Added check for endianness of machine in case of a + packed structure. Added code for printing typeless integers and + for LONG LONG's. + (set_maximum_command): Change to use parse_and_eval_address to get + argument (so can use expressions there). + * values.c (value_of_internalvar, set_internalvar_component, + set_internalvar, convenience_info): Add in hooks for trapped + internal vars. + (unpack_long): Deal with LONG_LONG. + (value_field): Remove LONGEST cast. + (using_struct_return): Fixed typo ENUM ==> UNION. + * xgdb.c (_initialize_xgdb): Make sure that specify_exec_file_hook + is not called unless we are setting up a windowing environ. + +Tue Apr 18 13:43:37 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + Various changes involved in 1) getting gdb to work on the convex, + and 2) Getting gdb to work with fortran (due to convex!csmith): + * convex-dep.c, convex-opcode.h, m-convex.h, convex-pinsn.c: + Created (or replaced with new files). + * Makefile: Add convex dependent files. Changed default flags to + gnu malloc to be CFLAGS. + * config.gdb: Added convex to list of machines. + * core.c (files_info): Added a FILES_INFO_HOOK to be used if + defined. + (xfer_core_file): Conditionalized compilation of xfer_core_file on + the macro XFER_CORE_FILE. + * coffread.c (record_misc_function): Made sure it zerod type field + (which is now being used; see next). + * dbxread.c: Included some convex dependent include files. + (copy_pending, fix_common_blocks): Created. + [STAB_REG_REGNUM, BELIEVE_PCC_PROMOTION]: Created default values; + may be overridden in m-*.h. + Included data structures for keeping track of common blocks. + (dbx_alloc_type): Modified; if called with negative 1's will + create a type without putting it into the type vector. + (read_dbx_symtab, read_addl_syms): Modified calls to + record_misc_function to include the new information. + (symbol_file_command, psymtab_to_symtab, add_file_command): + Modified reading in of string table to adapt to machines which + *don't* store the size of the string table in the first four bytes + of the string table. + (read_dbx_symtab, scan_file_globals, read_ofile_symtab, + read_addl_syms): Modified assignment of namestring to accept null + index into symtab as ok. + (read_addl_syms): Modified readin of a new object file to fiddle + with common blocks correctly. + (process_one_symbol): Fixed incorrect comment about convex. Get + symbols local to a lexical context from correct spot on a per + machine basis. Catch a bug in pcc which occaisionally puts an SO + where there should be an SOL. Seperate sections for N_BCOMM & + N_ECOMM. + (define_symbol): Ignore symbols with no ":". Use + STAB_REG_TO_REGNUM. Added support for function args calling by + reference. + (read_type): Only read type number if one is there. Remove old + (#if 0'd out) array code. + (read_array_type): Added code for dealing with adjustable (by + parameter) arrays half-heartedly. + (read_enum_type): Allow a ',' to end a list of values. + (read_range_type): Added code to check for long long. + * expread.y: Modified to use LONGEST instead of long where + necessary. Modified to use a default type of int for objects that + weren't in text space. + * findvar.c (locate_var_value, read_var_value): Modified to deal + with args passed by reference. + * inflow.c (create_inferior): Used CREATE_INFERIOR_HOOK if it + exists. + * infrun.c (attach_program): Run terminal inferior when attaching. + (wait_for_inferior): Removed several convex dependencies. + * main.c (float_handler): Created. + Made whatever signal indicates a stop configurable (via macro + STOP_SIGNAL). + (main): Setup use of above as a signal handler. Added check for + "-nw" in args already processed. + (command_line_input): SIGTSTP ==>STOP_SIGNAL. + + * expread.y: Added token BLOCKNAME to remove reduce/reduce + conflict. + * Makefile: Change message to reflect new grammar. + +Mon Apr 17 13:24:59 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * printcmd.c (compare_ints): Created. + (print_frame_args): Modified to always print arguments in the + order in which they were found in the symbol table. Figure out + what apots are missing on the fly. + + * stack.c (up_command): Error if no inferior or core file. + + * m-i386.h, m-symmetry.h [FRAMELESS_FUNCTION_INVOCATION]: Created; + same as m68k. + + * dbxread.c (define_symbol): Changed "desc==0" test to + "processing_gcc_compilation", which is the correct way to do it. + +Sat Apr 15 17:18:38 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * expread.y: Added precedence rules for arglists, ?:, and sizeof + to eliminate some shift-reduce conflicts. + * Makefile: Modified "Expect" message to conform to new results. + +Thu Apr 13 12:29:26 1989 Randall Smith (randy at plantaris.ai.mit.edu) + + * inflow.c (terminal_init_inferior): Fixed typo in recent diff + installation; TIOGETC ==> TIOCGETC. + + * m-vax.h, m-sun2.h, m-sun3.h, m-sparc.h, m-hp*.h, m-isi.h, + m-news.h [FRAMELESS_FUNCTION_INVOCATION]: Created macro with + appropriate definition. + +Wed Apr 12 15:30:29 1989 Randall Smith (randy at plantaris.ai.mit.edu) + + * blockframe.c (get_prev_frame_info): Added in a macro to specify + when a "frame" is called without a frame pointer being setup. + + * Makefile [clean]: Made sure to delete gnu malloc if it was being + used. + +Mon Apr 10 12:43:49 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * dbxread.c (process_one_symbol): Reset within_function to 0 after + last RBRAC of a function. + + * dbxread.c (read_struct_type): Changed check for filling in of + TYPE_MAIN_VARIANT of type. + + * inflow.c (create_inferior): Conditionalized fork so that it + would be used if USG was defined and HAVE_VFORK was not defined. + + * defs.h: Added comment about enum command_class element + class_alias. + + * dbxread.c (process_one_symbol): Fixed a typo with interesting + implications for associative processing in the brain (':' ==> 'c'). + + * sparc-dep.c (isabranch): Changed name to isannulled, modified to + deal with coprocessor branches, and improved comment. + (single_step): Changed to trap at npc + 4 instead of pc +8 on + annulled branches. Changed name in call to isabranch as above. + + * m-sun4os4.h (STACK_END_ADDRESS): Changed it to 0xf8000000 under + os 4.0. + +Sat Apr 8 17:04:07 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * dbxread.c (process_one_symbol): In the case N_FUN or N_FNAME the + value being refered to is sometimes just a text segment variable. + Catch this case. + + * infrun.c (wait_for_inferior), breakpoint.c + (breakpoint_stop_status): Move the selection of the frame to + inside breakpoint_stop_status so that the frame only gets selected + (and the symbols potentially read in) if the symbols are needed. + + * symtab.c (find_pc_psymbol): Fixed minor misthough (pc >= + fucntion start, not >). + + * breakpoint.c (_initialize_breakpoint): Change "delete" internal + help entry to simply refer to it being a prefix command (since the + list of subcommands is right there on a "help delete"). + +Fri Apr 7 15:22:18 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * blockframe.c (find_pc_partial_function): Created; figures out + what function pc is in (name and address) without reading in any + new symbols. + * symtab.h: Added decl for above. + * infrun.c (wait_for_inferior): Used instead of + find_pc_function_start. + * stack.c (print_frame_info): Used instead of hand coding for same + thing. + + * dbxread.c (psymtab_to_symtab): No longer patch readin pst's out + of the partial_symtab_list; need them there for some checks. + * blockframe.c (block_for_pc), source.c (select_source_symtab), + symtab.c (lookup_symbol, find_pc_symtab, list_symbols): Made extra + sure not to call psymtab_to_symtab with ->readin == 1, since these + psymtab now stay on the list. + * symtab.c (sources_info): Now distinguishes between psymtabs with + readin set and those with it not set. + + * symtab.c (lookup_symtab): Added check through partial symtabs + for name with .c appended. + + * source.c (select_source_symtab): Changed semantics a little so + that the argument means something. + * source.c (list_command), symtab.c (decode_line_1): Changed call + to select_source_symtab to match new conventions. + + * dbxread.c (add_file_command): This command no longer selects a + symbol table to list from. + + * infrun.c (wait_for_inferior): Only call find_pc_function (to + find out if we have debugging symbols for a function and hence if + we should step over or into it) if we are doing a "step". + +Thu Apr 6 12:42:28 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * main.c (command_line_input): Added a local buffer and only + copied information into the global main.c buffer when it is + appropriate for it to be saved (and repeated). + (dont_repeat): Only nail line when we are reading from stdin + (otherwise null lines won't repeat and what's in line needs to be + saved). + (read_command_lines): Fixed typo; you don't what to repeat when + reading command lines from the input stream unless it's standard + input. + + John Gilmore's (gnu@toad.com) mods for USG gdb: + * inflow.c: Removed inclusion of sys/user.h; no longer necessary. + (, terminal_init_inferior, terminal_inferior, terminal_ours_1, + term_status_command, _initialize_inflow) Seperated out declaration + and usage of terminal mode structures based on the existence of + the individual ioctls. + * utils.c (request_quit): Restore signal handler under USG. If + running under USG initialize sys_siglist at run time (too much + variation between systems). + +Wed Apr 5 13:47:24 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + John Gilmore's (gnu@toad.com) mods for USG gdb: + * default-dep.c: Moved include of sys/user.h to after include of + a.out.h. + (store_inferior_registers): Fixed error message. + (core_file_command): Improved error messages from reading in of + u area in core file. Changed calculation of offset of registers + to account for some machines putting it in as an offset rather + than an absolute address. Changed error messages for reading of + registers from core file. + + * coffread.c (read_file_hdr): Added final check for BADMAG macro + to use if couldn't recognize magic number. + * Makefile: Added explicit directions for alloca addition. + Included alloca.c in list of possible library files. Cleaned up + possible library usage. Included additional information on gcc + and include files. + + * source.c, remote.c, inflow.c, dbxread.c, core.c, coffread.c: + Changed include of sys/fcntl.h to an include of fcntl.h (as per + posix; presumably this will break fewer machines. I hopw). + * README: Added a pointer to comments at top of Makefile. + * Makefile: Added a comment about machines which need fcntl.h in + sys. + +Tue Apr 4 11:29:04 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * valprint.c (set_prettyprint_command, set_unionprint_command, + format_info): Created. + (_initialize_valprint): Added to lists of commands. + + * gdb.texinfo [Backtrace]: Added a section describing the format + if symbols have not yet been read in. + + * valprint.c (val_print): Added code to prettyprint structures if + "prettyprint" is set and only to print unions below the top level + if "unionprint" is set. + + * infcmd.c (registers_info), valprint.c (value_print, val_print): + Added argument to call to val_print indicating deptch of recursion. + + * symtab.[ch] (find_pc_psymbol): Created; finds static function + psymbol with value nearest to but under value passed. + * stack.c (print_frame_info): Used above to make sure I have best + fit to pc value. + + * symseg.h (struct partial_symbol): Added value field. + * dbxread.c (read_dbx_symtab): Set value field for partial symbols + saved (so that we can lookup static symbols). + + * symtab.[ch] (find_pc_symtab): Changed to external. + * stack.c (select_frame): Call above to make sure that symbols for + a selected frame is readin. + +Mon Apr 3 12:48:16 1989 Randall Smith (randy at plantaris.ai.mit.edu) + + * stack.c (print_frame_info): Modified to only print out full + stack frame info on symbols whose tables have been read in. + * symtab.c, symtab.h (find_pc_psymtab): Made function external; + above needed it. + + * main.c (,set_verbose_command, initialize_main): Created a + variable "info_verbose" which says to talk it up in various and + sundry places. Added command to set this variable. + * gdb.texinfo (GDB Output): Added documentation on "set verbose" + and changed the name of the "Screen Output" section to "GDB + Output". + * dbxread.c (psymtab_to_symtab): Added information message about + symbol readin. Conditionalized on above. + + * dbxread.c (define_symbol): Made an "i" constant be of class + LOC_CONST and an "r" constant be of class LOC_CONST_BYTES. + + * README: Made a note about modifications which may be necessary + to the manual for this version of gdb. + + * blockframe.c (get_prev_frame_info): Now we get saved address and + check for validity before we check for leafism. This means that + we will catch the fact that we are in start, but we will miss any + fns that start calls without an fp. This should be fine. + + * m-*.h (FRAME_CHAIN): Modified to return 0 if we are in start. + This is usually a test for within the first object file. + * m-sparc.h (FRAME_CHAIN): The test here is simply if the fp saved + off the the start sp is 0. + + * blockframe.c (get_prev_frame_info): Removed check to see if we + were in start. Screws up sparc. + + * m-sparc.h (FRAME_FIND_SAVED_REGISTERS): Changed test for dummy + frame to not need frame to be innermost. + + * gdb.texinfo: Added section on frameless invocations of functions + and when gdb can and can't deal with this. + + * stack.c (frame_info): Disallowed call if no inferior or core + file; fails gracefully if truely bad stack specfication has been + given (ie. parse_frame_specification returns 0). + +Fri Mar 31 13:59:33 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * infrun.c (normal_stop): Changed references to "unset-env" to + "delete env". + + * infcmd.c (_initialize_infcmd): Change reference to set-args in + help run to "set args". + + * remote.c (getpkt): Allow immediate quit when reading from + device; it could be hung. + + * coffread.c (process_coff_symbol): Modify handling of REG + parameter symbols. + +Thu Mar 30 15:27:23 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * dbxread.c (symbol_file_command): Use malloc to allocate the + space for the string table in symbol_file_command (and setup a + cleanup for this). This allows a more graceful error failure if + there isn't any memory availible (and probably allows more memory + to be avail, depending on the machine). + + Additional mods for handling GNU C++ (from Tiemann): + * dbxread.c (read_type): Added case for '#' type (method type, I + believe). + (read_struct_type): If type code is undefined, make the main + variant for the type be itself. Allow recognition of bad format + in reading of structure fields. + * eval.c (evaluate_subexp): Modify evaluation of a member of a + structure and pointer to same to make sure that the syntax is + being used correctly and that the member is being accessed correctly. + * symseg.h: Added TYPE_CODE_METHOD to enum type_code. Add a + pointer to an array of argument types to the type structure. + * symtab.c (lookout_method_type, smash_to_method_type): Created. + * symtab.h (TYPE_ARG_TYPES): Created. + * valops.c (call_function): Modified handling of methods to be the + same as handling of functions; no longer check for members. + * valprint.c (val_print, type_print_varspec_{prefix,suffix}, + type_print_base): Added code to print method args correctly. + * values.c (value_virtual_fn_field): Modify access to virtual + function table. + +Wed Mar 29 13:19:34 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * findvar.c: Special cases for REGISTER_WINDOWS: 1) Return 0 if we + are the innermost frame, and 2) return the next frame in's value + if the SP is being looked for. + + * blockframe.c (get_next_frame): Created; returns the next (inner) + frame of the called frame. + * frame.h: Extern delcaration for above. + + * main.c (command_line_input): Stick null at end before doing + history expansion. + +Tue Mar 28 17:35:50 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * dbxread.c (read_dbx_symtab): Added namestring assignment to + N_DATA/BSS/ABS case. Sigh. + +Sat Mar 25 17:49:07 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * expread.y: Defined YYDEBUG. + +Fri Mar 24 20:46:55 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * symtab.c (make_symbol_completion_list): Completely rewrote to + never call psymtab_to_symtab, to do a correct search (no + duplicates) through the visible symbols, and to include structure + and union fields in the things that it can match. + +Thu Mar 23 15:27:44 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * dbxread.c (dbx_create_type): Created; allocates and inits space + for a type without putting it on the type vector lists. + (dbx_alloc_type): Uses above. + + * Makefile: xgdb.o now produced by default rules for .o.c. + +Fri Mar 17 14:27:50 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * infrun.c: Fixed up inclusion of aouthdr.h on UMAX_PTRACE. + + * Makefile, config.gdb: Added hp300bsd to potential + configurations. + * hp300bsd-dep.c, m-hp300bsd.h: Created. + + * infrun.c (wait_for_inferior): Rewrote to do no access to + inferior until we make sure it's still there. + + * inflow.c (inferior_died): Added a select to force the selected + frame to null when inferior dies. + + * dbxread.c (symbol_file_command): free and zero symfile when + discarding symbols. + + * core.c (xfer_core_file): Extended and cleaned up logic in + interpeting memory address. + + * core.c (xfer_core_file): Extended opening comment. + +Thu Mar 16 15:39:42 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * coffread.c (symbol_file_command): Free symfile name when freeing + contents. + + * blockframe.c (get_prev_frame_info): Added to fatal error message + to indicate that it should never happen. + + * stack.c (frame_info): Printed out value of "saved" sp seperately + to call attention to the fact that it isn't stored in memory + anywhere; the actual previous frames address is printed. + + * m-sparc.h (FRAME_FIND_SAVED_REGS): Set address of sp saved in + frame to value of fp (rather than value of sp in current frame). + + * expread.y: Allow "unsigned" as a type itself, as well as a type + modifier. + + * coffread.c: Added declaration for fclose + +Fri Mar 10 17:22:31 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * main.c (command_line_input): Checked for -1 return from + readline; indicates EOF. + +Fri Mar 3 00:31:27 1989 Randall Smith (randy at gluteus.ai.mit.edu) + + * remote.c (remote_open): Cast return from signal to (void (*)) to + avoid problems on machines where the return type of signal is (int + (*)). + + * Makefile: Removed deletion of version control from it (users + will need it for their changes). + +Thu Mar 2 15:32:21 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * symmetry-dep.c (print_1167_regs): Print out effective doubles on + even number regs. + (fetch_inferior_registers): Get the floating point regs also. + + * xgdb.c (do_command): Copied command before calling execute + command (so that execute_command wouldn't write into text space). + + * copying.awk: Created (will produce copying.c as output when + given COPYING as input). + * Makefile: Used above to create copying.c. + * main.c: Took out info_warranty and info_copying. + + * *.*: Changed copyright notice to use new GNU General Public + License (includes necessary changes to manual). + + * xgdb.c (create_text_widget): Created text_widget before I create + the source and sink. + (print_prompt): Added fflush (stdout). + + * Makefile: Added -lXmu to the compilation line for xgdb. Left + the old one there incase people still had R2. + + * README: Added note about -gg format. + + * remote.c (getpkt): Fixed typo; && ==> &. + + * Makefile: Added new variable READLINE_FLAGS so that I could + force compilation of readline.c and history.c with -DSYSV on + system V machines. Mentioned in Makefile comments at top. + +Wed Mar 1 17:01:01 1989 Randall Smith (randy at gluteus.ai.mit.edu) + + * hp9k320-dep.c (store_inferior_registers): Fixed typo. + +Fri Feb 24 14:58:45 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * hp9k320-dep.c (store_inferior_registers, + fetch_inferior_registers): Added support for remote debugging. + + * remote.c (remote_timer): Created. + (remote_open, readchar): Setup to timeout reads if they take + longer than "timeout". This allows one to debug how long such + things take. + (putpkt): Modified to print a debugging message (if such things + are enabled) each time it resends a packet. + (getpkt): Modified to make the variable CSUM unsigned and read it + CSUM with an & 0xff (presumably to deal with poor sign extension + on some machines). Also made c1 and c2 unsigned. + (remote_wait): Changed buffer to unsigned status. + (remote_store_registers, remote_write_bytes): Puts a null byte at + the end of the control string. + + * infcmd.c (attach_command, detach_command, _initialize_infcmd): + Made attach_command and detach_command always availible, but + modified them to only allow device file attaches if ATTACH_DETACH + is not defined. + + * gdb.texinfo: Added cross reference from attach command to remote + debugging. + +Thu Feb 23 12:37:59 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * remote.c (remote_close): Created to close the remote connection + and set the remote_debugging flag to 0. + * infcmd.c (detach_command): Now calls the above when appropriate. + + * gdb.texinfo: Removed references to the ``Distribution'' section + in the copyright. + + * main.c, utils.c (ISATTY): Created default defintions of this + macro which use isatty and fileno. + * utils.c (fprintf_filtered, print_spaces_filtered), main.c + (command_loop, command_line_input): Used this macro. + * m-news.h: Created a definition to override this one. + + * utils.c (fprintf_filtered): Made line_size static (clueless). + + * utils.c (fprintf_filtered): Changed max length of line printed + to be 255 chars or twice the format length. + + * symmetry-dep.c, m-symmetry: Fixed typo (^L ==> ). + + * printcmd.c (do_examine): Fixed typo (\n ==> \t). + +Wed Feb 22 16:00:33 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + Contributed by Jay Vosburgh (jay@mentor.cc.purdue.edu) + * m-symmetry.h, symmetry-dep.c: Created. + * Makefile: Added above in appropriate lists. + * config.gdb: Added "symmetry" target. + + * utils.c (prompt_for_continue): Zero'd chars_printed also. + + * utils.c (fprintf_filtered): Call prompt for continue instead of + doing it yourself. + + * dbxread.c (read_dbx_symtab): Added code to conditionalize what + symbol type holds to "x.o" or "-lx" symbol that indicates the + beginning of a new file. + +Tue Feb 21 16:22:13 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * gdb.texinfo: Deleted @ignore block at end of file. + + * findvar.c, stack.c: Changed comments that refered to "frame + address" to "frame id". + + * findvar.c (locate_var_value): Modified so that taking the + address of an array generates an object whose type is a pointer to + the elements of the array. + +Sat Feb 18 16:35:14 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * gdb.texinfo: Removed reference to "!" as a shell escape + character. Added a section on controling screen output + (pagination); changing "Input" section to "User Interface" + section. Changed many inappropriate subsubsection nodes into + subsections nodes (in the readline and history expansion + sections). + +Fri Feb 17 11:10:54 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * utils.c (set_screensize_command): Created. + (_initialize_utils): Added above to setlist. + + * main.c (main): Added check to see if ~/.gdbinit and .gdbinit + were the same file; only one gets read if so. Had to include + sys/stat.h for this. + + * valprint.c (type_print_base): Changed calls to print_spaces to + print_spaces_filtered. + + * main.c (command_line_input): Chaned test for command line + editing to check for stdin and isatty. + + * main.c (command_loop): Call reinitialize_more_filter before each + command (if reading from stdin and it's a tty). + utils.c (initialize_more_filter): Changed name to + reinitialize_more_filter; killed arguments. + utils.c (_initialize_utils): Created; initialized lines_per_page + and chars_per_line here. + + * utils.c (fprintf_filtered): Removed printing of "\\\n" after + printing linesize - 1 chars; assume that the screen display will + take care of that. Still watching that overflow. + + * main.c: Created the global variables linesize and pagesize to + describe the number of chars per line and lines per page. + +Thu Feb 16 17:27:43 1989 Randall Smith (randy at gluteus.ai.mit.edu) + + * printcmd.c (do_examine, print_scalar_formatted, print_address, + whatis_command, do_one_display, ptype_command), valprint.c + (value_print, val_print, type_print_method_args, type_print_1, + type_print_derivation_info, type_print_varspec_suffix, + type_print_base), breakpoint.c (breakpoints_info, breakpoint_1), + values.c (history_info), main.c (editing_info, warranty_info, + copying_info), infcmd.c (registers_info), inflow.c + (term_status_command), infrun.c (signals_info), stack.c + (backtrace_command, print_frame_info), symtab.c (list_symbols, + output_source_filename), command.c (help_cmd, help_list, + help_command_list): Replaced calls to printf, fprintf, and putc + with calls to [f]printf_filtered to handle more processing. + Killed local more emulations where I noticed them. + +Wed Feb 15 15:27:36 1989 Randall Smith (randy at gluteus.ai.mit.edu) + + * defs.h, utils.c (initialize_more_filter, fprintf_filtered, + printf_filtered): Created a printf that will also act as a more + filter, prompting the user for a whenever the page length + is overflowed. + + * symtab.c (list_symbols): Elminated some code inside of an #if 0. + +Tue Feb 14 11:11:24 1989 Randall Smith (randy at gluteus.ai.mit.edu) + + * Makefile: Turned off backup versions for this file; it changes + too often. + + * command.c (lookup_cmd, _initialize_command): Changed '!' so that + it was no longer a shell escape. "sh" must be used. + + * main.c (command_line_input, set_history_expansion, + initialize_main): Turned history expansion on, made it the + default, and only execute it if the first character in the line is + a '!'. + + * version.c, gdb.texinfo: Moved version to 3.2 (as usual, jumping + the gun some time before release). + + * gdb.texinfo: Added sections (adapted from Brian's notes) on + command line editing and history expansion. + + * main.c (set_command_editing, initialize_main): Modified name to + set_editing and modified command to "set editing". + + * Makefile: Put in dependencies for READLINEOBJS. + + * main.c (history_info, command_info): Combined into new command + info; deleted history_info. + (initialize_main): Deleted "info history" command; it was + interfering with the value history. + + * coffread.c (enter_linenos): Modified to do bit copy instead of + pointer dereference, since the clipper machine can't handle having + longs on short boundaries. + (read_file_hdr): Added code to get number of syms for clipper. + + * stack.c (return_command): Fixed method for checking when all of + the necessary frames had been popped. + + * dbxread.c (read_dbx_symtab (ADD_PSYMBOL_TO_LIST)): Fixed typo in + allocation length. + +Mon Feb 13 10:03:27 1989 Randall Smith (randy at gluteus.ai.mit.edu) + + * dbxread.c (read_dbx_symtab): Split assignment to namestring into + several different assignments (so that it wouldn't be done except + when it had to be). Shortened switches and duplicated code to + produce the lowest possible execution time. Commented (at top of + switch) which code I duplicated. + + * dbxread.c (read_dbx_symtab): Modified which variables were + register and deleted several variables which weren't used. Also + eliminated 'F' choice from subswitch, broke out strcmp's, reversed + compare on line 1986, and elminated test for !namestring[0]; it is + caught by following test for null index of ':'. + +Sun Feb 12 12:57:56 1989 Randall Smith (randy at plantaris.ai.mit.edu) + + * main.c (gdb_completer_word_break_characters): Turned \~ into ~. + +Sat Feb 11 15:39:06 1989 Randall Smith (randy at plantaris.ai.mit.edu) + + * symtab.c (find_pc_psymtab): Created; checks all psymtab's till + it finds pc. + (find_pc_symtab): Used; fatal error if psymtab found is readin + (should have been caught in symtab loop). + (lookup_symbol): Added check before scan through partial symtab + list for symbol name to be on the misc function vector (only if in + VAR_NAMESPACE). Also made sure that psymtab's weren't fooled with + if they had already been read in. + (list_symbols): Checked through misc_function_vector for matching + names if we were looking for functions. + (make_symbol_completion_list): Checked through + misc_function_vector for matching names. + * dbxread.c (read_dbx_symtab): Don't bother to do processing on + global function types; this will be taken care of by the + misc_function hack. + + * symtab.h: Modified comment on misc_function structure. + +Fri Feb 10 18:09:33 1989 Randall Smith (randy at plantaris.ai.mit.edu) + + * symseg.h, dbxread.c (read_dbx_symtab, init_psymbol_list, + start_psymtab, end_psymtab), coffread.c (_initialize_coff), + symtab.c (lookup_partial_symbol, list_symbols, + make_symbol_completion_list): Changed separate variables for + description of partial symbol allocation into a specific kind of + structure. + + (read_dbx_symtab, process_symbol_for_psymtab): Moved most of + process_symbol_for_psymtab up into read_dbx_symtab, moved a couple + of symbol types down to the ingore section, streamlined (I hope) + code some, modularized access to psymbol lists. + +Thu Feb 9 13:21:19 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * main.c (command_line_input): Made sure that it could recognize + newlines as indications to repeat the last line. + + * symtab.c (_initialize_symtab): Changed size of builtin_type_void + to be 1 for compatibility with gcc. + + * main.c (initialize_main): Made history_expansion the default + when gdb is compiled with HISTORY_EXPANSION. + + * readline.c, readline.h, history.c, history.h, general.h, + emacs_keymap.c, vi_keymap.c, keymaps.c, funmap.c: Made all of + these links to /gp/gnu/bash/* to keep them updated. + * main.c (initialize_main): Made default be command editing on. + +Wed Feb 8 13:32:04 1989 & Smith (randy at hobbes) + + * dbxread.c (read_dbx_symtab): Ignore N_BSLINE on first + readthrough. + + * Makefile: Removed convex-dep.c from list of distribution files. + +Tue Feb 7 14:06:25 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * main.c: Added command lists sethistlist and unsethistlist to + accesible command lists. + (parse_binary_operation): Created to parse a on/1/yes vs. off/0/no + spec. + (set_command_edit, set_history, set_history_expansion, + set_history_write, set_history_size, set_history_filename, + command_info, history_info): Created to allow users to control + various aspects of command line editing. + + * main.c (symbol_creation_function): Created. + (command_line_input, initialize_main): Added rest of stuff + necessary for calling bfox' command editing routines under + run-time control. + * Makefile: Included readline and history source files for command + editing; also made arrangements to make sure that the termcap + library was available. + * symtab.c (make_symbol_completion_list): Created. + +Mon Feb 6 16:25:25 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * main.c: Invented variables to control command editing. + command_editing_p, history_expansion_p, history_size, + write_history_p, history_filename. Initialized them to default + values in initialize_main. + + * infcmd.c (registers_info), infrun.c (signals_info), + * main.c (gdb_read_line): Changed name to command_line_input. + (readline): Changed name to gdb_readline; added second argument + indicating that the read value shouldn't be saved (via malloc). + * infcmd.c (registers_info), infrun.c (signals_info), main.c + (copying_info), symtab.c (output_source_filename, MORE, + list_symbols): Converted to use gdb_readline in place of + gdb_read_line. + + +Sun Feb 5 17:34:38 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * blockframe.c (get_frame_saved_regs): Removed macro expansion + that had accidentally been left in the code. + +Sat Feb 4 17:54:14 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * main.c (gdb_read_line, readline): Added function readline and + converted gdb_read_line to use it. This was a conversion to the + line at a time style of input, in preparation for full command + editing. + +Fri Feb 3 12:39:03 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * dbxread.c (read_dbx_symtab): Call end_psymtab at the end of + read_dbx_symtab if any psymtab still needs to be completed. + + * config.gdb, sun3-dep.c: Brought these into accord with the + actual sun2 status (no floating point period; sun3-dep.c unless + has os > 3.0). + * m-sun2os2.h: Deleted; not needed. + + * config.gdb: Added a couple of aliases for machines in the + script. + + * infrun.c: Added inclusion of aouthdr.h inside of #ifdef UMAX + because ptrace needs to know about the a.out header. + + * Makefile: Made dep.o depend on dep.c and config.status only. + + * expread.y: Added declarations of all of the new write_exp_elt + functions at the include section in the top. + + * Makefile: Added a YACC definition so that people can use bison + if they wish. + + * Makefile: Added rms' XGDB-README to the distribution. + + * Makefile: Added removal of init.o on a "make clean". + +Thu Feb 2 16:27:06 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * *-dep.c: Deleted definition of COFF_FORMAT if AOUTHDR was + defined since 1) We *may* (recent mail message) want to define + AOUTHDR under a basically BSD system, and 2) AOUTHDR is sometimes + a typedef in coff encapsulation setups. Also removed #define's of + AOUTHDR if AOUTHDR is already defined (inside of coff format). + * core.c, dbxread.c: Removed #define's of AOUTHDR if AOUTHDR is + already defined (inside of coff format). + Tue Jan 31 12:56:01 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + * GDB 3.1 released. + * values.c (modify_field): Changed test for endianness to assign to integer and reference character (so that all bits would be defined). @@ -932,71 +3631,79 @@ Sun Dec 4 17:03:16 1988 Randall Smith (randy at gluteus.ai.mit.edu) * createtags: Cleaned up and commented. - * Makefile: Updated dependency list and cleaned it up somewhat - (used macros, didn't make .o files depend on .c files, etc.) + * Makefile: Updated depen_memory and write_inferior_memory in that errno is + checked after each ptrace and returned to the caller. Used in + value_at to detect references to addresses which are out of + bounds. Also core.c (xfer_core_file): return 1 if invalid + address, 0 otherwise. -Fri Dec 2 11:44:46 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu) + * inflow.c, -infdep.c: removed all calls to ptrace from + inflo, m-sun3.h: Cleaned up dealings with + functions returning structu0 19:19:36 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu) - * value.h, values.c, infcmd.c, valops.c, m-i386.h, m-sparc.h, - m-merlin.h, m-npl.h, m-pn.h, m-umax.h, m-vax.h, m-hp9k320.h, - m-isi.h, m-news.h, m-sun2.h, m-sun3.h: Cleaned up dealings with - functions returning structures. Specifically: Added a function - called using_struct_return which indicates whether the function - being called is using the structure returning conventions or it is - using the value returning conventions on that machine. Added a - macro, STORE_STRUCT_RETURN to store the address of the structure - to be copied into wherever it's supposed to go, and changed - call_function to handle all of this correctly. + * symmisc.c: (read_symsegs) Accept only format number 2. Since + the size of the type structure changed when C++ support was added, + format 1 can no longer be used. - * symseg.h, symtab.h, dbxread.c: Added hooks to recognize an - N_TEXT symbol with name "*gcc-compiled*" as being a flag - indicating that a file had been compiled with gcc and setting a - flag in all blocks produced during processing of that file. + * core.c, m-sunos4.h: (core_file_command) support for SunOS 4.0. + Slight change in the core structure. #ifdef SUNOS4. New file + m-sunos4.h. May want to change config.gdb also. -Thu Dec 1 13:54:29 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu) +Fri Jul 8 19:59:49 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu) - * m-sparc.h (PUSH_DUMMY_FRAME): Saved 8 less than the current pc, - as POP_FRAME and sparc return convention restore the pc to 8 more - than the value saved. + * breakpoint.c: (break_command_1) Allow `break if condition' + rather than parsing `if' as a function name and returning an + error. - * valops.c, printcmd.c, findvar.c, value.h: Added the routine - value_from_register, to access a specific register of a specific - frame as containing a specific type, and used it in read_var_value - and print_frame_args. +Thu Jul 7 22:22:47 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu) -Wed Nov 30 17:39:50 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu) + * C++: valops.c, valprint.c, value.h, values.c: merged code to deal + with C++ expressions. - * dbxread.c (read_number): Will accept either the argument passed - as an ending character, or a null byte as an ending character. +Wed Jul 6 03:28:18 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu) - * Makefile, createtags: Added entry to create tags for gdb - distribution which will make sure currently configured machine - dependent files come first in the list. + * C++: dbxread.c: (read_dbx_symtab, condense_misc_bunches, + add_file_command) Merged code to read symbol information from + an incrementally linked file. symmisc.c: + (init_free_inclink_symtabs, free_inclink_symtabs) Cleanup + routines. -Wed Nov 23 13:27:34 1988 Randall Smith (randy at gluteus.ai.mit.edu) +Tue Jul 5 02:50:41 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu) - * stack.c, infcmd.c, sparc-dep.c: Modified record_selected_frame - to work off of frame address. + * C++: symtab.c, breakpoint.c, source.c: Merged code to deal with + ambiguous line specifications. In C++ one can have overloaded + function names, so that `list classname::overloadedfuncname' + refers to several different lines, possibly sure currently configured machine + dependent files come first in e at corn-chex.ai.mit.edu) - * blockframe.c (create_new_frame, get_prev_frame_cache_item): - Added code to reset pointers within frame cache if it must be - realloc'd. + * C++: symtab.c: replaced lookup_symtab_1 and lookup_symtab_2 with + a modified lookup_symbol which checks for fields of the current + implied argument `this'. printcmd.c, source.c, symtab.c, + valops.c: Need to change callers once callers are + installed. - * dbxread.c (read_dbx_symtab): Added in optimization comparing - last couple of characters instead of first couple to avoid - strcmp's in read_dbx_symtab (recording extern syms in misc - functions or not). 1 call to strlen is balanced out by many fewer - calls to strcmp. +Wed Jun 29 01:26:56 1988 Peter TerMaat (pete at frosted-flakes.ai.mit.edu) -Tue Nov 22 16:40:14 1988 Randall Smith (randy at cream-of-wheat.ai.mit.edu) + * C++: eval.c, expprint.c, expread.y, expression.h, valarith.c, + Merged code to deal with evaluation of user-defined operators, + member functions, and virtual functions. + binop_must_be_user_defined tests for user-defined binops, + value_x_binop calls the appropriate operator function. - * dbxread.c (read_dbx_symtab): Took out optimization for ignoring - LSYM's; was disallowing typedefs. Silly me. +Tue Jun 28 02:56:42 1988 Peter TerMaat (pete at frosted-flakes.ai.mit.edu) - * Checkpointed distribution (mostly for sending to Tiemann). + * C++: Makefile: changed the echo: expect 101 shift/reduce conflicts + and 1 reduce/reduce conflict. - * expression.h: Added BINOP_MIN and BINOP_MAX operators for C++. - * symseg.h: Included flags for types having destructors and + +Local Variables: +mode: indented-text +eval: (auto-fill-mode 1) +left-margin: 8 +fill-column: 74 +version-control: never +End: +ng destructors and constructors, and flags being defined via public and via virtual paths. Added fields NEXT_VARIANT, N_BASECLASSES, and BASECLASSES to this type (tr: Changed types from @@ -1799,11 +4506,9 @@ Tue Jun 28 02:56:42 1988 Peter TerMaat (pete at frosted-flakes.ai.mit.edu) * C++: Makefile: changed the echo: expect 101 shift/reduce conflicts and 1 reduce/reduce conflict. - Local Variables: mode: indented-text -eval: (auto-fill-mode 1) left-margin: 8 fill-column: 74 version-control: never diff --git a/gdb/Convex.notes b/gdb/Convex.notes new file mode 100644 index 0000000000..28d336bfed --- /dev/null +++ b/gdb/Convex.notes @@ -0,0 +1,163 @@ + +@node Convex,,, Top +@appendix Convex-specific info +@cindex Convex notes + +Scalar registers are 64 bits long, which is a pain since +left half of an S register frequently contains noise. +Therefore there are two ways to obtain the value of an S register. + +@table @kbd +@item $s0 +returns the low half of the register as an int + +@item $S0 +returns the whole register as a long long +@end table + +You can print the value in floating point by using @samp{p/f $s0} or @samp{p/f $S0} +to print a single or double precision value. + +@cindex vector registers +Vector registers are handled similarly, with @samp{$V0} denoting the whole +64-bit register and @kbd{$v0} denoting the 32-bit low half; @samp{p/f $v0} +or @samp{p/f $V0} can be used to examine the register in floating point. +The length of the vector registers is taken from @samp{$vl}. + +Individual elements of a vector register are denoted in the obvious way; +@samp{print $v3[9]} prints the tenth element of register @kbd{v3}, and +@samp{set $v3[9] = 1234} alters it. + +@kbd{$vl} and @kbd{$vs} are int, and @kbd{$vm} is an int vector. +Elements of @kbd{$vm} can't be assigned to. + +@cindex communication registers +@kindex info comm-registers +Communication registers have names @kbd{$C0 .. $C63}, with @kbd{$c0 .. $c63} +denoting the low-order halves. @samp{info comm-registers} will print them +all out, and tell which are locked. (A communication register is +locked when a value is sent to it, and unlocked when the value is +received.) Communication registers are, of course, global to all +threads, so it does not matter what the currently selected thread is. +@samp{info comm-reg @var{name}} prints just that one communication +register; @samp{name} may also be a communication register number +@samp{nn} or @samp{0xnn}. +@samp{info comm-reg @var{address}} prints the contents of the resource +structure at that address. + +@kindex info psw +The command @samp{info psw} prints the processor status word @kbd{$ps} +bit by bit. + +@kindex set base +GDB normally prints all integers in base 10, but the leading +@kbd{0x80000000} of pointers is intolerable in decimal, so the default +output radix has been changed to try to print addresses appropriately. +The @samp{set base} command can be used to change this. + +@table @code +@item set base 10 +Integer values always print in decimal. + +@item set base 16 +Integer values always print in hex. + +@item set base +Go back to the initial state, which prints integer values in hex if they +look like pointers (specifically, if they start with 0x8 or 0xf in the +stack), otherwise in decimal. +@end table + +@kindex set pipeline +When an exception such as a bus error or overflow happens, usually the PC +is several instructions ahead by the time the exception is detected. +The @samp{set pipe} command will disable this. + +@table @code +@item set pipeline off +Forces serial execution of instructions; no vector chaining and no +scalar instruction overlap. With this, exceptions are detected with +the PC pointing to the instruction after the one in error. + +@item set pipeline on +Returns to normal, fast, execution. This is the default. +@end table + +@cindex parallel +In a parallel program, multiple threads may be executing, each +with its own registers, stack, and local memory. When one of them +hits a breakpoint, that thread is selected. Other threads do +not run while the thread is in the breakpoint. + +@kindex 1cont +The selected thread can be single-stepped, given signals, and so +on. Any other threads remain stopped. When a @samp{cont} command is given, +all threads are resumed. To resume just the selected thread, use +the command @samp{1cont}. + +@kindex thread +The @samp{thread} command will show the active threads and the +instruction they are about to execute. The selected thread is marked +with an asterisk. The command @samp{thread @var{n}} will select thread @var{n}, +shifting the debugger's attention to it for single-stepping, +registers, local memory, and so on. + +@kindex info threads +The @samp{info threads} command will show what threads, if any, have +invisibly hit breakpoints or signals and are waiting to be noticed. + +@kindex set parallel +The @samp{set parallel} command controls how many threads can be active. + +@table @code +@item set parallel off +One thread. Requests by the program that other threads join in +(spawn and pfork instructions) do not cause other threads to start up. +This does the same thing as the @samp{limit concurrency 1} command. + +@item set parallel fixed +All CPUs are assigned to your program whenever it runs. When it +executes a pfork or spawn instruction, it begins parallel execution +immediately. This does the same thing as the @samp{mpa -f} command. + +@item set parallel on +One or more threads. Spawn and pfork cause CPUs to join in when and if +they are free. This is the default. It is very good for system +throughput, but not very good for finding bugs in parallel code. If you +suspect a bug in parallel code, you probably want @samp{set parallel fixed.} +@end table + +@subsection Limitations + +WARNING: Convex GDB evaluates expressions in long long, because S +registers are 64 bits long. However, GDB expression semantics are not +exactly C semantics. This is a bug, strictly speaking, but it's not one I +know how to fix. If @samp{x} is a program variable of type int, then it +is also type int to GDB, but @samp{x + 1} is long long, as is @samp{x + y} +or any other expression requiring computation. So is the expression +@samp{1}, or any other constant. You only really have to watch out for +calls. The innocuous expression @samp{list_node (0x80001234)} has an +argument of type long long. You must explicitly cast it to int. + +It is not possible to continue after an uncaught fatal signal by using +@samp{signal 0}, @samp{return}, @samp{jump}, or anything else. The difficulty is with +Unix, not GDB. + +I have made no big effort to make such things as single-stepping a +@kbd{join} instruction do something reasonable. If the program seems to +hang when doing this, type @kbd{ctrl-c} and @samp{cont}, or use +@samp{thread} to shift to a live thread. Single-stepping a @kbd{spawn} +instruction apparently causes new threads to be born with their T bit set; +this is not handled gracefully. When a thread has hit a breakpoint, other +threads may have invisibly hit the breakpoint in the background; if you +clear the breakpoint gdb will be surprised when threads seem to continue +to stop at it. All of these situations produce spurious signal 5 traps; +if this happens, just type @samp{cont}. If it becomes a nuisance, use +@samp{handle 5 nostop}. (It will ask if you are sure. You are.) + +There is no way in GDB to store a float in a register, as with +@kbd{set $s0 = 3.1416}. The identifier @kbd{$s0} denotes an integer, +and like any C expression which assigns to an integer variable, the +right-hand side is casted to type int. If you should need to do +something like this, you can assign the value to @kbd{@{float@} ($sp-4)} +and then do @kbd{set $s0 = $sp[-4]}. Same deal with @kbd{set $v0[69] = 6.9}. diff --git a/gdb/Makefile b/gdb/Makefile deleted file mode 100644 index b47091cd24..0000000000 --- a/gdb/Makefile +++ /dev/null @@ -1,240 +0,0 @@ -# On HPUX, you need to add -Ihp-include to CFLAGS. -# The headers in the directory hp-include override system headers -# and tell GDB to use BSD executable file format. -# You must also define REGEX & REGEX1 below and ALLOCA & ALLOCA1 (get -# alloca.c from the emacs distribution) to the CLIBS. -# If you compile GDB with GCC on HPUX, you must make sure that the "nm" used -# in "munch" is GNU's nm. This is because gcc uses a different .o -# file format than the native HPUX compiler. - -# On USG (System V) machines, you must make sure to setup REGEX & -# REGEX1 to point at regex.o and use the USG version of CLIBS. -# If your system has a broken alloca() -- most do -- then get -# alloca.c from the GNU Emacs distribution and set ALLOCA & ALLOCA1. -# Also, 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. - -# On Sunos 4.0 machines, make sure to compile *without* shared -# libraries if you want to run gdb on itself. Make sure to compile -# any program on which you want to run gdb without shared libraries. - -# 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 will be -# incorrectly compiled. The "fixincludes" script in the gcc -# distribution will probably fix your include files up. - -CC=cc -SHELL=/bin/sh - -# Set this up with gcc if you have gnu ld and the loader will print out -# line numbers for undefinded refs. -CC-LD=${CC} - -# -I. for "#include ". Possibly regex.h also. -#CFLAGS = -g -pg -I. -O -CFLAGS = -I. -g -#LDFLAGS = -pg -g -LDFLAGS = -g - -# 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 system is missing alloca(), or, more likely, it's there but it -# doesn't work, define ALLOCA and ALLOCA1. -OBSTACK = obstack.o -OBSTACK1 = obstack.o -REGEX = regex.o -REGEX1 = regex.o -ALLOCA = alloca.o -ALLOCA1 = alloca.o -ADD_FILES = $(OBSTACK) $(REGEX) $(ALLOCA) $(GNU_MALLOC) -ADD_DEPS = $(OBSTACK1) $(REGEX1) $(ALLOCA1) $(GNU_MALLOC) - -# -# 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 = -#MALLOC_FLAGS = ${CFLAGS} -Drcheck -Dbotch=fatal -DMSTATS - -# for BSD -CLIBS = $(ADD_FILES) -# for USG -#CLIBS= $(ADD_FILES) -lPW - -SFILES = blockframe.c breakpoint.c coffread.c command.c core.c dbxread.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 = convex-dep.c umax-dep.c gould-dep.c default-dep.c sun3-dep.c \ - sparc-dep.c hp9k320-dep.c news-dep.c i386-dep.c - -PINSNS = gld-pinsn.c i386-pinsn.c sparc-pinsn.c vax-pinsn.c m68k-pinsn.c \ - ns32k-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 - -MFILES = m-hp9k320.h m-i386.h m-i386gas.h m-isi.h m-merlin.h m-news.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 - -POSSLIBS = obstack.h obstack.c regex.c regex.h malloc.c - -TESTS = testbpt.c testfun.c testrec.c testreg.c testregs.c - -OTHERS = Makefile createtags munch config.gdb ChangeLog README TAGS \ - gdb.texinfo .gdbinit COPYING expread.tab.c stab.def hp-include - -TAGFILES = ${SFILES} ${DEPFILES} ${PINSNS} ${HFILES} ${OPCODES} ${MFILES} \ - ${POSSLIBS} -TARFILES = ${TAGFILES} ${OTHERS} - -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 - -TSOBS = core.o inflow.o dep.o - -NTSOBS = standalone.o - -TSSTART = /lib/crt0.o - -NTSSTART = kdb-start.o - -gdb : $(OBS) $(TSOBS) $(ADD_DEPS) - -rm -f init.c - ./munch $(OBS) $(TSOBS) > init.c - ${CC-LD} $(LDFLAGS) -o gdb init.c $(OBS) $(TSOBS) $(CLIBS) - -xgdb : $(OBS) $(TSOBS) xgdb.o $(ADD_DEPS) - -rm -f init.c - ./munch $(OBS) $(TSOBS) xgdb.o > init.c - $(CC-LD) $(LDFLAGS) -o xgdb init.c $(OBS) $(TSOBS) xgdb.o \ - -lXaw -lXt -lX11 $(CLIBS) - -kdb : $(NTSSTART) $(OBS) $(NTSOBS) $(ADD_DEPS) - -rm -f init.c - ./munch $(OBS) $(NTSOBS) > init.c - $(CC-LD) $(LDFLAGS) -c init.c $(CLIBS) - ld -o kdb $(NTSSTART) $(OBS) $(NTSOBS) init.o -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 - tar chf gdb.tar dist-gdb - rm -rf dist-gdb - -gdb.tar.Z: gdb.tar - compress gdb.tar - -clean: - -rm -f ${OBS} ${TSOBS} ${NTSOBS} ${OBSTACK} ${REGEX} - -rm -f init.c init.o - -rm -f gdb - -realclean: clean - -rm -f expread.tab.c tags TAGS - -xgdb.o : xgdb.c defs.h param.h symtab.h frame.h - $(CC) -c $(CFLAGS) xgdb.c -o $@ - -expread.tab.c : expread.y - @echo 'Expect 101 shift/reduce conflicts and 1 reduce/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 - -# -# Only useful if you are using the gnu malloc routines. -# -malloc.o : malloc.c - ${CC} -c ${MALLOC_FLAGS} malloc.c - -# -# dep.o depends on ALL the dep files since we don't know which one -# is really being used. -# -dep.o : ${DEPFILES} defs.h param.h frame.h inferior.h obstack.h \ - a.out.encap.h - -# pinsn.o depends on ALL the opcode printers -# since we don't know which one is really being used. -pinsn.o : ${PINSNS} defs.h param.h symtab.h obstack.h symseg.h frame.h \ - ${OPCODES} - -# -# 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. -# -blockframe.o : defs.h param.h symtab.h obstack.h symseg.h frame.h -breakpoint.o : defs.h param.h symtab.h obstack.h symseg.h frame.h -coffread.o : defs.h param.h -command.o : command.h defs.h -core.o : defs.h param.h a.out.encap.h -dbxread.o : param.h 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 symtab.h obstack.h symseg.h value.h expression.h -expprint.o : defs.h symtab.h obstack.h symseg.h param.h expression.h -findvar.o : defs.h param.h symtab.h obstack.h symseg.h frame.h value.h -infcmd.o : defs.h param.h symtab.h obstack.h symseg.h frame.h inferior.h \ - environ.h value.h -inflow.o : defs.h param.h frame.h inferior.h -infrun.o : defs.h param.h symtab.h obstack.h symseg.h frame.h inferior.h \ - wait.h -kdb-start.o : defs.h param.h -main.o : defs.h command.h param.h -malloc.o : getpagesize.h -obstack.o : obstack.h -printcmd.o : defs.h param.h frame.h symtab.h obstack.h symseg.h value.h \ - expression.h -regex.o : regex.h -remote.o : defs.h param.h frame.h inferior.h wait.h -source.o : defs.h symtab.h obstack.h symseg.h param.h -stack.o : defs.h param.h symtab.h obstack.h symseg.h frame.h -standalone.o : defs.h param.h 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 obstack.h -utils.o : defs.h param.h -valarith.o : defs.h param.h symtab.h obstack.h symseg.h value.h expression.h -valops.o : defs.h param.h symtab.h obstack.h symseg.h value.h frame.h \ - inferior.h -valprint.o : defs.h param.h symtab.h obstack.h symseg.h value.h -values.o : defs.h param.h 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 diff --git a/gdb/Makefile.dist b/gdb/Makefile.dist new file mode 100644 index 0000000000..751145dbb7 --- /dev/null +++ b/gdb/Makefile.dist @@ -0,0 +1,351 @@ +/* This file should be run through the C preprocessor by config.gdb + to produce the Makefile. */ + +/* System V: + If your system has a broken alloca(), define ALLOCA & ALLOCA1 below. + Also, 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 ". Possibly regex.h also. */ + +/* M_CFLAGS, if defined, has system-dependent CFLAGS. */ +#if !defined(M_CFLAGS) +#define M_CFLAGS +#endif + +CFLAGS = -g -I. ${HAVE_VPRINTF_DEFINE} M_CFLAGS +/* CFLAGS = -I. -g -pg ${HAVE_VPRINTF_DEFINE} */ +/* 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 */ +#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 + +PINSNS = gld-pinsn.c i386-pinsn.c sparc-pinsn.c vax-pinsn.c m68k-pinsn.c \ + ns32k-pinsn.c convex-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 + +MFILES = m-hp9k320.h m-hp300bsd.h m-i386.h m-i386gas.h \ + m-i386-sysv3.2.h m-i386gas-sysv3.2.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 + +/* 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 \ + 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= + +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 +/* This did not work-- -Usparc became "-Usparc" became "-Usparc. + Or something like that. */ +/* $(CC) -E >Makefile tmp.c $(MD) "-DM_MAKEDEFINE=\"$(MD)\"" */ + $(CC) -E >Makefile tmp.c $(MD) "-DM_MAKEDEFINE=$(MD)" + -rm tmp.c + +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; fi + compress gdb.tar + +clean: + rm -f ${OBS} ${TSOBS} ${NTSOBS} ${OBSTACK} ${REGEX} ${GNU_MALLOC} + rm -f init.c init.o + 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}" "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 + diff --git a/gdb/Projects b/gdb/Projects new file mode 100644 index 0000000000..f38f6c74e9 --- /dev/null +++ b/gdb/Projects @@ -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: diff --git a/gdb/RCS/Makefile,v b/gdb/RCS/Makefile,v deleted file mode 100644 index fd71c1c385..0000000000 --- a/gdb/RCS/Makefile,v +++ /dev/null @@ -1,367 +0,0 @@ -head 1.4; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.4 -date 89.03.27.21.28.33; author gnu; state Exp; -branches ; -next 1.3; - -1.3 -date 89.03.27.18.33.31; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.03.13.19.02.58; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.09.03.15.53; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.4 -log -@More general support for ALLOCA and other local library routines; -other minor cleanup. -@ -text -@# On HPUX, you need to add -Ihp-include to CFLAGS. -# The headers in the directory hp-include override system headers -# and tell GDB to use BSD executable file format. -# You must also define REGEX & REGEX1 below and ALLOCA & ALLOCA1 (get -# alloca.c from the emacs distribution) to the CLIBS. -# If you compile GDB with GCC on HPUX, you must make sure that the "nm" used -# in "munch" is GNU's nm. This is because gcc uses a different .o -# file format than the native HPUX compiler. - -# On USG (System V) machines, you must make sure to setup REGEX & -# REGEX1 to point at regex.o and use the USG version of CLIBS. -# If your system has a broken alloca() -- most do -- then get -# alloca.c from the GNU Emacs distribution and set ALLOCA & ALLOCA1. -# Also, 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. - -# On Sunos 4.0 machines, make sure to compile *without* shared -# libraries if you want to run gdb on itself. Make sure to compile -# any program on which you want to run gdb without shared libraries. - -# 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 will be -# incorrectly compiled. The "fixincludes" script in the gcc -# distribution will probably fix your include files up. - -CC=cc -SHELL=/bin/sh - -# Set this up with gcc if you have gnu ld and the loader will print out -# line numbers for undefinded refs. -CC-LD=${CC} - -# -I. for "#include ". Possibly regex.h also. -#CFLAGS = -g -pg -I. -O -CFLAGS = -I. -g -#LDFLAGS = -pg -g -LDFLAGS = -g - -# 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 system is missing alloca(), or, more likely, it's there but it -# doesn't work, define ALLOCA and ALLOCA1. -OBSTACK = obstack.o -OBSTACK1 = obstack.o -REGEX = regex.o -REGEX1 = regex.o -ALLOCA = alloca.o -ALLOCA1 = alloca.o -ADD_FILES = $(OBSTACK) $(REGEX) $(ALLOCA) $(GNU_MALLOC) -ADD_DEPS = $(OBSTACK1) $(REGEX1) $(ALLOCA1) $(GNU_MALLOC) - -# -# 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 = -#MALLOC_FLAGS = ${CFLAGS} -Drcheck -Dbotch=fatal -DMSTATS - -# for BSD -CLIBS = $(ADD_FILES) -# for USG -#CLIBS= $(ADD_FILES) -lPW - -SFILES = blockframe.c breakpoint.c coffread.c command.c core.c dbxread.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 = convex-dep.c umax-dep.c gould-dep.c default-dep.c sun3-dep.c \ - sparc-dep.c hp9k320-dep.c news-dep.c i386-dep.c - -PINSNS = gld-pinsn.c i386-pinsn.c sparc-pinsn.c vax-pinsn.c m68k-pinsn.c \ - ns32k-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 - -MFILES = m-hp9k320.h m-i386.h m-i386gas.h m-isi.h m-merlin.h m-news.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 - -POSSLIBS = obstack.h obstack.c regex.c regex.h malloc.c - -TESTS = testbpt.c testfun.c testrec.c testreg.c testregs.c - -OTHERS = Makefile createtags munch config.gdb ChangeLog README TAGS \ - gdb.texinfo .gdbinit COPYING expread.tab.c stab.def hp-include - -TAGFILES = ${SFILES} ${DEPFILES} ${PINSNS} ${HFILES} ${OPCODES} ${MFILES} \ - ${POSSLIBS} -TARFILES = ${TAGFILES} ${OTHERS} - -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 - -TSOBS = core.o inflow.o dep.o - -NTSOBS = standalone.o - -TSSTART = /lib/crt0.o - -NTSSTART = kdb-start.o - -gdb : $(OBS) $(TSOBS) $(ADD_DEPS) - -rm -f init.c - ./munch $(OBS) $(TSOBS) > init.c - ${CC-LD} $(LDFLAGS) -o gdb init.c $(OBS) $(TSOBS) $(CLIBS) - -xgdb : $(OBS) $(TSOBS) xgdb.o $(ADD_DEPS) - -rm -f init.c - ./munch $(OBS) $(TSOBS) xgdb.o > init.c - $(CC-LD) $(LDFLAGS) -o xgdb init.c $(OBS) $(TSOBS) xgdb.o \ - -lXaw -lXt -lX11 $(CLIBS) - -kdb : $(NTSSTART) $(OBS) $(NTSOBS) $(ADD_DEPS) - -rm -f init.c - ./munch $(OBS) $(NTSOBS) > init.c - $(CC-LD) $(LDFLAGS) -c init.c $(CLIBS) - ld -o kdb $(NTSSTART) $(OBS) $(NTSOBS) init.o -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 - tar chf gdb.tar dist-gdb - rm -rf dist-gdb - -gdb.tar.Z: gdb.tar - compress gdb.tar - -clean: - -rm -f ${OBS} ${TSOBS} ${NTSOBS} ${OBSTACK} ${REGEX} - -rm -f init.c init.o - -rm -f gdb - -realclean: clean - -rm -f expread.tab.c tags TAGS - -xgdb.o : xgdb.c defs.h param.h symtab.h frame.h - $(CC) -c $(CFLAGS) xgdb.c -o $@@ - -expread.tab.c : expread.y - @@echo 'Expect 101 shift/reduce conflicts and 1 reduce/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 - -# -# Only useful if you are using the gnu malloc routines. -# -malloc.o : malloc.c - ${CC} -c ${MALLOC_FLAGS} malloc.c - -# -# dep.o depends on ALL the dep files since we don't know which one -# is really being used. -# -dep.o : ${DEPFILES} defs.h param.h frame.h inferior.h obstack.h \ - a.out.encap.h - -# pinsn.o depends on ALL the opcode printers -# since we don't know which one is really being used. -pinsn.o : ${PINSNS} defs.h param.h symtab.h obstack.h symseg.h frame.h \ - ${OPCODES} - -# -# 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. -# -blockframe.o : defs.h param.h symtab.h obstack.h symseg.h frame.h -breakpoint.o : defs.h param.h symtab.h obstack.h symseg.h frame.h -coffread.o : defs.h param.h -command.o : command.h defs.h -core.o : defs.h param.h a.out.encap.h -dbxread.o : param.h 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 symtab.h obstack.h symseg.h value.h expression.h -expprint.o : defs.h symtab.h obstack.h symseg.h param.h expression.h -findvar.o : defs.h param.h symtab.h obstack.h symseg.h frame.h value.h -infcmd.o : defs.h param.h symtab.h obstack.h symseg.h frame.h inferior.h \ - environ.h value.h -inflow.o : defs.h param.h frame.h inferior.h -infrun.o : defs.h param.h symtab.h obstack.h symseg.h frame.h inferior.h \ - wait.h -kdb-start.o : defs.h param.h -main.o : defs.h command.h param.h -malloc.o : getpagesize.h -obstack.o : obstack.h -printcmd.o : defs.h param.h frame.h symtab.h obstack.h symseg.h value.h \ - expression.h -regex.o : regex.h -remote.o : defs.h param.h frame.h inferior.h wait.h -source.o : defs.h symtab.h obstack.h symseg.h param.h -stack.o : defs.h param.h symtab.h obstack.h symseg.h frame.h -standalone.o : defs.h param.h 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 obstack.h -utils.o : defs.h param.h -valarith.o : defs.h param.h symtab.h obstack.h symseg.h value.h expression.h -valops.o : defs.h param.h symtab.h obstack.h symseg.h value.h frame.h \ - inferior.h -valprint.o : defs.h param.h symtab.h obstack.h symseg.h value.h -values.o : defs.h param.h 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 -@ - - -1.3 -log -@A/UX changes. Use cc, use local regex.o, use local alloca.o -@ -text -@d4 2 -a5 2 -# You must also define REGEX & REGEX1 below and add alloca.o (from -# the emacs distribution) to the CLIBS. -d12 2 -d26 2 -a27 1 -# incorrectly compiled. -d46 2 -d52 4 -d70 1 -a70 1 -#CLIBS = $(OBSTACK) $(REGEX) $(GNU_MALLOC) -d72 1 -a72 1 -CLIBS= $(OBSTACK) $(REGEX) $(GNU_MALLOC) alloca.o -d122 1 -a122 1 -gdb : $(OBS) $(TSOBS) $(OBSTACK1) $(REGEX1) ${GNU_MALLOC} -d127 1 -a127 1 -xgdb : $(OBS) $(TSOBS) xgdb.o $(OBSTACK1) $(REGEX1) ${GNU_MALLOC} -d133 1 -a133 1 -kdb : $(NTSSTART) $(OBS) $(NTSOBS) $(OBSTACK1) $(REGEX1) ${GNU_MALLOC} -d161 1 -a161 1 - -rm -f init.c -d165 1 -a165 1 - -rm -f expread.tab.c -@ - - -1.2 -log -@All rm's to rm -f's. -@ -text -@d26 1 -a26 1 -CC=gcc -d45 2 -a46 2 -REGEX = -REGEX1 = -d61 1 -a61 1 -CLIBS = $(OBSTACK) $(REGEX) $(GNU_MALLOC) -d63 1 -a63 1 -#CLIBS= $(OBSTACK) $(REGEX) $(GNU_MALLOC) -lPW -@ - - -1.1 -log -@Initial revision -@ -text -@d26 1 -a26 1 -CC=/bin/cc -d114 1 -a114 1 - -rm init.c -d119 1 -a119 1 - -rm init.c -d125 1 -a125 1 - -rm init.c -d151 3 -a153 3 - -rm ${OBS} ${TSOBS} ${NTSOBS} ${OBSTACK} ${REGEX} - -rm init.c - -rm gdb -d156 1 -a156 1 - -rm expread.tab.c -@ diff --git a/gdb/RCS/blockframe.c,v b/gdb/RCS/blockframe.c,v deleted file mode 100644 index fc64e2f1e8..0000000000 --- a/gdb/RCS/blockframe.c,v +++ /dev/null @@ -1,606 +0,0 @@ -head 1.3; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.3 -date 89.03.16.21.09.52; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.02.09.23.21.53; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.09.15.15.16; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.3 -log -@Don't stop the stack trace until the "next frame pointer" is zero. -@ -text -@/* Get info from stack frames; - convert between frames, blocks, functions and pc values. - Copyright (C) 1986, 1987, 1988 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! -*/ - -#include "defs.h" -#include "param.h" -#include "symtab.h" -#include "frame.h" - -/* Address of end of first object file. - This file is assumed to be a startup file - and frames with pc's inside it - are treated as nonexistent. */ - -CORE_ADDR first_object_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); -} - -/* - * 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; -} - -/* Return a structure containing various interesting information - about the frame that called NEXT_FRAME. */ - -struct frame_info * -get_prev_frame_info (next_frame) - FRAME next_frame; -{ - FRAME_ADDR address; - struct frame_info *prev; - int fromleaf = 0; - - /* If we are within "start" right now, don't go any higher. */ - /* This truncates stack traces of things at sigtramp() though, - because sigtramp() doesn't have a normal return PC, it has - garbage or a small value (seen: 3) in the return PC slot. - It's VITAL to see where the signal occurred, so punt this. */ -#if 0 - if (next_frame && next_frame->pc < first_object_file_end) - return 0; -#endif - - /* 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) - error ("No frame is currently selected."); - - return current_frame; - } - else - { - /* If we have the prev one, return it */ - if (next_frame->prev) - return next_frame->prev; - - /* There is a questionable, but probably always correct - assumption being made here. The assumption is that if - functions on a specific machine has a FUNCTION_START_OFFSET, - then this is used by the function call instruction for some - purpose. If the function call instruction has this much hair - in it, it probably also sets up the frame pointer - automatically (ie. we'll never have what I am calling a - "leaf node", one which shares a frame pointer with it's - calling function). This is true on a vax. The only other - way to find this out would be to setup a seperate macro - "FUNCTION_HAS_FRAME_POINTER", which would often be equivalent - to SKIP_PROLOGUE modifying a pc value. */ - -#if FUNCTION_START_OFFSET == 0 - if (!(next_frame->next)) - { - /* Innermost */ - CORE_ADDR func_start, after_prologue; - - func_start = (get_pc_function_start (next_frame->pc) + - FUNCTION_START_OFFSET); - after_prologue = func_start; - SKIP_PROLOGUE (after_prologue); - if (after_prologue == func_start) - { - fromleaf = 1; - 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. */ - address = FRAME_CHAIN (next_frame); - if (!FRAME_CHAIN_VALID (address, next_frame)) - return 0; - - /* If frame has a caller, combine the chain pointer and - the frame's own address to get the address of the caller. */ - address = FRAME_CHAIN_COMBINE (address, next_frame); - } - } - - 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; -{ -#if 1 - FRAME_FIND_SAVED_REGS (frame_info_addr, *saved_regs_addr); -#else - { - register int regnum; - register int regmask; - register CORE_ADDR next_addr; - register CORE_ADDR pc; - int nextinsn; - bzero (&*saved_regs_addr, sizeof *saved_regs_addr); - if ((frame_info_addr)->pc >= ((frame_info_addr)->frame - - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4) - && (frame_info_addr)->pc <= (frame_info_addr)->frame) - { - next_addr = (frame_info_addr)->frame; - pc = (frame_info_addr)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; - } - else - { - pc = get_pc_function_start ((frame_info_addr)->pc); - /* Verify we have a link a6 instruction next; - if not we lose. If we win, find the address above the saved - regs using the amount of storage from the link instruction. */ - if (044016 == read_memory_integer (pc, 2)) - { - next_addr = (frame_info_addr)->frame + read_memory_integer (pc += 2, 4); - pc += 4; - } - else if (047126 == read_memory_integer (pc, 2)) - { - next_addr = (frame_info_addr)->frame + read_memory_integer (pc += 2, 2); - pc+=2; - } - else goto lose; - - /* If have an addal #-n, sp next, adjust next_addr. */ - if ((0177777 & read_memory_integer (pc, 2)) == 0157774) - { - next_addr += read_memory_integer (pc += 2, 4); - pc += 4; - } - } - /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ - regmask = read_memory_integer (pc + 2, 2); - - /* But before that can come an fmovem. Check for it. */ - nextinsn = 0xffff & read_memory_integer (pc, 2); - if (0xf227 == nextinsn - && (regmask & 0xff00) == 0xe000) - { - pc += 4; /* Regmask's low bit is for register fp7, the first pushed */ - for (regnum = FP0_REGNUM + 7; - regnum >= FP0_REGNUM; - regnum--, regmask >>= 1) - if (regmask & 1) - (*saved_regs_addr).regs[regnum] = (next_addr -= 12); - regmask = read_memory_integer (pc + 2, 2); - } - if (0044327 == read_memory_integer (pc, 2)) - { - pc += 4; /* Regmask's low bit is for register 0, the first written */ - for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) - if (regmask & 1) - (*saved_regs_addr).regs[regnum] = (next_addr += 4) - 4; - } - else if (0044347 == read_memory_integer (pc, 2)) - { pc += 4; /* Regmask's low bit is for register 15, the first pushed */ - for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) - if (regmask & 1) - (*saved_regs_addr).regs[regnum] = (next_addr -= 4); } - else if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2))) - { regnum = 0xf & read_memory_integer (pc, 2); pc += 2; - (*saved_regs_addr).regs[regnum] = (next_addr -= 4); } - /* fmovemx to index of sp may follow. */ - regmask = read_memory_integer (pc + 2, 2); - nextinsn = 0xffff & read_memory_integer (pc, 2); - if (0xf236 == nextinsn - && (regmask & 0xff00) == 0xf000) - { - pc += 10; /* Regmask's low bit is for register fp0, the first written */ - for (regnum = FP0_REGNUM + 7; - regnum >= FP0_REGNUM; - regnum--, regmask >>= 1) - if (regmask & 1) - (*saved_regs_addr).regs[regnum] = (next_addr += 12) - 12; - regmask = read_memory_integer (pc + 2, 2); - } - /* clrw -(sp); movw ccr,-(sp) may follow. */ - if (0x426742e7 == read_memory_integer (pc, 4)) - (*saved_regs_addr).regs[PS_REGNUM] = (next_addr -= 4); - lose: ; - (*saved_regs_addr).regs[SP_REGNUM] = (frame_info_addr)->frame + 8; - (*saved_regs_addr).regs[FP_REGNUM] = (frame_info_addr)->frame; - (*saved_regs_addr).regs[PC_REGNUM] = (frame_info_addr)->frame + 4; - } -#endif -} - -/* 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; - - fi = get_frame_info (frame); - return block_for_pc (fi->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) - { - 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); -} - -/* 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. */ - - /* 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; - - 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); -} -@ - - -1.2 -log -@Avoid fatal error for simple user error -@ -text -@d142 5 -d149 1 -@ - - -1.1 -log -@Initial revision -@ -text -@d152 1 -a152 1 - fatal ("get_prev_frame_info: Called before cache primed"); -@ diff --git a/gdb/RCS/coffread.c,v b/gdb/RCS/coffread.c,v deleted file mode 100644 index 9c45395c53..0000000000 --- a/gdb/RCS/coffread.c,v +++ /dev/null @@ -1,2047 +0,0 @@ -head 1.5; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.5 -date 89.03.27.18.38.25; author gnu; state Exp; -branches ; -next 1.4; - -1.4 -date 89.03.27.18.37.20; author gnu; state Exp; -branches ; -next 1.3; - -1.3 -date 89.03.27.18.36.15; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.02.10.01.38.05; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.10.01.32.45; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.5 -log -@Remake A/UX changes. -@ -text -@/* Read coff symbol tables and convert to internal format, for GDB. - Design and support routines derived from dbxread.c, and UMAX COFF - specific routines written 9/1/87 by David D. Johnson, Brown University. - Revised 11/27/87 ddj@@cs.brown.edu - Copyright (C) 1987, 1988, 1989 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! -*/ - -#include "defs.h" -#include "param.h" -#ifdef COFF_FORMAT -#include "symtab.h" - -#ifdef USG -#include -#include -#endif - -#include -#include -#include -#include -#include - -/* Avoid problems with A/UX predefine */ -#undef aux - -static void add_symbol_to_list (); -static void read_coff_symtab (); -static void patch_opaque_types (); -static struct type *decode_function_type (); -static struct type *decode_type (); -static struct type *decode_base_type (); -static struct type *read_enum_type (); -static struct type *read_struct_type (); -static void finish_block (); -static struct blockvector *make_blockvector (); -static struct symbol *process_coff_symbol (); -static int init_stringtab (); -static void free_stringtab (); -static char *getfilename (); -static char *getsymname (); -static int init_lineno (); -static void enter_linenos (); - -extern void free_all_symtabs (); -extern void free_all_psymtabs (); - - -/* Name of source file whose symbol data we are now processing. - This comes from a symbol named ".file". */ - -static char *last_source_file; - -/* Core address of start and end of text of current source file. - This comes from a ".text" symbol where x_nlinno > 0. */ - -static CORE_ADDR cur_src_start_addr; -static CORE_ADDR cur_src_end_addr; - -/* End of the text segment of the executable file, - as found in the symbol _etext. */ - -static CORE_ADDR end_of_text_addr; - -/* The addresses of the symbol table stream and number of symbols - of the object file we are reading (as copied into core). */ - -static FILE *nlist_stream_global; -static int nlist_nsyms_global; - -/* The file and text section headers of the symbol file */ - -static FILHDR file_hdr; -static SCNHDR text_hdr; - -/* The index in the symbol table of the last coff symbol that was processed. */ - -static int symnum; - -/* Vector of types defined so far, indexed by their coff symnum. */ - -static struct typevector *type_vector; - -/* Number of elements allocated for type_vector currently. */ - -static int type_vector_length; - -/* Vector of line number information. */ - -static struct linetable *line_vector; - -/* Index of next entry to go in line_vector_index. */ - -static int line_vector_index; - -/* Last line number recorded in the line vector. */ - -static int prev_line_number; - -/* Number of elements allocated for line_vector currently. */ - -static int line_vector_length; - -/* Chain of typedefs of pointers to empty struct/union types. - They are chained thru the SYMBOL_VALUE. */ - -#define HASHSIZE 127 -static struct symbol *opaque_type_chain[HASHSIZE]; - -/* Record the symbols defined for each context in a list. - We don't create a struct block for the context until we - know how long to make it. */ - -struct pending -{ - struct pending *next; - struct symbol *symbol; -}; - -/* Here are the three lists that symbols are put on. */ - -struct pending *file_symbols; /* static at top level, and types */ - -struct pending *global_symbols; /* global functions and variables */ - -struct pending *local_symbols; /* everything local to lexical context */ - -/* List of unclosed lexical contexts - (that will become blocks, eventually). */ - -struct context_stack -{ - struct context_stack *next; - struct pending *locals; - struct pending_block *old_blocks; - struct symbol *name; - CORE_ADDR start_addr; - int depth; -}; - -struct context_stack *context_stack; - -/* Nonzero if within a function (so symbols should be local, - if nothing says specifically). */ - -int within_function; - -/* List of blocks already made (lexical contexts already closed). - This is used at the end to make the blockvector. */ - -struct pending_block -{ - struct pending_block *next; - struct block *block; -}; - -struct pending_block *pending_blocks; - -extern CORE_ADDR first_object_file_end; /* From blockframe.c */ - -/* File name symbols were loaded from. */ - -static char *symfile; - -/* Look up a coff type-number index. Return the address of the slot - where the type for that index is stored. - The type-number is in INDEX. - - This can be used for finding the type associated with that index - or for associating a new type with the index. */ - -static struct type ** -coff_lookup_type (index) - register int index; -{ - if (index >= type_vector_length) - { - int old_vector_length = type_vector_length; - - type_vector_length *= 2; - if (type_vector_length < index) { - type_vector_length = index * 2; - } - type_vector = (struct typevector *) - xrealloc (type_vector, sizeof (struct typevector) - + type_vector_length * sizeof (struct type *)); - bzero (&type_vector->type[ old_vector_length ], - (type_vector_length - old_vector_length) * sizeof(struct type *)); - } - return &type_vector->type[index]; -} - -/* Make sure there is a type allocated for type number index - and return the type object. - This can create an empty (zeroed) type object. */ - -static struct type * -coff_alloc_type (index) - int index; -{ - register struct type **type_addr = coff_lookup_type (index); - register struct type *type = *type_addr; - - /* If we are referring to a type not known at all yet, - allocate an empty type for it. - We will fill it in later if we find out how. */ - if (type == 0) - { - type = (struct type *) obstack_alloc (symbol_obstack, - sizeof (struct type)); - bzero (type, sizeof (struct type)); - *type_addr = type; - } - return type; -} - -/* maintain the lists of symbols and blocks */ - -/* Add a symbol to one of the lists of symbols. */ -static void -add_symbol_to_list (symbol, listhead) - struct symbol *symbol; - struct pending **listhead; -{ - register struct pending *link - = (struct pending *) xmalloc (sizeof (struct pending)); - - link->next = *listhead; - link->symbol = symbol; - *listhead = link; -} - -/* Take one of the lists of symbols and make a block from it. - Put the block on the list of pending blocks. */ - -static void -finish_block (symbol, listhead, old_blocks, start, end) - struct symbol *symbol; - struct pending **listhead; - struct pending_block *old_blocks; - CORE_ADDR start, end; -{ - register struct pending *next, *next1; - register struct block *block; - register struct pending_block *pblock; - struct pending_block *opblock; - register int i; - - /* Count the length of the list of symbols. */ - - for (next = *listhead, i = 0; next; next = next->next, i++); - - block = (struct block *) - obstack_alloc (symbol_obstack, sizeof (struct block) + (i - 1) * sizeof (struct symbol *)); - - /* Copy the symbols into the block. */ - - BLOCK_NSYMS (block) = i; - for (next = *listhead; next; next = next->next) - BLOCK_SYM (block, --i) = next->symbol; - - BLOCK_START (block) = start; - BLOCK_END (block) = end; - BLOCK_SUPERBLOCK (block) = 0; /* Filled in when containing block is made */ - - /* Put the block in as the value of the symbol that names it. */ - - if (symbol) - { - SYMBOL_BLOCK_VALUE (symbol) = block; - BLOCK_FUNCTION (block) = symbol; - } - else - BLOCK_FUNCTION (block) = 0; - - /* Now free the links of the list, and empty the list. */ - - for (next = *listhead; next; next = next1) - { - next1 = next->next; - free (next); - } - *listhead = 0; - - /* Install this block as the superblock - of all blocks made since the start of this scope - that don't have superblocks yet. */ - - opblock = 0; - for (pblock = pending_blocks; pblock != old_blocks; pblock = pblock->next) - { - if (BLOCK_SUPERBLOCK (pblock->block) == 0) - BLOCK_SUPERBLOCK (pblock->block) = block; - opblock = pblock; - } - - /* Record this block on the list of all blocks in the file. - Put it after opblock, or at the beginning if opblock is 0. - This puts the block in the list after all its subblocks. */ - - pblock = (struct pending_block *) xmalloc (sizeof (struct pending_block)); - pblock->block = block; - if (opblock) - { - pblock->next = opblock->next; - opblock->next = pblock; - } - else - { - pblock->next = pending_blocks; - pending_blocks = pblock; - } -} - -static struct blockvector * -make_blockvector () -{ - register struct pending_block *next, *next1; - register struct blockvector *blockvector; - register int i; - - /* Count the length of the list of blocks. */ - - for (next = pending_blocks, i = 0; next; next = next->next, i++); - - blockvector = (struct blockvector *) - obstack_alloc (symbol_obstack, sizeof (struct blockvector) + (i - 1) * sizeof (struct block *)); - - /* Copy the blocks into the blockvector. - This is done in reverse order, which happens to put - the blocks into the proper order (ascending starting address). - finish_block has hair to insert each block into the list - after its subblocks in order to make sure this is true. */ - - BLOCKVECTOR_NBLOCKS (blockvector) = i; - for (next = pending_blocks; next; next = next->next) - BLOCKVECTOR_BLOCK (blockvector, --i) = next->block; - - /* Now free the links of the list, and empty the list. */ - - for (next = pending_blocks; next; next = next1) - { - next1 = next->next; - free (next); - } - pending_blocks = 0; - - return blockvector; -} - -/* Manage the vector of line numbers. */ - -static -record_line (line, pc) - int line; - CORE_ADDR pc; -{ - struct linetable_entry *e; - /* Make sure line vector is big enough. */ - - if (line_vector_index + 2 >= line_vector_length) - { - line_vector_length *= 2; - line_vector = (struct linetable *) - xrealloc (line_vector, sizeof (struct linetable) - + (line_vector_length - * sizeof (struct linetable_entry))); - } - - e = line_vector->item + line_vector_index++; - e->line = line; e->pc = pc; -} - -/* Start a new symtab for a new source file. - This is called when a COFF ".file" symbol is seen; - it indicates the start of data for one original source file. */ - -static void -start_symtab () -{ - file_symbols = 0; - global_symbols = 0; - context_stack = 0; - within_function = 0; - last_source_file = 0; - - /* Initialize the source file information for this file. */ - - line_vector_index = 0; - line_vector_length = 1000; - prev_line_number = -2; /* Force first line number to be explicit */ - line_vector = (struct linetable *) - xmalloc (sizeof (struct linetable) - + line_vector_length * sizeof (struct linetable_entry)); -} - -/* Save the vital information for use when closing off the current file. - NAME is the file name the symbols came from, START_ADDR is the first - text address for the file, and SIZE is the number of bytes of text. */ - -static void -complete_symtab (name, start_addr, size) - char *name; - CORE_ADDR start_addr; - unsigned int size; -{ - last_source_file = savestring (name, strlen (name)); - cur_src_start_addr = start_addr; - cur_src_end_addr = start_addr + size; -} - -/* Finish the symbol definitions for one main source file, - close off all the lexical contexts for that file - (creating struct block's for them), then make the - struct symtab for that file and put it in the list of all such. */ - -static void -end_symtab () -{ - register struct symtab *symtab; - register struct context_stack *cstk; - register struct blockvector *blockvector; - register struct linetable *lv; - - /* Finish the lexical context of the last function in the file. */ - - if (context_stack) - { - cstk = context_stack; - context_stack = 0; - /* Make a block for the local symbols within. */ - finish_block (cstk->name, &local_symbols, cstk->old_blocks, - cstk->start_addr, cur_src_end_addr); - free (cstk); - } - - /* Ignore a file that has no functions with real debugging info. */ - if (pending_blocks == 0 && file_symbols == 0 && global_symbols == 0) - { - free (line_vector); - line_vector = 0; - line_vector_length = -1; - last_source_file = 0; - return; - } - - /* Create the two top-level blocks for this file. */ - finish_block (0, &file_symbols, 0, cur_src_start_addr, cur_src_end_addr); - finish_block (0, &global_symbols, 0, cur_src_start_addr, cur_src_end_addr); - - /* Create the blockvector that points to all the file's blocks. */ - blockvector = make_blockvector (); - - /* Now create the symtab object for this source file. */ - symtab = (struct symtab *) xmalloc (sizeof (struct symtab)); - symtab->free_ptr = 0; - - /* Fill in its components. */ - symtab->blockvector = blockvector; - symtab->free_code = free_linetable; - symtab->filename = last_source_file; - lv = line_vector; - lv->nitems = line_vector_index; - symtab->linetable = (struct linetable *) - xrealloc (lv, (sizeof (struct linetable) - + lv->nitems * sizeof (struct linetable_entry))); - symtab->nlines = 0; - symtab->line_charpos = 0; - - /* Link the new symtab into the list of such. */ - symtab->next = symtab_list; - symtab_list = symtab; - - /* Reinitialize for beginning of new file. */ - line_vector = 0; - line_vector_length = -1; - last_source_file = 0; -} - -/* Accumulate the misc functions in bunches of 127. - At the end, copy them all into one newly allocated structure. */ - -#define MISC_BUNCH_SIZE 127 - -struct misc_bunch -{ - struct misc_bunch *next; - struct misc_function contents[MISC_BUNCH_SIZE]; -}; - -/* Bunch currently being filled up. - The next field points to chain of filled bunches. */ - -static struct misc_bunch *misc_bunch; - -/* Number of slots filled in current bunch. */ - -static int misc_bunch_index; - -/* Total number of misc functions recorded so far. */ - -static int misc_count; - -static void -init_misc_functions () -{ - misc_count = 0; - misc_bunch = 0; - misc_bunch_index = MISC_BUNCH_SIZE; -} - -static void -record_misc_function (name, address) - char *name; - CORE_ADDR address; -{ - register struct misc_bunch *new; - - if (misc_bunch_index == MISC_BUNCH_SIZE) - { - new = (struct misc_bunch *) xmalloc (sizeof (struct misc_bunch)); - misc_bunch_index = 0; - new->next = misc_bunch; - misc_bunch = new; - } - misc_bunch->contents[misc_bunch_index].name = savestring (name, strlen (name)); - misc_bunch->contents[misc_bunch_index].address = address; - misc_bunch_index++; - misc_count++; -} - -/* if we see a function symbol, we do record_misc_function. - * however, if it turns out the next symbol is '.bf', then - * we call here to undo the misc definition - */ -static void -unrecord_misc_function () -{ - if (misc_bunch_index == 0) - error ("Internal error processing symbol table, at symbol %d.", - symnum); - misc_bunch_index--; - misc_count--; -} - - -static int -compare_misc_functions (fn1, fn2) - struct misc_function *fn1, *fn2; -{ - /* Return a signed result based on unsigned comparisons - so that we sort into unsigned numeric order. */ - if (fn1->address < fn2->address) - return -1; - if (fn1->address > fn2->address) - return 1; - return 0; -} - -static void -discard_misc_bunches () -{ - register struct misc_bunch *next; - - while (misc_bunch) - { - next = misc_bunch->next; - free (misc_bunch); - misc_bunch = next; - } -} - -static void -condense_misc_bunches () -{ - register int i, j; - register struct misc_bunch *bunch; -#ifdef NAMES_HAVE_UNDERSCORE - int offset = 1; -#else - int offset = 0; -#endif - - misc_function_vector - = (struct misc_function *) - xmalloc (misc_count * sizeof (struct misc_function)); - - j = 0; - bunch = misc_bunch; - while (bunch) - { - for (i = 0; i < misc_bunch_index; i++) - { - register char *tmp; - - misc_function_vector[j] = bunch->contents[i]; - tmp = misc_function_vector[j].name; - misc_function_vector[j].name = (tmp[0] == '_' ? tmp + offset : tmp); - j++; - } - bunch = bunch->next; - misc_bunch_index = MISC_BUNCH_SIZE; - } - - misc_function_count = j; - - /* Sort the misc functions by address. */ - - qsort (misc_function_vector, j, sizeof (struct misc_function), - compare_misc_functions); -} - -/* Call sort_syms to sort alphabetically - the symbols of each block of each symtab. */ - -static int -compare_symbols (s1, s2) - struct symbol **s1, **s2; -{ - /* Names that are less should come first. */ - register int namediff = strcmp (SYMBOL_NAME (*s1), SYMBOL_NAME (*s2)); - if (namediff != 0) return namediff; - /* For symbols of the same name, registers should come first. */ - return ((SYMBOL_CLASS (*s2) == LOC_REGISTER) - - (SYMBOL_CLASS (*s1) == LOC_REGISTER)); -} - -static void -sort_syms () -{ - register struct symtab *s; - register int i, nbl; - register struct blockvector *bv; - register struct block *b; - - for (s = symtab_list; s; s = s->next) - { - bv = BLOCKVECTOR (s); - nbl = BLOCKVECTOR_NBLOCKS (bv); - for (i = 0; i < nbl; i++) - { - b = BLOCKVECTOR_BLOCK (bv, i); - if (BLOCK_SHOULD_SORT (b)) - qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b), - sizeof (struct symbol *), compare_symbols); - } - } -} - -/* This is the symbol-file command. Read the file, analyze its symbols, - and add a struct symtab to symtab_list. */ - -void -symbol_file_command (name) - char *name; -{ - int desc; - int num_symbols; - int num_sections; - int symtab_offset; - extern void close (); - register int val; - struct cleanup *old_chain; - - dont_repeat (); - - if (name == 0) - { - if (symtab_list && !query ("Discard symbol table? ", 0)) - error ("Not confirmed."); - if (symfile) - free (symfile); - symfile = 0; - free_all_symtabs (); - return; - } - - if (symtab_list && !query ("Load new symbol table from \"%s\"? ", name)) - error ("Not confirmed."); - - if (symfile) - free (symfile); - symfile = 0; - - { - char *absolute_name; - - desc = openp (getenv ("PATH"), 1, name, O_RDONLY, 0, &absolute_name); - if (desc < 0) - perror_with_name (name); - else - name = absolute_name; - } - - old_chain = make_cleanup (close, desc); - make_cleanup (free_current_contents, &name); - - if ((num_symbols = read_file_hdr (desc, &file_hdr)) < 0) - error ("File \"%s\" not in executable format.", name); - - if (num_symbols == 0) - { - free_all_symtabs (); - printf ("%s does not have a symbol-table.\n", name); - fflush (stdout); - return; - } - - printf ("Reading symbol data from %s...", name); - fflush (stdout); - - /* Throw away the old symbol table. */ - - free_all_symtabs (); - free_all_psymtabs (); /* Make sure that partial_symtab_list */ - /* is 0 also. */ - - num_sections = file_hdr.f_nscns; - symtab_offset = file_hdr.f_symptr; - - if (read_section_hdr (desc, _TEXT, &text_hdr, num_sections) < 0) - error ("\"%s\": can't read text section header", name); - - /* Read the line number table, all at once. */ - - val = init_lineno (desc, text_hdr.s_lnnoptr, text_hdr.s_nlnno); - if (val < 0) - error ("\"%s\": error reading line numbers\n", name); - - /* Now read the string table, all at once. */ - - val = init_stringtab (desc, symtab_offset + num_symbols * SYMESZ); - if (val < 0) - { - free_all_symtabs (); - printf ("\"%s\": can't get string table", name); - fflush (stdout); - return; - } - make_cleanup (free_stringtab, 0); - - /* Position to read the symbol table. Do not read it all at once. */ - val = lseek (desc, (long)symtab_offset, 0); - if (val < 0) - perror_with_name (name); - - init_misc_functions (); - make_cleanup (discard_misc_bunches, 0); - - /* Now that the executable file is positioned at symbol table, - process it and define symbols accordingly. */ - - read_coff_symtab (desc, num_symbols); - - patch_opaque_types (); - - /* Sort symbols alphabetically within each block. */ - - sort_syms (); - - /* Go over the misc functions and install them in vector. */ - - condense_misc_bunches (); - - /* Don't allow char * to have a typename (else would get caddr_t.) */ - - TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0; - - /* Make a default for file to list. */ - - select_source_symtab (symtab_list); - - symfile = savestring (name, strlen (name)); - - do_cleanups (old_chain); - - printf ("done.\n"); - fflush (stdout); -} - -/* Return name of file symbols were loaded from, or 0 if none.. */ - -char * -get_sym_file () -{ - return symfile; -} - -/* Simplified internal version of coff symbol table information */ - -struct coff_symbol { - char *c_name; - int c_symnum; /* symbol number of this entry */ - int c_nsyms; /* 1 if syment only, 2 if syment + auxent */ - long c_value; - int c_sclass; - int c_secnum; - unsigned int c_type; -}; - -/* Given pointers to a symbol table in coff style exec file, - analyze them and create struct symtab's describing the symbols. - NSYMS is the number of symbols in the symbol table. - We read them one at a time using read_one_sym (). */ - -static void -read_coff_symtab (desc, nsyms) - int desc; - int nsyms; -{ - int newfd; /* Avoid multiple closes on same desc */ - FILE *stream; - register struct context_stack *new; - struct coff_symbol coff_symbol; - register struct coff_symbol *cs = &coff_symbol; - static SYMENT main_sym; - static AUXENT main_aux; - struct coff_symbol fcn_cs_saved; - static SYMENT fcn_sym_saved; - static AUXENT fcn_aux_saved; - - int num_object_files = 0; - int next_file_symnum = -1; - char *filestring; - int depth; - int fcn_first_line; - int fcn_last_line; - int fcn_start_addr; - long fcn_line_ptr; - struct cleanup *old_chain; - int fclose(); - - newfd = dup (desc); - if (newfd == -1) - fatal ("Too many open files"); - stream = fdopen (newfd, "r"); - - old_chain = make_cleanup (free_all_symtabs, 0); - make_cleanup (fclose, stream); - nlist_stream_global = stream; - nlist_nsyms_global = nsyms; - last_source_file = 0; - bzero (opaque_type_chain, sizeof opaque_type_chain); - - type_vector_length = 160; - type_vector = (struct typevector *) - xmalloc (sizeof (struct typevector) - + type_vector_length * sizeof (struct type *)); - bzero (type_vector->type, type_vector_length * sizeof (struct type *)); - - start_symtab (); - - symnum = 0; - while (symnum < nsyms) - { - QUIT; /* Make this command interruptable. */ - read_one_sym (cs, &main_sym, &main_aux); - - if (cs->c_symnum == next_file_symnum && cs->c_sclass != C_FILE) - { - CORE_ADDR last_file_end = cur_src_end_addr; - - if (last_source_file) - end_symtab (); - - start_symtab (); - complete_symtab ("_globals_", 0, first_object_file_end); - /* done with all files, everything from here on out is globals */ - } - - /* Special case for file with type declarations only, no text. */ - if (!last_source_file && cs->c_type != T_NULL && cs->c_secnum == N_DEBUG) - complete_symtab (filestring, 0, 0); - - /* Typedefs should not be treated as symbol definitions. */ - if (ISFCN (cs->c_type) && cs->c_sclass != C_TPDEF) - { - /* record as misc function. if we get '.bf' next, - * then we undo this step - */ - record_misc_function (cs->c_name, cs->c_value); - - fcn_line_ptr = main_aux.x_sym.x_fcnary.x_fcn.x_lnnoptr; - fcn_start_addr = cs->c_value; - fcn_cs_saved = *cs; - fcn_sym_saved = main_sym; - fcn_aux_saved = main_aux; - continue; - } - - switch (cs->c_sclass) - { - case C_EFCN: - case C_EXTDEF: - case C_ULABEL: - case C_USTATIC: - case C_LINE: - case C_ALIAS: - case C_HIDDEN: - printf ("Bad n_sclass = %d\n", cs->c_sclass); - break; - - case C_FILE: - /* - * c_value field contains symnum of next .file entry in table - * or symnum of first global after last .file. - */ - next_file_symnum = cs->c_value; - filestring = getfilename (&main_aux); - /* - * Complete symbol table for last object file - * containing debugging information. - */ - if (last_source_file) - { - end_symtab (); - start_symtab (); - } - num_object_files++; - break; - - case C_STAT: - if (cs->c_name[0] == '.') { - if (strcmp (cs->c_name, _TEXT) == 0) { - if (num_object_files == 1) { - /* last address of startup file */ - first_object_file_end = cs->c_value + - main_aux.x_scn.x_scnlen; - } - /* for some reason the old code didn't do - * this if this section entry had - * main_aux.x_scn.x_nlinno equal to 0 - */ - complete_symtab (filestring, cs->c_value, - main_aux.x_scn.x_scnlen); - } - /* flush rest of '.' symbols */ - break; - } - /* fall in for static symbols that don't start with '.' */ - case C_EXT: - if (cs->c_sclass == C_EXT && - cs->c_secnum == N_ABS && - strcmp (cs->c_name, _ETEXT) == 0) - end_of_text_addr = cs->c_value; - if (cs->c_type == T_NULL) { - if (cs->c_secnum <= 1) { /* text or abs */ - record_misc_function (cs->c_name, cs->c_value); - break; - } else { - cs->c_type = T_INT; - } - } - (void) process_coff_symbol (cs, &main_aux); - break; - - case C_FCN: - if (strcmp (cs->c_name, ".bf") == 0) - { - unrecord_misc_function (); - - within_function = 1; - - /* value contains address of first non-init type code */ - /* main_aux.x_sym.x_misc.x_lnsz.x_lnno - contains line number of '{' } */ - fcn_first_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno; - - new = (struct context_stack *) - xmalloc (sizeof (struct context_stack)); - new->depth = depth = 0; - new->next = 0; - context_stack = new; - new->locals = 0; - new->old_blocks = pending_blocks; - new->start_addr = fcn_start_addr; - fcn_cs_saved.c_name = getsymname (&fcn_sym_saved); - new->name = process_coff_symbol (&fcn_cs_saved, - &fcn_aux_saved); - } - else if (strcmp (cs->c_name, ".ef") == 0) - { - /* the value of .ef is the address of epilogue code; - * not useful for gdb - */ - /* { main_aux.x_sym.x_misc.x_lnsz.x_lnno - contains number of lines to '}' */ - fcn_last_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno; - enter_linenos (fcn_line_ptr, fcn_first_line, fcn_last_line); - new = context_stack; - - if (new == 0) - error ("Invalid symbol data; .bf/.ef/.bb/.eb symbol mismatch, at symbol %d.", - symnum); - - finish_block (new->name, &local_symbols, new->old_blocks, - new->start_addr, - fcn_cs_saved.c_value + - fcn_aux_saved.x_sym.x_misc.x_fsize); - context_stack = 0; - within_function = 0; - free (new); - } - break; - - case C_BLOCK: - if (strcmp (cs->c_name, ".bb") == 0) - { - new = (struct context_stack *) - xmalloc (sizeof (struct context_stack)); - depth++; - new->depth = depth; - new->next = context_stack; - context_stack = new; - new->locals = local_symbols; - new->old_blocks = pending_blocks; - new->start_addr = cs->c_value; - new->name = 0; - local_symbols = 0; - } - else if (strcmp (cs->c_name, ".eb") == 0) - { - new = context_stack; - if (new == 0 || depth != new->depth) - error ("Invalid symbol data: .bb/.eb symbol mismatch at symbol %d.", - symnum); - if (local_symbols && context_stack->next) - { - /* Make a block for the local symbols within. */ - finish_block (0, &local_symbols, new->old_blocks, - new->start_addr, cs->c_value); - } - depth--; - local_symbols = new->locals; - context_stack = new->next; - free (new); - } - break; - - default: - (void) process_coff_symbol (cs, &main_aux); - break; - } - } - - if (last_source_file) - end_symtab (); - fclose (stream); - discard_cleanups (old_chain); -} - -/* Routines for reading headers and symbols from executable. */ - -/* Read COFF file header, check magic number, - and return number of symbols. */ -read_file_hdr (chan, file_hdr) - int chan; - FILHDR *file_hdr; -{ - lseek (chan, 0L, 0); - if (myread (chan, (char *)file_hdr, FILHSZ) < 0) - return -1; - - switch (file_hdr->f_magic) - { -#ifdef NS32GMAGIC - case NS32GMAGIC: - case NS32SMAGIC: -#endif -#ifdef I386MAGIC - case I386MAGIC: -#endif - return file_hdr->f_nsyms; - - - default: -#ifdef BADMAG - if (BADMAG(file_hdr)) - return -1; - else - return file_hdr->f_nsyms; -#else - return -1; -#endif - } -} - -read_aout_hdr (chan, aout_hdr, size) - int chan; - AOUTHDR *aout_hdr; - int size; -{ - lseek (chan, (long)FILHSZ, 0); - if (size != sizeof (AOUTHDR)) - return -1; - if (myread (chan, (char *)aout_hdr, size) != size) - return -1; - return 0; -} - -read_section_hdr (chan, section_name, section_hdr, nsects) - register int chan; - register char *section_name; - SCNHDR *section_hdr; - register int nsects; -{ - register int i; - - if (lseek (chan, FILHSZ + sizeof (AOUTHDR), 0) < 0) - return -1; - - for (i = 0; i < nsects; i++) - { - if (myread (chan, (char *)section_hdr, SCNHSZ) < 0) - return -1; - if (strncmp (section_hdr->s_name, section_name, 8) == 0) - return 0; - } - return -1; -} - -read_one_sym (cs, sym, aux) - register struct coff_symbol *cs; - register SYMENT *sym; - register AUXENT *aux; -{ - cs->c_symnum = symnum; - fread ((char *)sym, SYMESZ, 1, nlist_stream_global); - cs->c_nsyms = (sym->n_numaux & 0xff) + 1; - if (cs->c_nsyms == 2) - { - /* doc for coff says there is either no aux entry or just one */ - fread ((char *)aux, AUXESZ, 1, nlist_stream_global); - } - else if (cs->c_nsyms > 2) - error ("more than one aux symbol table entry at symnum=%d\n", symnum); - - cs->c_name = getsymname (sym); - cs->c_value = sym->n_value; - cs->c_sclass = (sym->n_sclass & 0xff); - cs->c_secnum = sym->n_scnum; - cs->c_type = (unsigned) sym->n_type; - - symnum += cs->c_nsyms; -} - -/* Support for string table handling */ - -static char *stringtab = NULL; - -static int -init_stringtab (chan, offset) - int chan; - long offset; -{ - long buffer; - int val; - - if (stringtab) - { - free (stringtab); - stringtab = NULL; - } - - if (lseek (chan, offset, 0) < 0) - return -1; - - val = myread (chan, (char *)&buffer, sizeof buffer); - - /* If no string table is needed, then the file may end immediately - after the symbols. Just return with `stringtab' set to null. */ - if (val != sizeof buffer || buffer == 0) - return 0; - - stringtab = (char *) xmalloc (buffer); - if (stringtab == NULL) - return -1; - - bcopy (&buffer, stringtab, sizeof buffer); - - val = myread (chan, stringtab + sizeof buffer, buffer - sizeof buffer); - if (val != buffer - sizeof buffer || stringtab[buffer - 1] != '\0') - return -1; - - return 0; -} - -static void -free_stringtab () -{ - if (stringtab) - free (stringtab); - stringtab = NULL; -} - -static char * -getsymname (symbol_entry) - SYMENT *symbol_entry; -{ - static char buffer[SYMNMLEN+1]; - char *result; - - if (symbol_entry->n_zeroes == 0) - { - result = stringtab + symbol_entry->n_offset; - } - else - { - strncpy (buffer, symbol_entry->n_name, SYMNMLEN); - buffer[SYMNMLEN] = '\0'; - result = buffer; - } - return result; -} - -static char * -getfilename (aux_entry) - AUXENT *aux_entry; -{ - static char buffer[BUFSIZ]; - register char *temp; - char *result; - extern char *rindex (); - -#ifndef COFF_NO_LONG_FILE_NAMES - if (aux_entry->x_file.x_foff != 0) - strcpy (buffer, stringtab + aux_entry->x_file.x_foff); - else -#endif - { - strncpy (buffer, aux_entry->x_file.x_fname, FILNMLEN); - buffer[FILNMLEN] = '\0'; - } - result = buffer; - if ((temp = rindex (result, '/')) != NULL) - result = temp + 1; - return (result); -} - -/* Support for line number handling */ -static char *linetab = NULL; -static long linetab_offset; -static int linetab_count; - -static int -init_lineno (chan, offset, count) - int chan; - long offset; - int count; -{ - int val; - - if (lseek (chan, offset, 0) < 0) - return -1; - - if (linetab) - free (linetab); - linetab = (char *) xmalloc (count * LINESZ); - - val = myread (chan, linetab, count * LINESZ); - if (val != count * LINESZ) - return -1; - - linetab_offset = offset; - linetab_count = count; - return 0; -} - -static void -enter_linenos (file_offset, first_line, last_line) - long file_offset; - register int first_line; - register int last_line; -{ - register char *rawptr = &linetab[file_offset - linetab_offset]; - register struct lineno *lptr; - - /* skip first line entry for each function */ - rawptr += LINESZ; - /* line numbers start at one for the first line of the function */ - first_line--; - - for (lptr = (struct lineno *)rawptr; - lptr->l_lnno && lptr->l_lnno <= last_line; - rawptr += LINESZ, lptr = (struct lineno *)rawptr) - { - record_line (first_line + lptr->l_lnno, lptr->l_addr.l_paddr); - } -} - -static int -hashname (name) - char *name; -{ - register char *p = name; - register int total = p[0]; - register int c; - - c = p[1]; - total += c << 2; - if (c) - { - c = p[2]; - total += c << 4; - if (c) - total += p[3] << 6; - } - - return total % HASHSIZE; -} - -static void -patch_type (type, real_type) - struct type *type; - struct type *real_type; -{ - register struct type *target = TYPE_TARGET_TYPE (type); - register struct type *real_target = TYPE_TARGET_TYPE (real_type); - int field_size = TYPE_NFIELDS (real_target) * sizeof (struct field); - - TYPE_LENGTH (target) = TYPE_LENGTH (real_target); - TYPE_NFIELDS (target) = TYPE_NFIELDS (real_target); - TYPE_FIELDS (target) = (struct field *) - obstack_alloc (symbol_obstack, field_size); - - bcopy (TYPE_FIELDS (real_target), TYPE_FIELDS (target), field_size); - - if (TYPE_NAME (real_target)) - { - if (TYPE_NAME (target)) - free (TYPE_NAME (target)); - TYPE_NAME (target) = concat (TYPE_NAME (real_target), "", ""); - } -} - -/* Patch up all appropriate typdef symbols in the opaque_type_chains - so that they can be used to print out opaque data structures properly */ - -static void -patch_opaque_types () -{ - struct symtab *s; - - /* Look at each symbol in the per-file block of each symtab. */ - for (s = symtab_list; s; s = s->next) - { - register struct block *b; - register int i; - - /* Go through the per-file symbols only */ - b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 1); - for (i = BLOCK_NSYMS (b) - 1; i >= 0; i--) - { - register struct symbol *real_sym; - - /* Find completed typedefs to use to fix opaque ones. - Remove syms from the chain when their types are stored, - but search the whole chain, as there may be several syms - from different files with the same name. */ - real_sym = BLOCK_SYM (b, i); - if (SYMBOL_CLASS (real_sym) == LOC_TYPEDEF && - SYMBOL_NAMESPACE (real_sym) == VAR_NAMESPACE && - TYPE_CODE (SYMBOL_TYPE (real_sym)) == TYPE_CODE_PTR && - TYPE_LENGTH (TYPE_TARGET_TYPE (SYMBOL_TYPE (real_sym))) != 0) - { - register char *name = SYMBOL_NAME (real_sym); - register int hash = hashname (name); - register struct symbol *sym, *prev; - - prev = 0; - for (sym = opaque_type_chain[hash]; sym;) - { - if (name[0] == SYMBOL_NAME (sym)[0] && - !strcmp (name + 1, SYMBOL_NAME (sym) + 1)) - { - if (prev) - SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym); - else - opaque_type_chain[hash] - = (struct symbol *) SYMBOL_VALUE (sym); - - patch_type (SYMBOL_TYPE (sym), SYMBOL_TYPE (real_sym)); - - if (prev) - sym = (struct symbol *) SYMBOL_VALUE (prev); - else - sym = opaque_type_chain[hash]; - } - else - { - prev = sym; - sym = (struct symbol *) SYMBOL_VALUE (sym); - } - } - } - } - } -} - -static struct symbol * -process_coff_symbol (cs, aux) - register struct coff_symbol *cs; - register AUXENT *aux; -{ - register struct symbol *sym - = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol)); - char *name; - char *dot; -#ifdef NAMES_HAVE_UNDERSCORE - int offset = 1; -#else - int offset = 0; -#endif - - bzero (sym, sizeof (struct symbol)); - name = cs->c_name; - name = (name[0] == '_' ? name + offset : name); - SYMBOL_NAME (sym) = obstack_copy0 (symbol_obstack, name, strlen (name)); - - /* default assumptions */ - SYMBOL_VALUE (sym) = cs->c_value; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - - if (ISFCN (cs->c_type)) - { - SYMBOL_TYPE (sym) = - lookup_function_type (decode_function_type (cs, cs->c_type, aux)); - SYMBOL_CLASS (sym) = LOC_BLOCK; - if (cs->c_sclass == C_STAT) - add_symbol_to_list (sym, &file_symbols); - else if (cs->c_sclass == C_EXT) - add_symbol_to_list (sym, &global_symbols); - } - else - { - SYMBOL_TYPE (sym) = decode_type (cs, cs->c_type, aux); - switch (cs->c_sclass) - { - case C_NULL: - break; - - case C_AUTO: - SYMBOL_CLASS (sym) = LOC_LOCAL; - add_symbol_to_list (sym, &local_symbols); - break; - - case C_EXT: - SYMBOL_CLASS (sym) = LOC_STATIC; - add_symbol_to_list (sym, &global_symbols); - break; - - case C_STAT: - SYMBOL_CLASS (sym) = LOC_STATIC; - if (within_function) { - /* Static symbol of local scope */ - add_symbol_to_list (sym, &local_symbols); - } - else { - /* Static symbol at top level of file */ - add_symbol_to_list (sym, &file_symbols); - } - break; - - case C_REG: - case C_REGPARM: - SYMBOL_CLASS (sym) = LOC_REGISTER; - add_symbol_to_list (sym, &local_symbols); - break; - - case C_LABEL: - break; - - case C_ARG: - SYMBOL_CLASS (sym) = LOC_ARG; - add_symbol_to_list (sym, &local_symbols); - /* If PCC says a parameter is a short or a char, - it is really an int. */ - if (SYMBOL_TYPE (sym) == builtin_type_char - || SYMBOL_TYPE (sym) == builtin_type_short) - SYMBOL_TYPE (sym) = builtin_type_int; - else if (SYMBOL_TYPE (sym) == builtin_type_unsigned_char - || SYMBOL_TYPE (sym) == builtin_type_unsigned_short) - SYMBOL_TYPE (sym) = builtin_type_unsigned_int; - break; - - case C_TPDEF: - SYMBOL_CLASS (sym) = LOC_TYPEDEF; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - - /* If type has no name, give it one */ - if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0 - && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0) - TYPE_NAME (SYMBOL_TYPE (sym)) - = concat (SYMBOL_NAME (sym), "", ""); - - /* Keep track of any type which points to empty structured type, - so it can be filled from a definition from another file */ - if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR && - TYPE_LENGTH (TYPE_TARGET_TYPE (SYMBOL_TYPE (sym))) == 0) - { - register int i = hashname (SYMBOL_NAME (sym)); - - SYMBOL_VALUE (sym) = (int) opaque_type_chain[i]; - opaque_type_chain[i] = sym; - } - add_symbol_to_list (sym, &file_symbols); - break; - - case C_STRTAG: - case C_UNTAG: - case C_ENTAG: - SYMBOL_CLASS (sym) = LOC_TYPEDEF; - SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE; - if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0 - && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0) - TYPE_NAME (SYMBOL_TYPE (sym)) - = concat ("", - (cs->c_sclass == C_ENTAG - ? "enum " - : (cs->c_sclass == C_STRTAG - ? "struct " : "union ")), - SYMBOL_NAME (sym)); - add_symbol_to_list (sym, &file_symbols); - break; - - default: - break; - } - } - return sym; -} - -/* Decode a coff type specifier; - return the type that is meant. */ - -static -struct type * -decode_type (cs, c_type, aux) - register struct coff_symbol *cs; - unsigned int c_type; - register AUXENT *aux; -{ - register struct type *type = 0; - register int n; - unsigned int new_c_type; - - if (c_type & ~N_BTMASK) - { - new_c_type = DECREF (c_type); - if (ISPTR (c_type)) - { - type = decode_type (cs, new_c_type, aux); - type = lookup_pointer_type (type); - } - else if (ISFCN (c_type)) - { - type = decode_type (cs, new_c_type, aux); - type = lookup_function_type (type); - } - else if (ISARY (c_type)) - { - int i, n; - register unsigned short *dim; - struct type *base_type; - - /* Define an array type. */ - /* auxent refers to array, not base type */ - if (aux->x_sym.x_tagndx == 0) - cs->c_nsyms = 1; - - /* shift the indices down */ - dim = &aux->x_sym.x_fcnary.x_ary.x_dimen[0]; - i = 1; - n = dim[0]; - for (i = 0; *dim && i < DIMNUM - 1; i++, dim++) - *dim = *(dim + 1); - *dim = 0; - - type = (struct type *) - obstack_alloc (symbol_obstack, sizeof (struct type)); - bzero (type, sizeof (struct type)); - - base_type = decode_type (cs, new_c_type, aux); - - TYPE_CODE (type) = TYPE_CODE_ARRAY; - TYPE_TARGET_TYPE (type) = base_type; - TYPE_LENGTH (type) = n * TYPE_LENGTH (base_type); - } - return type; - } - - /* Reference to existing type */ - if (cs->c_nsyms > 1 && aux->x_sym.x_tagndx != 0) - { - type = coff_alloc_type (aux->x_sym.x_tagndx); - return type; - } - - return decode_base_type (cs, BTYPE (c_type), aux); -} - -/* Decode a coff type specifier for function definition; - return the type that the function returns. */ - -static -struct type * -decode_function_type (cs, c_type, aux) - register struct coff_symbol *cs; - unsigned int c_type; - register AUXENT *aux; -{ - if (aux->x_sym.x_tagndx == 0) - cs->c_nsyms = 1; /* auxent refers to function, not base type */ - - return decode_type (cs, DECREF (cs->c_type), aux); -} - -/* basic C types */ - -static -struct type * -decode_base_type (cs, c_type, aux) - register struct coff_symbol *cs; - unsigned int c_type; - register AUXENT *aux; -{ - struct type *type; - - switch (c_type) - { - case T_NULL: - /* shows up with "void (*foo)();" structure members */ - return builtin_type_void; - - case T_ARG: - /* shouldn't show up here */ - break; - - case T_CHAR: - return builtin_type_char; - - case T_SHORT: - return builtin_type_short; - - case T_INT: - return builtin_type_int; - - case T_LONG: - return builtin_type_long; - - case T_FLOAT: - return builtin_type_float; - - case T_DOUBLE: - return builtin_type_double; - - case T_STRUCT: - if (cs->c_nsyms != 2) - { - /* anonymous structure type */ - type = coff_alloc_type (cs->c_symnum); - TYPE_CODE (type) = TYPE_CODE_STRUCT; - TYPE_NAME (type) = concat ("struct ", "", ""); - TYPE_LENGTH (type) = 0; - TYPE_FIELDS (type) = 0; - TYPE_NFIELDS (type) = 0; - } - else - { - type = read_struct_type (cs->c_symnum, - aux->x_sym.x_misc.x_lnsz.x_size, - aux->x_sym.x_fcnary.x_fcn.x_endndx); - } - return type; - - case T_UNION: - if (cs->c_nsyms != 2) - { - /* anonymous union type */ - type = coff_alloc_type (cs->c_symnum); - TYPE_NAME (type) = concat ("union ", "", ""); - TYPE_LENGTH (type) = 0; - TYPE_FIELDS (type) = 0; - TYPE_NFIELDS (type) = 0; - } - else - { - type = read_struct_type (cs->c_symnum, - aux->x_sym.x_misc.x_lnsz.x_size, - aux->x_sym.x_fcnary.x_fcn.x_endndx); - } - TYPE_CODE (type) = TYPE_CODE_UNION; - return type; - - case T_ENUM: - return read_enum_type (cs->c_symnum, - aux->x_sym.x_misc.x_lnsz.x_size, - aux->x_sym.x_fcnary.x_fcn.x_endndx); - - case T_MOE: - /* shouldn't show up here */ - break; - - case T_UCHAR: - return builtin_type_unsigned_char; - - case T_USHORT: - return builtin_type_unsigned_short; - - case T_UINT: - return builtin_type_unsigned_int; - - case T_ULONG: - return builtin_type_unsigned_long; - } - printf ("unexpected type %d at symnum %d\n", c_type, cs->c_symnum); - return builtin_type_void; -} - -/* This page contains subroutines of read_type. */ - -/* Read the description of a structure (or union type) - and return an object describing the type. */ - -static struct type * -read_struct_type (index, length, lastsym) - int index; - int length; - int lastsym; -{ - struct nextfield - { - struct nextfield *next; - struct field field; - }; - - register struct type *type; - register struct nextfield *list = 0; - struct nextfield *new; - int nfields = 0; - register int n; - char *name; -#ifdef NAMES_HAVE_UNDERSCORE - int offset = 1; -#else - int offset = 0; -#endif - struct coff_symbol member_sym; - register struct coff_symbol *ms = &member_sym; - SYMENT sub_sym; - AUXENT sub_aux; - int done = 0; - - type = coff_alloc_type (index); - TYPE_CODE (type) = TYPE_CODE_STRUCT; - TYPE_LENGTH (type) = length; - - while (!done && symnum < lastsym && symnum < nlist_nsyms_global) - { - read_one_sym (ms, &sub_sym, &sub_aux); - name = ms->c_name; - name = (name[0] == '_' ? name + offset : name); - - switch (ms->c_sclass) - { - case C_MOS: - case C_MOU: - - /* Get space to record the next field's data. */ - new = (struct nextfield *) alloca (sizeof (struct nextfield)); - new->next = list; - list = new; - - /* Save the data. */ - list->field.name = savestring (name, strlen (name)); - list->field.type = decode_type (ms, ms->c_type, &sub_aux); - list->field.bitpos = 8 * ms->c_value; - list->field.bitsize = 0; - nfields++; - break; - - case C_FIELD: - - /* Get space to record the next field's data. */ - new = (struct nextfield *) alloca (sizeof (struct nextfield)); - new->next = list; - list = new; - - /* Save the data. */ - list->field.name = savestring (name, strlen (name)); - list->field.type = decode_type (ms, ms->c_type, &sub_aux); - list->field.bitpos = ms->c_value; - list->field.bitsize = sub_aux.x_sym.x_misc.x_lnsz.x_size; - nfields++; - break; - - case C_EOS: - done = 1; - break; - } - } - /* Now create the vector of fields, and record how big it is. */ - - TYPE_NFIELDS (type) = nfields; - TYPE_FIELDS (type) = (struct field *) - obstack_alloc (symbol_obstack, sizeof (struct field) * nfields); - - /* Copy the saved-up fields into the field vector. */ - - for (n = nfields; list; list = list->next) - TYPE_FIELD (type, --n) = list->field; - - return type; -} - -/* Read a definition of an enumeration type, - and create and return a suitable type object. - Also defines the symbols that represent the values of the type. */ - -static struct type * -read_enum_type (index, length, lastsym) - int index; - int length; - int lastsym; -{ - register struct symbol *sym; - register struct type *type; - int nsyms = 0; - struct pending **symlist; - struct coff_symbol member_sym; - register struct coff_symbol *ms = &member_sym; - SYMENT sub_sym; - AUXENT sub_aux; - struct pending *osyms, *syms; - register int n; - char *name; -#ifdef NAMES_HAVE_UNDERSCORE - int offset = 1; -#else - int offset = 0; -#endif - - type = coff_alloc_type (index); - if (within_function) - symlist = &local_symbols; - else - symlist = &file_symbols; - osyms = *symlist; - - while (symnum < lastsym && symnum < nlist_nsyms_global) - { - read_one_sym (ms, &sub_sym, &sub_aux); - name = ms->c_name; - name = (name[0] == '_' ? name + offset : name); - - switch (ms->c_sclass) - { - case C_MOE: - sym = (struct symbol *) xmalloc (sizeof (struct symbol)); - bzero (sym, sizeof (struct symbol)); - - SYMBOL_NAME (sym) = savestring (name, strlen (name)); - SYMBOL_CLASS (sym) = LOC_CONST; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - SYMBOL_VALUE (sym) = ms->c_value; - add_symbol_to_list (sym, symlist); - nsyms++; - break; - - case C_EOS: - break; - } - } - - /* Now fill in the fields of the type-structure. */ - - TYPE_LENGTH (type) = sizeof (int); - TYPE_CODE (type) = TYPE_CODE_ENUM; - TYPE_NFIELDS (type) = nsyms; - TYPE_FIELDS (type) = (struct field *) - obstack_alloc (symbol_obstack, sizeof (struct field) * nsyms); - - /* Find the symbols for the values and put them into the type. - The symbols can be found in the symlist that we put them on - to cause them to be defined. osyms contains the old value - of that symlist; everything up to there was defined by us. */ - - for (syms = *symlist, n = nsyms; syms != osyms; syms = syms->next) - { - SYMBOL_TYPE (syms->symbol) = type; - TYPE_FIELD_NAME (type, --n) = SYMBOL_NAME (syms->symbol); - TYPE_FIELD_VALUE (type, n) = 0; - TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (syms->symbol); - TYPE_FIELD_BITSIZE (type, n) = 0; - } - return type; -} - -/* This function is really horrible, but to avoid it, there would need - to be more filling in of forward references. THIS SHOULD BE MOVED - OUT OF COFFREAD.C AND DBXREAD.C TO SOME PLACE WHERE IT CAN BE SHARED. */ -int -fill_in_vptr_fieldno (type) - struct type *type; -{ - if (TYPE_VPTR_FIELDNO (type) < 0) - TYPE_VPTR_FIELDNO (type) = - fill_in_vptr_fieldno (TYPE_BASECLASS (type, 1)); - return TYPE_VPTR_FIELDNO (type); -} - -/* partial symbol tables are not implemented in coff, therefore - block_for_pc() (and others) will never decide to call this. */ - -extern struct symtab * -psymtab_to_symtab () -{ - fatal ("error: Someone called psymtab_to_symtab\n"); -} - -/* These will stay zero all the time */ -struct partial_symbol *global_psymbols, *static_psymbols; - -_initialize_coff () -{ - symfile = 0; - - static_psymbols = global_psymbols = (struct partial_symbol *) 0; - - add_com ("symbol-file", class_files, symbol_file_command, - "Load symbol table (in coff format) from executable file FILE."); -} - - -#endif /* COFF_FORMAT */ - -@ - - -1.4 -log -@Avoid A/UX change (#undef aux) for sending in to FSF. -@ -text -@d40 3 -@ - - -1.3 -log -@A/UX and USG changes. If BADMAG defined, use it. Avoid . -Declare fclose(). #undef aux which we use as a var. -@ -text -@a39 3 -/* Avoid problems with A/UX predefine */ -#undef aux - -@ - - -1.2 -log -@If discarding the symbol table, discard its name too, so "info files" -will give the right answer. -@ -text -@d31 1 -a31 1 -#include -d40 3 -d847 1 -a847 1 - -d1093 6 -d1100 1 -@ - - -1.1 -log -@Initial revision -@ -text -@d5 1 -a5 1 - Copyright (C) 1987, 1988 Free Software Foundation, Inc. -d684 3 -@ diff --git a/gdb/RCS/config.gdb,v b/gdb/RCS/config.gdb,v deleted file mode 100755 index b569f62cd7..0000000000 --- a/gdb/RCS/config.gdb,v +++ /dev/null @@ -1,229 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @@; - - -1.2 -date 89.03.27.18.38.55; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.13.19.14.24; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Add A/UX option (config.gdb aux). -@ -text -@#!/bin/sh - -# -# Shell script to create proper links to machine-dependent files in -# preparation for compiling gdb. -# -# Usage: config.gdb machine [operating-system] -# -# If config.gdb succeeds, it leaves its status in config.status. -# If config.gdb fails after disturbing the status quo, -# config.status is removed. -# - -progname=$0 - -case $# in -1) - machine=$1 - os="none" - ;; -2) - machine=$1 - os=$2 - ;; -*) - echo "Usage: $progname machine [operating-system]" - echo "Available machine types:" - echo m-*.h | sed 's/m-//g' | sed 's/\.h//g' - if [ -r config.status ] - then - cat config.status - fi - exit 1 - ;; -esac - -paramfile=m-${machine}.h -pinsnfile=${machine}-pinsn.c -opcodefile=${machine}-opcode.h -if [ -r ${machine}-dep.c ] -then - depfile=${machine}-dep.c -else - depfile=default-dep.c -fi - -# -# Special cases. -# If a file is not needed, set the filename to 'skip' and it will be -# ignored. -# -case $machine in -aux) - pinsnfile=m68k-pinsn.c - opcodefile=m68k-opcode.h - ;; -vax) - pinsnfile=vax-pinsn.c - opcodefile=vax-opcode.h - ;; -hp9k320) - pinsnfile=m68k-pinsn.c - opcodefile=m68k-opcode.h - ;; -isi) - pinsnfile=m68k-pinsn.c - opcodefile=m68k-opcode.h - ;; -i386) - echo "Note: i386 users need to modify \`CLIBS' & \`REGEX*' in the Makefile" - opcodefile=skip - ;; -i386gas) - echo "Note: i386 users need to modify \`CLIBS' & \`REGEX*' in the Makefile" - echo "Use of the coff encapsulation features also requires the GNU binutils utilities" - echo "to be ahead of their System V counterparts in your path." - pinsnfile=i386-pinsn.c - depfile=i386-dep.c - opcodefile=skip - ;; -merlin) - pinsnfile=ns32k-pinsn.c - opcodefile=ns32k-opcode.h - ;; -news) - pinsnfile=m68k-pinsn.c - opcodefile=m68k-opcode.h - ;; -npl) - pinsnfile=gld-pinsn.c - ;; -pn) - pinsnfile=gld-pinsn.c - ;; -sun2) - case $os in - os4|sunos4) - paramfile=m-sun2os4.h - ;; - os2|sunos2) - paramfile=m-sun2os2.h - esac - pinsnfile=m68k-pinsn.c - opcodefile=m68k-opcode.h - ;; -sun2os2) - pinsnfile=m68k-pinsn.c - opcodefile=m68k-opcode.h - ;; -sun2os4) - pinsnfile=m68k-pinsn.c - opcodefile=m68k-opcode.h - ;; -sun3) - case $os in - os4|sunos4) - paramfile=m-sun3os4.h - esac - pinsnfile=m68k-pinsn.c - opcodefile=m68k-opcode.h - ;; -sun3os4) - pinsnfile=m68k-pinsn.c - opcodefile=m68k-opcode.h - depfile=sun3-dep.c - ;; -sun4os4) - pinsnfile=sparc-pinsn.c - opcodefile=sparc-opcode.h - depfile=sparc-dep.c - ;; -umax) - pinsnfile=ns32k-pinsn.c - opcodefile=ns32k-opcode.h - ;; -sparc|sun4) - case $os in - os4|sunos4) - paramfile=m-sun4os4.h - esac - pinsnfile=sparc-pinsn.c - opcodefile=sparc-opcode.h - depfile=sparc-dep.c - paramfile=m-sparc.h - ;; -test) - paramfile=one - pinsnfile=three - opcodefile=four - ;; -*) - echo "Unknown machine type: \`$machine'" - echo "Available types:" - echo m-*.h | sed 's/m-//g' | sed 's/\.h//g' - exit 1 -esac - -files="$paramfile $pinsnfile $opcodefile $depfile" -links="param.h pinsn.c opcode.h dep.c" - -while [ -n "$files" ] -do - # set file to car of files, files to cdr of files - set $files; file=$1; shift; files=$* - set $links; link=$1; shift; links=$* - - if [ "$file" != skip ] - then - if [ ! -r $file ] - then - echo "$progname: cannot create a link \`$link'," - echo "since the file \`$file' does not exist." - exit 1 - fi - - rm -f $link config.status - # Make a symlink if possible, otherwise try a hard link - ln -s $file $link 2>/dev/null || ln $file $link - - if [ ! -r $link ] - then - echo "$progname: unable to link \`$link' to \`$file'." - exit 1 - fi - echo "Linked \`$link' to \`$file'." - fi -done - -echo "Links are now set up for use with a $machine." \ - | tee config.status -exit 0 - -@ - - -1.1 -log -@Initial revision -@ -text -@d53 4 -@ diff --git a/gdb/RCS/core.c,v b/gdb/RCS/core.c,v deleted file mode 100644 index f63081db32..0000000000 --- a/gdb/RCS/core.c,v +++ /dev/null @@ -1,651 +0,0 @@ -head 1.4; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.4 -date 89.03.27.18.39.18; author gnu; state Exp; -branches ; -next 1.3; - -1.3 -date 89.02.10.01.39.45; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.02.09.23.22.33; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.09.22.49.56; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.4 -log -@Unisoft Assholes changes for user.ps. Avoid sys/fcntl.h. -@ -text -@/* Work with core dump and executable files, for GDB. - Copyright (C) 1986, 1987, 1989 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! -*/ - -#include "defs.h" -#include "param.h" -#include "gdbcore.h" - -#ifdef USG -#include -#include -#endif - -#ifdef COFF_ENCAPSULATE -#include "a.out.encap.h" -#else -#include -#endif - -#ifndef N_MAGIC -#ifdef COFF_FORMAT -#define N_MAGIC(exec) ((exec).magic) -#else -#define N_MAGIC(exec) ((exec).a_magic) -#endif -#endif - -#include -#include -#include -#include -#include -#include - -#ifdef UNISOFT_ASSHOLES -#define PMMU -#define NEW_PMMU -#include /* Required for user.ps */ -#include /* '' */ -#include /* '' */ -#include -#define mc68881 /* Required to get float in user.ps */ -#endif - -#ifdef UMAX_CORE -#include -#else -#include -#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 -#define AOUTHDR struct exec -#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; - -/* 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; - -/* Address in executable file of start of text area data. */ - -int text_offset; - -/* Address in executable file of start of data area data. */ - -int exec_data_offset; - -/* Address in core file of start of data area data. */ - -int data_offset; - -/* Address in 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; - - fstat (corechan, &st_core); - - 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) - 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) - printf ("Core dump file \"%s\".\n", corefile); - else - printf ("No core dump file\n"); - - 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); - - 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 (have_inferior_p ()) - 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 ()) - return write_inferior_memory (memaddr, myaddr, len); - else - error ("Can write memory only when program being debugged is running."); -} - -/* 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; - - 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; - } - 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 (memaddr >= (corechan >= 0 ? data_end : exec_data_end) - && memaddr < stack_start) - { - i = min (len, stack_start - memaddr); - } - else if (memaddr >= stack_end && stack_end != 0) - { - i = min (len, - memaddr); - } - else - { - /* Address did not classify into one of the known ranges. - This could be because data_start != exec_data_start - or data_end similarly. */ - abort(); - } - - /* 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 < 0) - 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. - (FIXME we never write.) */ - else - { - bzero (myaddr, i); - returnval = 1; - } - - memaddr += i; - myaddr += i; - len -= i; - } - return returnval; -} - -/* 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."); -} - -@ - - -1.3 -log -@Fix up "info files" some more, to give more information. -Rearrange the tests in xfer_core_file to avoid dependencies -between data_start and exec_data_start, and for efficiency -and add an abort() to test correctness. (If you take out -never mind...) -@ -text -@d27 1 -a27 1 -#include -d50 10 -@ - - -1.2 -log -@Create gdbcore.h for externally visible variables; -spiff up the "info files" output to make it easier to read and more -informative. -@ -text -@d250 4 -d257 4 -a260 7 - printf ("Data segment in core file from 0x%x to 0x%x.\nStack segment in core file from 0x%x to 0x%x.\n", - data_start, data_end, stack_start, stack_end); - } - else if (execfile) - { - printf ("Data segment in executable from 0x%x to 0x%x.\n", - exec_data_start, exec_data_end); -d297 3 -a299 1 -/* Return 0 if address could be read, 1 if not. */ -d301 4 -d327 1 -d329 1 -d331 3 -a333 1 - along with the next address. */ -a334 17 - if (memaddr < text_start) - { - i = min (len, text_start - memaddr); - } - else if (memaddr >= text_end && memaddr < data_start) - { - i = min (len, data_start - memaddr); - } - else if (memaddr >= (corechan >= 0 ? data_end : exec_data_end) - && memaddr < stack_start) - { - i = min (len, stack_start - memaddr); - } - else if (memaddr >= stack_end && stack_end != 0) - { - i = min (len, - memaddr); - } -d337 1 -a337 1 - else if (memaddr >= data_start && memaddr < data_end) -d368 25 -d411 2 -a412 1 - read zeros if reading, or do nothing if writing. */ -@ - - -1.1 -log -@Initial revision -@ -text -@d2 1 -a2 1 - Copyright (C) 1986, 1987 Free Software Foundation, Inc. -d23 1 -d35 1 -d43 1 -d231 4 -a234 1 - if (corefile == 0) -a235 2 - else - printf ("Core dump file \"%s\".\n", corefile); -d242 1 -a242 1 - printf ("Symbols loaded from \"%s\".\n", symfile); -d248 1 -a248 1 - printf ("Text segment from 0x%x to 0x%x.\n", -d253 1 -a253 1 - printf ("Data segment from 0x%x to 0x%x.\nStack segment from 0x%x to 0x%x.\n", -d256 1 -a256 1 - else -@ diff --git a/gdb/RCS/dbxread.c,v b/gdb/RCS/dbxread.c,v deleted file mode 100644 index eb9d1cd3c2..0000000000 --- a/gdb/RCS/dbxread.c,v +++ /dev/null @@ -1,4610 +0,0 @@ -head 1.3; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.3 -date 89.03.27.18.41.32; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.02.10.01.38.34; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.10.01.30.11; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.3 -log -@Avoid sys/fcntl.h. -@ -text -@/* Read dbx symbol tables and convert to internal format, for GDB. - Copyright (C) 1986, 1987, 1988, 1989 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! -*/ - -#include "param.h" - -#ifdef READ_DBX_FORMAT - -#ifdef USG -#include -#include -#define L_SET 0 -#define L_INCR 1 -#endif - -#ifdef COFF_ENCAPSULATE -#include "a.out.encap.h" -#include "stab.gnu.h" -#else -#include -#include -#endif - -/* - * Define specifically gnu symbols here. - */ - -/* The following type indicates the definition of a symbol as being - an indirect reference to another symbol. The other symbol - appears as an undefined reference, immediately following this symbol. - - Indirection is asymmetrical. The other symbol's value will be used - to satisfy requests for the indirect symbol, but not vice versa. - If the other symbol does not have a definition, libraries will - be searched to find a definition. */ -#ifndef N_INDR -#define N_INDR 0xa -#endif - -/* The following symbols refer to set elements. - All the N_SET[ATDB] symbols with the same name form one set. - Space is allocated for the set in the text section, and each set - element's value is stored into one word of the space. - The first word of the space is the length of the set (number of elements). - - The address of the set is made into an N_SETV symbol - whose name is the same as the name of the set. - This symbol acts like a N_DATA global symbol - in that it can satisfy undefined external references. */ - -#ifndef N_SETA -#define N_SETA 0x14 /* Absolute set element symbol */ -#endif /* This is input to LD, in a .o file. */ - -#ifndef N_SETT -#define N_SETT 0x16 /* Text set element symbol */ -#endif /* This is input to LD, in a .o file. */ - -#ifndef N_SETD -#define N_SETD 0x18 /* Data set element symbol */ -#endif /* This is input to LD, in a .o file. */ - -#ifndef N_SETB -#define N_SETB 0x1A /* Bss set element symbol */ -#endif /* This is input to LD, in a .o file. */ - -/* Macros dealing with the set element symbols defined in a.out.h */ -#define SET_ELEMENT_P(x) ((x)>=N_SETA&&(x)<=(N_SETB|N_EXT)) -#define TYPE_OF_SET_ELEMENT(x) ((x)-N_SETA+N_ABS) - -#ifndef N_SETV -#define N_SETV 0x1C /* Pointer to set vector in data area. */ -#endif /* This is output from LD. */ - -#ifndef N_WARNING -#define N_WARNING 0x1E /* Warning message to print if file included */ -#endif /* This is input to ld */ - -#ifndef __GNU_STAB__ - -/* Line number for the data section. This is to be used to describe - the source location of a variable declaration. */ -#ifndef N_DSLINE -#define N_DSLINE (N_SLINE+N_DATA-N_TEXT) -#endif - -/* Line number for the bss section. This is to be used to describe - the source location of a variable declaration. */ -#ifndef N_BSLINE -#define N_BSLINE (N_SLINE+N_BSS-N_TEXT) -#endif - -#endif /* not __GNU_STAB__ */ - -#include -#include -#include -#include -#include -#include "defs.h" -#include "symtab.h" - -#ifndef COFF_FORMAT -#define AOUTHDR struct exec -#endif - -static void add_symbol_to_list (); -static void read_dbx_symtab (); -static void process_one_symbol (); -static void free_all_psymbols (); -static struct type *read_type (); -static struct type *read_range_type (); -static struct type *read_enum_type (); -static struct type *read_struct_type (); -static struct type *read_array_type (); -static long read_number (); -static void finish_block (); -static struct blockvector *make_blockvector (); -static struct symbol *define_symbol (); -static void start_subfile (); -static int hashname (); -static void hash_symsegs (); - -extern struct symtab *read_symsegs (); -extern void free_all_symtabs (); -extern void free_all_psymtabs (); -extern void free_inclink_symtabs (); - -/* C++ */ -static struct type **read_args(); - -/* Macro to determine which symbols to ignore when reading the first symbol - of a file. Some machines override this definition. */ -#ifdef N_NSYMS -#ifndef IGNORE_SYMBOL -/* This code is used on Ultrix systems. Ignore it */ -#define IGNORE_SYMBOL(type) (type == N_NSYMS) -#endif -#else -#ifndef IGNORE_SYMBOL -/* Don't ignore any symbols. */ -#define IGNORE_SYMBOL(type) (0) -#endif -#endif /* not N_NSYMS */ - -/* Macro for number of symbol table entries (in usual a.out format). - Some machines override this definition. */ -#ifndef NUMBER_OF_SYMBOLS -#ifdef COFF_HEADER -#define NUMBER_OF_SYMBOLS \ - ((COFF_HEADER(hdr) ? hdr.coffhdr.filehdr.f_nsyms : hdr.a_syms) / \ - sizeof (struct nlist)) -#else -#define NUMBER_OF_SYMBOLS (hdr.a_syms / sizeof (struct nlist)) -#endif -#endif - -/* Macro for file-offset of symbol table (in usual a.out format). */ -#ifndef SYMBOL_TABLE_OFFSET -#define SYMBOL_TABLE_OFFSET N_SYMOFF (hdr) -#endif - -/* Macro for file-offset of string table (in usual a.out format). */ -#ifndef STRING_TABLE_OFFSET -#define STRING_TABLE_OFFSET (N_SYMOFF (hdr) + hdr.a_syms) -#endif - -/* Macro to store the length of the string table data in INTO. */ -#ifndef READ_STRING_TABLE_SIZE -#define READ_STRING_TABLE_SIZE(INTO) \ -{ val = myread (desc, &INTO, sizeof INTO); \ - if (val < 0) perror_with_name (name); } -#endif - -/* Macro to declare variables to hold the file's header data. */ -#ifndef DECLARE_FILE_HEADERS -#define DECLARE_FILE_HEADERS AOUTHDR hdr -#endif - -/* Macro to read the header data from descriptor DESC and validate it. - NAME is the file name, for error messages. */ -#ifndef READ_FILE_HEADERS -#ifdef HEADER_SEEK_FD -#define READ_FILE_HEADERS(DESC, NAME) \ -{ HEADER_SEEK_FD (DESC); \ - val = myread (DESC, &hdr, sizeof hdr); \ - if (val < 0) perror_with_name (NAME); \ - if (N_BADMAG (hdr)) \ - error ("File \"%s\" not in executable format.", NAME); } -#else -#define READ_FILE_HEADERS(DESC, NAME) \ -{ val = myread (DESC, &hdr, sizeof hdr); \ - if (val < 0) perror_with_name (NAME); \ - if (N_BADMAG (hdr)) \ - error ("File \"%s\" not in executable format.", NAME); } -#endif -#endif - -/* Macro for size of text segment */ -#ifndef SIZE_OF_TEXT_SEGMENT -#define SIZE_OF_TEXT_SEGMENT hdr.a_text -#endif - -/* Macro for name of symbol to indicate a file compiled with gcc. */ -#ifndef GCC_COMPILED_FLAG_SYMBOL -#define GCC_COMPILED_FLAG_SYMBOL "gcc_compiled." -#endif - -/* Chain of symtabs made from reading the file's symsegs. - These symtabs do not go into symtab_list themselves, - but the information is copied from them when appropriate - to make the symtabs that will exist permanently. */ - -static struct symtab *symseg_chain; - -/* Symseg symbol table for the file whose data we are now processing. - It is one of those in symseg_chain. Or 0, for a compilation that - has no symseg. */ - -static struct symtab *current_symseg; - -/* Name of source file whose symbol data we are now processing. - This comes from a symbol of type N_SO. */ - -static char *last_source_file; - -/* Core address of start of text of current source file. - This too comes from the N_SO symbol. */ - -static CORE_ADDR last_source_start_addr; - -/* End of the text segment of the executable file, - as found in the symbol _etext. */ - -static CORE_ADDR end_of_text_addr; - -/* The list of sub-source-files within the current individual compilation. - Each file gets its own symtab with its own linetable and associated info, - but they all share one blockvector. */ - -struct subfile -{ - struct subfile *next; - char *name; - struct linetable *line_vector; - int line_vector_length; - int line_vector_index; - int prev_line_number; -}; - -static struct subfile *subfiles; - -static struct subfile *current_subfile; - -/* Count symbols as they are processed, for error messages. */ - -static int symnum; - -/* Vector of types defined so far, indexed by their dbx type numbers. - (In newer sun systems, dbx uses a pair of numbers in parens, - as in "(SUBFILENUM,NUMWITHINSUBFILE)". Then these numbers must be - translated through the type_translations hash table to get - the index into the type vector.) */ - -static struct typevector *type_vector; - -/* Number of elements allocated for type_vector currently. */ - -static int type_vector_length; - -/* Vector of line number information. */ - -static struct linetable *line_vector; - -/* Index of next entry to go in line_vector_index. */ - -static int line_vector_index; - -/* Last line number recorded in the line vector. */ - -static int prev_line_number; - -/* Number of elements allocated for line_vector currently. */ - -static int line_vector_length; - -/* Hash table of global symbols whose values are not known yet. - They are chained thru the SYMBOL_VALUE, since we don't - have the correct data for that slot yet. */ - -#define HASHSIZE 127 -static struct symbol *global_sym_chain[HASHSIZE]; - -/* Record the symbols defined for each context in a list. - We don't create a struct block for the context until we - know how long to make it. */ - -#define PENDINGSIZE 100 - -struct pending -{ - struct pending *next; - int nsyms; - struct symbol *symbol[PENDINGSIZE]; -}; - -/* List of free `struct pending' structures for reuse. */ -struct pending *free_pendings; - -/* Here are the three lists that symbols are put on. */ - -struct pending *file_symbols; /* static at top level, and types */ - -struct pending *global_symbols; /* global functions and variables */ - -struct pending *local_symbols; /* everything local to lexical context */ - -/* Stack representing unclosed lexical contexts - (that will become blocks, eventually). */ - -struct context_stack -{ - struct pending *locals; - struct pending_block *old_blocks; - struct symbol *name; - CORE_ADDR start_addr; - int depth; -}; - -struct context_stack *context_stack; - -/* Index of first unused entry in context stack. */ -int context_stack_depth; - -/* Currently allocated size of context stack. */ - -int context_stack_size; - -/* Nonzero if within a function (so symbols should be local, - if nothing says specifically). */ - -int within_function; - -/* List of blocks already made (lexical contexts already closed). - This is used at the end to make the blockvector. */ - -struct pending_block -{ - struct pending_block *next; - struct block *block; -}; - -struct pending_block *pending_blocks; - -extern CORE_ADDR first_object_file_end; /* From blockframe.c */ - -/* File name symbols were loaded from. */ - -static char *symfile; - -/* Low and high symbol values (inclusive) for the global variable - entries in the symbol file. */ - -static int first_global_sym, last_global_sym; - -/* Partial symbol list for all of the global and static symbols found - in a file */ - -struct partial_symbol *global_psymbols, *static_psymbols; -int global_psymbols_allocated, static_psymbols_allocated; - -/* Position for next psymbol to be added */ - -struct partial_symbol *next_ps_global, *next_ps_static; - -/* Global variable which, when set, indicates that we are processing a - .o file compiled with gcc */ - -static unsigned char processing_gcc_compilation; - -static int -xxmalloc (n) -{ - int v = malloc (n); - if (v == 0) - abort (); - return v; -} - -/* Make a copy of the string at PTR with SIZE characters in the symbol obstack - (and add a null character at the end in the copy). - Returns the address of the copy. */ - -static char * -obsavestring (ptr, size) - char *ptr; - int size; -{ - register char *p = (char *) obstack_alloc (symbol_obstack, size + 1); - /* Open-coded bcopy--saves function call time. - These strings are usually short. */ - { - register char *p1 = ptr; - register char *p2 = p; - char *end = ptr + size; - while (p1 != end) - *p2++ = *p1++; - } - p[size] = 0; - return p; -} - -/* Concatenate strings S1, S2 and S3; return the new string. - Space is found in the symbol_obstack. */ - -static char * -obconcat (s1, s2, s3) - char *s1, *s2, *s3; -{ - register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1; - register char *val = (char *) obstack_alloc (symbol_obstack, len); - strcpy (val, s1); - strcat (val, s2); - strcat (val, s3); - return val; -} - -/* Support for Sun changes to dbx symbol format */ - -/* For each identified header file, we have a table of types defined - in that header file. - - header_files maps header file names to their type tables. - It is a vector of n_header_files elements. - Each element describes one header file. - It contains a vector of types. - - Sometimes it can happen that the same header file produces - different results when included in different places. - This can result from conditionals or from different - things done before including the file. - When this happens, there are multiple entries for the file in this table, - one entry for each distinct set of results. - The entries are distinguished by the INSTANCE field. - The INSTANCE field appears in the N_BINCL and N_EXCL symbol table and is - used to match header-file references to their corresponding data. */ - -struct header_file -{ - char *name; /* Name of header file */ - int instance; /* Numeric code distinguishing instances - of one header file that produced - different results when included. - It comes from the N_BINCL or N_EXCL. */ - struct type **vector; /* Pointer to vector of types */ - int length; /* Allocated length (# elts) of that vector */ -}; - -static struct header_file *header_files; - -static int n_header_files; - -static int n_allocated_header_files; - -/* During initial symbol readin, we need to have a structure to keep - track of which psymtabs have which bincls in them. This structure - is used during readin to setup the list of dependencies within each - partial symbol table. */ - -struct header_file_location -{ - char *name; /* Name of header file */ - int instance; /* See above */ - struct partial_symtab *pst; /* Partial symtab that has the - BINCL/EINCL defs for this file */ -}; - -/* The actual list and controling variables */ -static struct header_file_location *bincl_list, *next_bincl; -static int bincls_allocated; - -/* Within each object file, various header files are assigned numbers. - A type is defined or referred to with a pair of numbers - (FILENUM,TYPENUM) where FILENUM is the number of the header file - and TYPENUM is the number within that header file. - TYPENUM is the index within the vector of types for that header file. - - FILENUM == 1 is special; it refers to the main source of the object file, - and not to any header file. FILENUM != 1 is interpreted by looking it up - in the following table, which contains indices in header_files. */ - -static int *this_object_header_files; - -static int n_this_object_header_files; - -static int n_allocated_this_object_header_files; - -/* When a header file is getting special overriding definitions - for one source file, record here the header_files index - of its normal definition vector. - At other times, this is -1. */ - -static int header_file_prev_index; - -/* At the start of reading dbx symbols, allocate our tables. */ - -static void -init_header_files () -{ - n_allocated_header_files = 10; - header_files = (struct header_file *) xxmalloc (10 * sizeof (struct header_file)); - n_header_files = 0; - - n_allocated_this_object_header_files = 10; - this_object_header_files = (int *) xxmalloc (10 * sizeof (int)); -} - -/* At the end of reading dbx symbols, free our tables. */ - -static void -free_header_files () -{ - register int i; - for (i = 0; i < n_header_files; i++) - free (header_files[i].name); - if (header_files) free (header_files); - if (this_object_header_files) - free (this_object_header_files); -} - -/* Called at the start of each object file's symbols. - Clear out the mapping of header file numbers to header files. */ - -static void -new_object_header_files () -{ - /* Leave FILENUM of 0 free for builtin types and this file's types. */ - n_this_object_header_files = 1; - header_file_prev_index = -1; -} - -/* Add header file number I for this object file - at the next successive FILENUM. */ - -static void -add_this_object_header_file (i) - int i; -{ - if (n_this_object_header_files == n_allocated_this_object_header_files) - { - n_allocated_this_object_header_files *= 2; - this_object_header_files - = (int *) xrealloc (this_object_header_files, - n_allocated_this_object_header_files * sizeof (int)); - } - - this_object_header_files[n_this_object_header_files++] = i; -} - -/* Add to this file an "old" header file, one already seen in - a previous object file. NAME is the header file's name. - INSTANCE is its instance code, to select among multiple - symbol tables for the same header file. */ - -static void -add_old_header_file (name, instance) - char *name; - int instance; -{ - register struct header_file *p = header_files; - register int i; - - for (i = 0; i < n_header_files; i++) - if (!strcmp (p[i].name, name) && instance == p[i].instance) - { - add_this_object_header_file (i); - return; - } - error ("Invalid symbol data: \"repeated\" header file that hasn't been seen before, at symtab pos %d.", - symnum); -} - -/* Add to this file a "new" header file: definitions for its types follow. - NAME is the header file's name. - Most often this happens only once for each distinct header file, - but not necessarily. If it happens more than once, INSTANCE has - a different value each time, and references to the header file - use INSTANCE values to select among them. - - dbx output contains "begin" and "end" markers for each new header file, - but at this level we just need to know which files there have been; - so we record the file when its "begin" is seen and ignore the "end". */ - -static void -add_new_header_file (name, instance) - char *name; - int instance; -{ - register int i; - register struct header_file *p = header_files; - header_file_prev_index = -1; - -#if 0 - /* This code was used before I knew about the instance codes. - My first hypothesis is that it is not necessary now - that instance codes are handled. */ - - /* Has this header file a previous definition? - If so, make a new entry anyway so that this use in this source file - gets a separate entry. Later source files get the old entry. - Record here the index of the old entry, so that any type indices - not previously defined can get defined in the old entry as - well as in the new one. */ - - for (i = 0; i < n_header_files; i++) - if (!strcmp (p[i].name, name)) - { - header_file_prev_index = i; - } - -#endif - - /* Make sure there is room for one more header file. */ - - if (n_header_files == n_allocated_header_files) - { - n_allocated_header_files *= 2; - header_files = (struct header_file *) - xrealloc (header_files, - (n_allocated_header_files - * sizeof (struct header_file))); - } - - /* Create an entry for this header file. */ - - i = n_header_files++; - header_files[i].name = savestring (name, strlen(name)); - header_files[i].instance = instance; - header_files[i].length = 10; - header_files[i].vector - = (struct type **) xxmalloc (10 * sizeof (struct type *)); - bzero (header_files[i].vector, 10 * sizeof (struct type *)); - - add_this_object_header_file (i); -} - -/* Look up a dbx type-number pair. Return the address of the slot - where the type for that number-pair is stored. - The number-pair is in TYPENUMS. - - This can be used for finding the type associated with that pair - or for associating a new type with the pair. */ - -static struct type ** -dbx_lookup_type (typenums) - int typenums[2]; -{ - register int filenum = typenums[0], index = typenums[1]; - - if (filenum < 0 || filenum >= n_this_object_header_files) - error ("Invalid symbol data: type number (%d,%d) out of range at symtab pos %d.", - filenum, index, symnum); - - if (filenum == 0) - { - /* Type is defined outside of header files. - Find it in this object file's type vector. */ - if (index >= type_vector_length) - { - type_vector_length *= 2; - type_vector = (struct typevector *) - xrealloc (type_vector, - (sizeof (struct typevector) - + type_vector_length * sizeof (struct type *))); - bzero (&type_vector->type[type_vector_length / 2], - type_vector_length * sizeof (struct type *) / 2); - } - return &type_vector->type[index]; - } - else - { - register int real_filenum = this_object_header_files[filenum]; - register struct header_file *f; - - if (real_filenum >= n_header_files) - abort (); - - f = &header_files[real_filenum]; - - if (index >= f->length) - { - f->length *= 2; - f->vector = (struct type **) - xrealloc (f->vector, f->length * sizeof (struct type *)); - bzero (&f->vector[f->length / 2], - f->length * sizeof (struct type *) / 2); - } - return &f->vector[index]; - } -} - -/* Make sure there is a type allocated for type numbers TYPENUMS - and return the type object. - This can create an empty (zeroed) type object. */ - -static struct type * -dbx_alloc_type (typenums) - int typenums[2]; -{ - register struct type **type_addr = dbx_lookup_type (typenums); - register struct type *type = *type_addr; - - /* If we are referring to a type not known at all yet, - allocate an empty type for it. - We will fill it in later if we find out how. */ - if (type == 0) - { - type = (struct type *) obstack_alloc (symbol_obstack, - sizeof (struct type)); - bzero (type, sizeof (struct type)); - TYPE_VPTR_FIELDNO (type) = -1; - *type_addr = type; - } - return type; -} - -#if 0 -static struct type ** -explicit_lookup_type (real_filenum, index) - int real_filenum, index; -{ - register struct header_file *f = &header_files[real_filenum]; - - if (index >= f->length) - { - f->length *= 2; - f->vector = (struct type **) - xrealloc (f->vector, f->length * sizeof (struct type *)); - bzero (&f->vector[f->length / 2], - f->length * sizeof (struct type *) / 2); - } - return &f->vector[index]; -} -#endif - -/* maintain the lists of symbols and blocks */ - -/* Add a symbol to one of the lists of symbols. */ -static void -add_symbol_to_list (symbol, listhead) - struct symbol *symbol; - struct pending **listhead; -{ - /* We keep PENDINGSIZE symbols in each link of the list. - If we don't have a link with room in it, add a new link. */ - if (*listhead == 0 || (*listhead)->nsyms == PENDINGSIZE) - { - register struct pending *link; - if (free_pendings) - { - link = free_pendings; - free_pendings = link->next; - } - else - link = (struct pending *) xxmalloc (sizeof (struct pending)); - - link->next = *listhead; - *listhead = link; - link->nsyms = 0; - } - - (*listhead)->symbol[(*listhead)->nsyms++] = symbol; -} - -/* At end of reading syms, or in case of quit, - really free as many `struct pending's as we can easily find. */ - -static void -really_free_pendings () -{ - struct pending *next, *next1; - struct pending_block *bnext, *bnext1; - - for (next = free_pendings; next; next = next1) - { - next1 = next->next; - free (next); - } - free_pendings = 0; - - for (bnext = pending_blocks; bnext; bnext = bnext1) - { - bnext1 = bnext->next; - free (bnext); - } - pending_blocks = 0; - - for (next = file_symbols; next; next = next1) - { - next1 = next->next; - free (next); - } - for (next = global_symbols; next; next = next1) - { - next1 = next->next; - free (next); - } -} - -/* Take one of the lists of symbols and make a block from it. - Keep the order the symbols have in the list (reversed from the input file). - Put the block on the list of pending blocks. */ - -static void -finish_block (symbol, listhead, old_blocks, start, end) - struct symbol *symbol; - struct pending **listhead; - struct pending_block *old_blocks; - CORE_ADDR start, end; -{ - register struct pending *next, *next1; - register struct block *block; - register struct pending_block *pblock; - struct pending_block *opblock; - register int i; - - /* Count the length of the list of symbols. */ - - for (next = *listhead, i = 0; next; i += next->nsyms, next = next->next); - - block = (struct block *) obstack_alloc (symbol_obstack, - (sizeof (struct block) - + ((i - 1) - * sizeof (struct symbol *)))); - - /* Copy the symbols into the block. */ - - BLOCK_NSYMS (block) = i; - for (next = *listhead; next; next = next->next) - { - register int j; - for (j = next->nsyms - 1; j >= 0; j--) - BLOCK_SYM (block, --i) = next->symbol[j]; - } - - BLOCK_START (block) = start; - BLOCK_END (block) = end; - BLOCK_SUPERBLOCK (block) = 0; /* Filled in when containing block is made */ - BLOCK_GCC_COMPILED (block) = processing_gcc_compilation; - - /* Put the block in as the value of the symbol that names it. */ - - if (symbol) - { - SYMBOL_BLOCK_VALUE (symbol) = block; - BLOCK_FUNCTION (block) = symbol; - } - else - BLOCK_FUNCTION (block) = 0; - - /* Now "free" the links of the list, and empty the list. */ - - for (next = *listhead; next; next = next1) - { - next1 = next->next; - next->next = free_pendings; - free_pendings = next; - } - *listhead = 0; - - /* Install this block as the superblock - of all blocks made since the start of this scope - that don't have superblocks yet. */ - - opblock = 0; - for (pblock = pending_blocks; pblock != old_blocks; pblock = pblock->next) - { - if (BLOCK_SUPERBLOCK (pblock->block) == 0) - BLOCK_SUPERBLOCK (pblock->block) = block; - opblock = pblock; - } - - /* Record this block on the list of all blocks in the file. - Put it after opblock, or at the beginning if opblock is 0. - This puts the block in the list after all its subblocks. */ - - /* Allocate in the symbol_obstack to save time. - It wastes a little space. */ - pblock = (struct pending_block *) - obstack_alloc (symbol_obstack, - sizeof (struct pending_block)); - pblock->block = block; - if (opblock) - { - pblock->next = opblock->next; - opblock->next = pblock; - } - else - { - pblock->next = pending_blocks; - pending_blocks = pblock; - } -} - -static struct blockvector * -make_blockvector () -{ - register struct pending_block *next, *next1; - register struct blockvector *blockvector; - register int i; - - /* Count the length of the list of blocks. */ - - for (next = pending_blocks, i = 0; next; next = next->next, i++); - - blockvector = (struct blockvector *) - obstack_alloc (symbol_obstack, - (sizeof (struct blockvector) - + (i - 1) * sizeof (struct block *))); - - /* Copy the blocks into the blockvector. - This is done in reverse order, which happens to put - the blocks into the proper order (ascending starting address). - finish_block has hair to insert each block into the list - after its subblocks in order to make sure this is true. */ - - BLOCKVECTOR_NBLOCKS (blockvector) = i; - for (next = pending_blocks; next; next = next->next) - BLOCKVECTOR_BLOCK (blockvector, --i) = next->block; - -#if 0 /* Now we make the links in the obstack, so don't free them. */ - /* Now free the links of the list, and empty the list. */ - - for (next = pending_blocks; next; next = next1) - { - next1 = next->next; - free (next); - } -#endif - pending_blocks = 0; - - return blockvector; -} - -/* Manage the vector of line numbers. */ - -static void -record_line (line, pc) - int line; - CORE_ADDR pc; -{ - struct linetable_entry *e; - /* Ignore the dummy line number in libg.o */ - - if (line == 0xffff) - return; - - /* Make sure line vector is big enough. */ - - if (line_vector_index + 1 >= line_vector_length) - { - line_vector_length *= 2; - line_vector = (struct linetable *) - xrealloc (line_vector, - (sizeof (struct linetable) - + line_vector_length * sizeof (struct linetable_entry))); - current_subfile->line_vector = line_vector; - } - - e = line_vector->item + line_vector_index++; - e->line = line; e->pc = pc; -} - -/* Start a new symtab for a new source file. - This is called when a dbx symbol of type N_SO is seen; - it indicates the start of data for one original source file. */ - -static void -start_symtab (name, start_addr) - char *name; - CORE_ADDR start_addr; -{ - register struct symtab *s; - - last_source_file = name; - last_source_start_addr = start_addr; - file_symbols = 0; - global_symbols = 0; - within_function = 0; - - /* Context stack is initially empty, with room for 10 levels. */ - context_stack - = (struct context_stack *) xxmalloc (10 * sizeof (struct context_stack)); - context_stack_size = 10; - context_stack_depth = 0; - - new_object_header_files (); - - for (s = symseg_chain; s; s = s->next) - if (s->ldsymoff == symnum * sizeof (struct nlist)) - break; - current_symseg = s; - if (s != 0) - return; - - type_vector_length = 160; - type_vector = (struct typevector *) - xxmalloc (sizeof (struct typevector) - + type_vector_length * sizeof (struct type *)); - bzero (type_vector->type, type_vector_length * sizeof (struct type *)); - - /* Initialize the list of sub source files with one entry - for this file (the top-level source file). */ - - subfiles = 0; - current_subfile = 0; - start_subfile (name); - - /* Set default for compiler to pcc; assume that we aren't processing - a gcc compiled file until proved otherwise. */ - - processing_gcc_compilation = 0; -} - -/* Handle an N_SOL symbol, which indicates the start of - code that came from an included (or otherwise merged-in) - source file with a different name. */ - -static void -start_subfile (name) - char *name; -{ - register struct subfile *subfile; - - /* Save the current subfile's line vector data. */ - - if (current_subfile) - { - current_subfile->line_vector_index = line_vector_index; - current_subfile->line_vector_length = line_vector_length; - current_subfile->prev_line_number = prev_line_number; - } - - /* See if this subfile is already known as a subfile of the - current main source file. */ - - for (subfile = subfiles; subfile; subfile = subfile->next) - { - if (!strcmp (subfile->name, name)) - { - line_vector = subfile->line_vector; - line_vector_index = subfile->line_vector_index; - line_vector_length = subfile->line_vector_length; - prev_line_number = subfile->prev_line_number; - current_subfile = subfile; - return; - } - } - - /* This subfile is not known. Add an entry for it. */ - - line_vector_index = 0; - line_vector_length = 1000; - prev_line_number = -2; /* Force first line number to be explicit */ - line_vector = (struct linetable *) - xxmalloc (sizeof (struct linetable) - + line_vector_length * sizeof (struct linetable_entry)); - - /* Make an entry for this subfile in the list of all subfiles - of the current main source file. */ - - subfile = (struct subfile *) xxmalloc (sizeof (struct subfile)); - subfile->next = subfiles; - subfile->name = savestring (name, strlen (name)); - subfile->line_vector = line_vector; - subfiles = subfile; - current_subfile = subfile; -} - -/* Finish the symbol definitions for one main source file, - close off all the lexical contexts for that file - (creating struct block's for them), then make the struct symtab - for that file and put it in the list of all such. - - END_ADDR is the address of the end of the file's text. */ - -static void -end_symtab (end_addr) - CORE_ADDR end_addr; -{ - register struct symtab *symtab; - register struct blockvector *blockvector; - register struct subfile *subfile; - register struct linetable *lv; - struct subfile *nextsub; - - if (current_symseg != 0) - { - last_source_file = 0; - current_symseg = 0; - return; - } - - /* Finish the lexical context of the last function in the file; - pop the context stack. */ - - if (context_stack_depth > 0) - { - register struct context_stack *cstk; - context_stack_depth--; - cstk = &context_stack[context_stack_depth]; - /* Make a block for the local symbols within. */ - finish_block (cstk->name, &local_symbols, cstk->old_blocks, - cstk->start_addr, end_addr); - } - - /* Finish defining all the blocks of this symtab. */ - finish_block (0, &file_symbols, 0, last_source_start_addr, end_addr); - finish_block (0, &global_symbols, 0, last_source_start_addr, end_addr); - blockvector = make_blockvector (); - - current_subfile->line_vector_index = line_vector_index; - - /* Now create the symtab objects proper, one for each subfile. */ - /* (The main file is one of them.) */ - - for (subfile = subfiles; subfile; subfile = nextsub) - { - symtab = (struct symtab *) xxmalloc (sizeof (struct symtab)); - symtab->free_ptr = 0; - - /* Fill in its components. */ - symtab->blockvector = blockvector; - type_vector->length = type_vector_length; - symtab->typevector = type_vector; - symtab->free_code = free_linetable; - if (subfile->next == 0) - symtab->free_ptr = (char *) type_vector; - - symtab->filename = subfile->name; - lv = subfile->line_vector; - lv->nitems = subfile->line_vector_index; - symtab->linetable = (struct linetable *) - xrealloc (lv, (sizeof (struct linetable) - + lv->nitems * sizeof (struct linetable_entry))); - symtab->nlines = 0; - symtab->line_charpos = 0; - - /* Link the new symtab into the list of such. */ - symtab->next = symtab_list; - symtab_list = symtab; - - nextsub = subfile->next; - free (subfile); - } - - type_vector = 0; - type_vector_length = -1; - line_vector = 0; - line_vector_length = -1; - last_source_file = 0; -} - -#ifdef N_BINCL - -/* Handle the N_BINCL and N_EINCL symbol types - that act like N_SOL for switching source files - (different subfiles, as we call them) within one object file, - but using a stack rather than in an arbitrary order. */ - -struct subfile_stack -{ - struct subfile_stack *next; - char *name; - int prev_index; -}; - -struct subfile_stack *subfile_stack; - -static void -push_subfile () -{ - register struct subfile_stack *tem - = (struct subfile_stack *) xxmalloc (sizeof (struct subfile_stack)); - - tem->next = subfile_stack; - subfile_stack = tem; - if (current_subfile == 0 || current_subfile->name == 0) - abort (); - tem->name = current_subfile->name; - tem->prev_index = header_file_prev_index; -} - -static char * -pop_subfile () -{ - register char *name; - register struct subfile_stack *link = subfile_stack; - - if (link == 0) - abort (); - - name = link->name; - subfile_stack = link->next; - header_file_prev_index = link->prev_index; - free (link); - - return name; -} -#endif /* Have N_BINCL */ - -/* Accumulate the misc functions in bunches of 127. - At the end, copy them all into one newly allocated structure. */ - -#define MISC_BUNCH_SIZE 127 - -struct misc_bunch -{ - struct misc_bunch *next; - struct misc_function contents[MISC_BUNCH_SIZE]; -}; - -/* Bunch currently being filled up. - The next field points to chain of filled bunches. */ - -static struct misc_bunch *misc_bunch; - -/* Number of slots filled in current bunch. */ - -static int misc_bunch_index; - -/* Total number of misc functions recorded so far. */ - -static int misc_count; - -static void -init_misc_functions () -{ - misc_count = 0; - misc_bunch = 0; - misc_bunch_index = MISC_BUNCH_SIZE; -} - -static void -record_misc_function (name, address) - char *name; - CORE_ADDR address; -{ - register struct misc_bunch *new; - - if (misc_bunch_index == MISC_BUNCH_SIZE) - { - new = (struct misc_bunch *) xxmalloc (sizeof (struct misc_bunch)); - misc_bunch_index = 0; - new->next = misc_bunch; - misc_bunch = new; - } - misc_bunch->contents[misc_bunch_index].name = name; - misc_bunch->contents[misc_bunch_index].address = address; - misc_bunch_index++; - misc_count++; -} - -static int -compare_misc_functions (fn1, fn2) - struct misc_function *fn1, *fn2; -{ - /* Return a signed result based on unsigned comparisons - so that we sort into unsigned numeric order. */ - if (fn1->address < fn2->address) - return -1; - if (fn1->address > fn2->address) - return 1; - return 0; -} - -static void -discard_misc_bunches () -{ - register struct misc_bunch *next; - - while (misc_bunch) - { - next = misc_bunch->next; - free (misc_bunch); - misc_bunch = next; - } -} - -/* INCLINK nonzero means bunches are from an incrementally-linked file. - Add them to the existing bunches. - Otherwise INCLINK is zero, and we start from scratch. */ -static void -condense_misc_bunches (inclink) - int inclink; -{ - register int i, j; - register struct misc_bunch *bunch; -#ifdef NAMES_HAVE_UNDERSCORE - int offset = 1; -#else - int offset = 0; -#endif - - if (inclink) - { - misc_function_vector - = (struct misc_function *) - xrealloc (misc_function_vector, (misc_count + misc_function_count) - * sizeof (struct misc_function)); - j = misc_function_count; - } - else - { - misc_function_vector - = (struct misc_function *) - xxmalloc (misc_count * sizeof (struct misc_function)); - j = 0; - } - - bunch = misc_bunch; - while (bunch) - { - for (i = 0; i < misc_bunch_index; i++) - { - misc_function_vector[j] = bunch->contents[i]; - misc_function_vector[j].name - = obconcat (misc_function_vector[j].name - + (misc_function_vector[j].name[0] == '_' ? offset : 0), - "", ""); - j++; - } - bunch = bunch->next; - misc_bunch_index = MISC_BUNCH_SIZE; - } - - if (inclink) - misc_function_count += misc_count; - else - misc_function_count = j; - - /* Sort the misc functions by address. */ - - qsort (misc_function_vector, misc_function_count, - sizeof (struct misc_function), - compare_misc_functions); -} - -/* Call sort_syms to sort alphabetically - the symbols of each block of each symtab. */ - -static int -compare_symbols (s1, s2) - struct symbol **s1, **s2; -{ - register int namediff; - - /* Compare the initial characters. */ - namediff = SYMBOL_NAME (*s1)[0] - SYMBOL_NAME (*s2)[0]; - if (namediff != 0) return namediff; - - /* If they match, compare the rest of the names. */ - namediff = strcmp (SYMBOL_NAME (*s1), SYMBOL_NAME (*s2)); - if (namediff != 0) return namediff; - - /* For symbols of the same name, registers should come first. */ - return ((SYMBOL_CLASS (*s2) == LOC_REGISTER) - - (SYMBOL_CLASS (*s1) == LOC_REGISTER)); -} - -static void sort_symtab_syms (); - -static void -sort_syms () -{ - register struct symtab *s; - - for (s = symtab_list; s; s = s->next) - sort_symtab_syms (s); -} - -static void -sort_symtab_syms (s) - register struct symtab *s; -{ - register struct blockvector *bv = BLOCKVECTOR (s); - int nbl = BLOCKVECTOR_NBLOCKS (bv); - int i; - register struct block *b; - - /* Note that in the following sort, we always make sure that - register debug symbol declarations always come before regular - debug symbol declarations (as might happen when parameters are - then put into registers by the compiler). We do this by a - correct compare in compare_symbols, and by the reversal of the - symbols if we don't sort. This works as long as a register debug - symbol always comes after a parameter debug symbol. */ - - /* This is no longer necessary; lookup_block_symbol now always - prefers some other declaration over a parameter declaration. We - still sort the thing (that is necessary), but we don't reverse it - if we shouldn't sort it. */ - - for (i = 0; i < nbl; i++) - { - b = BLOCKVECTOR_BLOCK (bv, i); - if (BLOCK_SHOULD_SORT (b)) - qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b), - sizeof (struct symbol *), compare_symbols); - } -} - - -extern struct symtab *psymtab_to_symtab (); - -/* This is the symbol-file command. Read the file, analyze its symbols, - and add a struct symtab to symtab_list. */ - -void -symbol_file_command (name) - char *name; -{ - register int desc; - DECLARE_FILE_HEADERS; - struct nlist *nlist; - char *stringtab; - long buffer; - register int val; - extern void close (); - struct cleanup *old_chain; - struct symtab *symseg; - struct stat statbuf; - - dont_repeat (); - - if (name == 0) - { - if ((symtab_list || partial_symtab_list) - && !query ("Discard symbol table? ", 0)) - error ("Not confirmed."); - if (symfile) - free (symfile); - symfile = 0; - free_all_symtabs (); - free_all_psymtabs (); - return; - } - - if ((symtab_list || partial_symtab_list) - && !query ("Load new symbol table from \"%s\"? ", name)) - error ("Not confirmed."); - - { - char *absolute_name; - desc = openp (getenv ("PATH"), 1, name, O_RDONLY, 0, &absolute_name); - if (desc < 0) - perror_with_name (name); - else - name = absolute_name; - } - - old_chain = make_cleanup (close, desc); - make_cleanup (free_current_contents, &name); - - READ_FILE_HEADERS (desc, name); - - if (NUMBER_OF_SYMBOLS == 0) - { - if (symfile) - free (symfile); - symfile = 0; - free_all_symtabs (); - free_all_psymtabs (); - printf ("%s has no symbol-table; symbols discarded.\n", name); - fflush (stdout); - do_cleanups (old_chain); - return; - } - - printf ("Reading symbol data from %s...", name); - fflush (stdout); - - /* Now read the string table, all at once. */ - val = lseek (desc, STRING_TABLE_OFFSET, 0); - if (val < 0) - perror_with_name (name); - stat (name, &statbuf); - READ_STRING_TABLE_SIZE (buffer); - if (buffer >= 0 && buffer < statbuf.st_size) - stringtab = (char *) alloca (buffer); - else - stringtab = NULL; - if (stringtab == NULL) - error ("ridiculous string table size: %d bytes", name, buffer); - - bcopy (&buffer, stringtab, sizeof buffer); - val = myread (desc, stringtab + sizeof buffer, buffer - sizeof buffer); - if (val < 0) - perror_with_name (name); - - /* Throw away the old symbol table. */ - - if (symfile) - free (symfile); - symfile = 0; - free_all_symtabs (); - free_all_psymtabs (); - - /* Empty the hash table of global syms looking for values. */ - bzero (global_sym_chain, sizeof global_sym_chain); - -#ifdef READ_GDB_SYMSEGS - /* That puts us at the symsegs. Read them. */ - symseg_chain = read_symsegs (desc, name); - hash_symsegs (); - - /* Free the symtabs made by read_symsegs, but not their contents, - which have been copied into symtabs on symtab_list. */ - for (symseg = symseg_chain; symseg; symseg = symseg->next) - { - int i; - struct sourcevector *sv = (struct sourcevector *) symseg->linetable; - - for (i = 0; i < sv->length; i++) - { - int j; - struct source *source = sv->source[i]; - struct symtab *sp1 - = (struct symtab *) xxmalloc (sizeof (struct symtab)); - - bcopy (symseg, sp1, sizeof (struct symtab)); - sp1->filename = savestring (source->name, strlen (source->name)); - sp1->linetable = &source->contents; - sp1->free_code = free_nothing; - sp1->free_ptr = (i == 0) ? (char *) symseg : 0; - - sp1->next = symtab_list; - symtab_list = sp1; - } - } -#else - /* Where people are using the 4.2 ld program, must not check for - symsegs, because that ld puts randonm garbage at the end of - the output file and that would trigger an error message. */ - symseg_chain = 0; -#endif - - /* Position to read the symbol table. Do not read it all at once. */ - val = lseek (desc, SYMBOL_TABLE_OFFSET, 0); - if (val < 0) - perror_with_name (name); - - /* Don't put these on the cleanup chain; they need to stick around - until the next call to symbol_file_command. *Then* we'll free - them. */ - free_header_files (); - init_header_files (); - - init_misc_functions (); - make_cleanup (discard_misc_bunches, 0); - - free_pendings = 0; - pending_blocks = 0; - file_symbols = 0; - global_symbols = 0; - make_cleanup (really_free_pendings, 0); - - /* Now that the symbol table data of the executable file are all in core, - process them and define symbols accordingly. Closes desc. */ - - read_dbx_symtab (desc, stringtab, NUMBER_OF_SYMBOLS, 0, 0, 0); - - /* Go over the misc functions and install them in vector. */ - - condense_misc_bunches (0); - - /* Don't allow char * to have a typename (else would get caddr_t.) */ - - TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0; - - /* Make a default for file to list. */ - - symfile = savestring (name, strlen (name)); - - /* Call to select_source_symtab used to be here; it was using too - much time. I'll make sure that list_sources can handle the lack - of current_source_symtab */ - - do_cleanups (old_chain); /* Descriptor closed here */ - - /* Free the symtabs made by read_symsegs, but not their contents, - which have been copied into symtabs on symtab_list. */ - while (symseg_chain) - { - register struct symtab *s = symseg_chain->next; - free (symseg_chain); - symseg_chain = s; - } - - if (!partial_symtab_list) - printf ("\n(no debugging symbols found)..."); - - printf ("done.\n"); - fflush (stdout); -} - -/* Return name of file symbols were loaded from, or 0 if none.. */ - -char * -get_sym_file () -{ - return symfile; -} - -/* Buffer for reading the symbol table entries. */ -static struct nlist symbuf[4096]; -static int symbuf_idx; -static int symbuf_end; - -/* I/O descriptor for reading the symbol table. */ -static int symtab_input_desc; - -/* The address of the string table - of the object file we are reading (as copied into core). */ -static char *stringtab_global; - -/* Refill the symbol table input buffer - and set the variables that control fetching entries from it. - Reports an error if no data available. - This function can read past the end of the symbol table - (into the string table) but this does no harm. */ - -static int -fill_symbuf () -{ - int nbytes = myread (symtab_input_desc, symbuf, sizeof (symbuf)); - if (nbytes <= 0) - error ("error or end of file reading symbol table"); - symbuf_end = nbytes / sizeof (struct nlist); - symbuf_idx = 0; - return 1; -} - -/* dbx allows the text of a symbol name to be continued into the - next symbol name! When such a continuation is encountered - (a \ at the end of the text of a name) - call this function to get the continuation. */ - -static char * -next_symbol_text () -{ - if (symbuf_idx == symbuf_end) - fill_symbuf (); - symnum++; - return symbuf[symbuf_idx++].n_un.n_strx + stringtab_global; -} - -/* - * Initializes storage for all of the partial symbols that will be - * created by read_dbx_symtab and subsidiaries. - */ -void -init_psymbol_list (total_symbols) - int total_symbols; -{ - /* Current best guess is that there are approximately a twentieth - of the total symbols (in a debugging file) are global or static - oriented symbols */ - global_psymbols_allocated = total_symbols / 10; - static_psymbols_allocated = total_symbols / 10; - next_ps_global = global_psymbols = (struct partial_symbol *) - xmalloc (global_psymbols_allocated * sizeof (struct partial_symbol)); - next_ps_static = static_psymbols = (struct partial_symbol *) - xmalloc (static_psymbols_allocated * sizeof (struct partial_symbol)); -} - -/* - * Initialize the list of bincls to contain none and have some - * allocated. - */ -static void -init_bincl_list (number) - int number; -{ - bincls_allocated = number; - next_bincl = bincl_list = (struct header_file_location *) - xmalloc (bincls_allocated * sizeof(struct header_file_location)); -} - -/* - * Add a bincl to the list. - */ -static void -add_bincl_to_list (pst, name, instance) - struct partial_symtab *pst; - char *name; - int instance; -{ - if (next_bincl >= bincl_list + bincls_allocated) - { - int offset = next_bincl - bincl_list; - bincls_allocated *= 2; - bincl_list = (struct header_file_location *) - xrealloc (bincl_list, - bincls_allocated * sizeof (struct header_file_location)); - next_bincl = bincl_list + offset; - } - next_bincl->pst = pst; - next_bincl->instance = instance; - next_bincl++->name = name; -} - -/* - * Given a name, value pair, find the corresponding - * bincl in the list. Return the partial symtab associated - * with that header_file_location. - */ -struct partial_symtab * -find_corresponding_bincl_psymtab (name, instance) - char *name; - int instance; -{ - struct header_file_location *bincl; - - for (bincl = bincl_list; bincl < next_bincl; bincl++) - if (bincl->instance == instance - && !strcmp (name, bincl->name)) - return bincl->pst; - - return (struct partial_symtab *) 0; -} - -/* - * Free the storage allocated for the bincl list. - */ -static void -free_bincl_list () -{ - free (bincl_list); - bincls_allocated = 0; -} - -static struct partial_symtab *start_psymtab (); -static void add_psymtab_dependency (); -static void end_psymtab(); - -/* Given pointers to an a.out symbol table in core containing dbx - style data, setup partial_symtab's describing each source file for - which debugging information is available. NLISTLEN is the number - of symbols in the symbol table. All symbol names are given as - offsets relative to STRINGTAB. - - I have no idea whether or not this routine should be setup to deal - with inclinks. It seems reasonable to me that they be dealt with - standardly, so I am not going to make a strong effort to deal with - them here. - */ - -static void process_symbol_for_psymtab (); - -static void -read_dbx_symtab (desc, stringtab, nlistlen, inclink, text_addr, text_size) - int desc; - register char *stringtab; - register int nlistlen; - int inclink; - unsigned text_addr; - int text_size; -{ - register char *namestring; - register struct symbol *sym, *prev; - int hash; - int num_object_files = 0; - int past_first_source_file = 0; - struct cleanup *old_chain; - int current_text_start, current_file_symbol_start; - struct pending *global_symbols, *static_symbols; - int nsl; /* Length of namestring, when needed */ - - /* Current partial symtab */ - struct partial_symtab *pst; - - /* List of current psymtab's include files */ - char **psymtab_include_list; - int includes_allocated; - int includes_used; - - /* Index within current psymtab dependency list */ - struct partial_symtab **dependency_list; - int dependencies_used, dependencies_allocated; - - /* Setup a define to deal cleanly with the underscore problem */ - -#ifdef NAMES_HAVE_UNDERSCORE -#define HASH_OFFSET 1 -#else -#define HASH_OFFSET 0 -#endif - - global_symbols = static_symbols = - (struct pending *) 0; - pst = (struct partial_symtab *) 0; - - includes_allocated = 30; - includes_used = 0; - psymtab_include_list = (char **) alloca (includes_allocated * - sizeof (char *)); - - dependencies_allocated = 30; - dependencies_used = 0; - dependency_list = - (struct partial_symtab **) alloca (dependencies_allocated * - sizeof (struct partial_symtab *)); - - old_chain = make_cleanup (free_all_psymtabs, 0); - - /* Init bincl list */ - init_bincl_list (20); - make_cleanup (free_bincl_list, 0); - - /* Setup global partial symbol list */ - init_psymbol_list (nlistlen); - - last_source_file = 0; - -#ifdef END_OF_TEXT_DEFAULT - end_of_text_addr = END_OF_TEXT_DEFAULT; -#endif - - symtab_input_desc = desc; /* This is needed for fill_symbuf below */ - symbuf_end = symbuf_idx = 0; - - for (symnum = 0; symnum < nlistlen; symnum++) - { - struct nlist *bufp; - unsigned char type; - - /* Get the symbol for this run and pull out some info */ - QUIT; /* allow this to be interruptable */ - if (symbuf_idx == symbuf_end) - fill_symbuf (); - bufp = &symbuf[symbuf_idx++]; - type = bufp->n_type; - - /* - * Special cases to speed up readin. - */ - if (type == N_SLINE) continue; - - namestring = bufp->n_un.n_strx ? bufp->n_un.n_strx + stringtab : ""; - - switch (type) - { - /* - * Standard, non-debugger, symbols - */ - - case N_TEXT | N_EXT: - /* Catch etext */ - - if (!strcmp (namestring, "_etext")) - end_of_text_addr = bufp->n_value; - /* Fall through */ - -#ifdef N_NBTEXT - case N_NBTEXT | N_EXT: -#endif -#ifdef N_NBDATA - case N_NBDATA | N_EXT: -#endif -#ifdef N_NBBSS - case N_NBBSS | N_EXT: -#endif - case N_ABS | N_EXT: - case N_DATA | N_EXT: - case N_BSS | N_EXT: - /* Figure out beginning and end of global linker symbol - section and put non-debugger specified symbols on - tmp_symchain */ - - last_global_sym = symnum; - if (!first_global_sym) first_global_sym = symnum; - - record_misc_function (namestring, bufp->n_value); /* Always */ - - continue; - -#ifdef N_NBTEXT - case N_NBTEXT: -#endif - case N_TEXT: - if (!strcmp (namestring + strlen (namestring) - 2, ".o") - || !strncmp (namestring, "-l", 2)) - { - if (num_object_files++ == 1) - first_object_file_end = bufp->n_value; - if (past_first_source_file && pst) - { - end_psymtab (pst, psymtab_include_list, includes_used, - symnum * sizeof (struct nlist), bufp->n_value, - dependency_list, dependencies_used, - next_ps_global, next_ps_static); - pst = (struct partial_symtab *) 0; - includes_used = 0; - dependencies_used = 0; - } - else - past_first_source_file = 1; - } - continue; - - case N_UNDF: - case N_UNDF | N_EXT: - case N_ABS: - case N_DATA: - case N_BSS: -#ifdef N_NBDATA - case N_NBDATA: -#endif -#ifdef N_NBBSS - case N_NBBSS: -#endif - case N_FN: - /* Keep going . . .*/ - - /* - * Special symbol types for GNU - */ -#ifdef N_INDR - case N_INDR: - case N_INDR | N_EXT: -#endif -#ifdef N_SETA - case N_SETA: - case N_SETA | N_EXT: - case N_SETT: - case N_SETT | N_EXT: - case N_SETD: - case N_SETD | N_EXT: - case N_SETB: - case N_SETB | N_EXT: - case N_SETV: - case N_SETV | N_EXT: -#endif - continue; - - /* - * Debugger symbols - */ - - case N_SO: - /* End the current partial symtab and start a new one */ - - if (past_first_source_file && pst) - { - end_psymtab (pst, psymtab_include_list, includes_used, - symnum * sizeof (struct nlist), bufp->n_value, - dependency_list, dependencies_used, - next_ps_global, next_ps_static); - pst = (struct partial_symtab *) 0; - includes_used = 0; - dependencies_used = 0; - } - else - past_first_source_file = 1; - - pst = start_psymtab (namestring, bufp->n_value, - symnum * sizeof (struct nlist), - next_ps_global, next_ps_static); - - continue; - -#ifdef N_BINCL - case N_BINCL: - /* Add this bincl to the bincl_list for future EXCLs. No - need to save the string; it'll be around until - read_dbx_symtab function return */ - add_bincl_to_list (pst, namestring, bufp->n_value); - - /* Fall through */ -#endif - - case N_SOL: - /* Mark down an include file in the current psymtab */ - - psymtab_include_list[includes_used++] = namestring; - if (includes_used >= includes_allocated) - { - char **orig = psymtab_include_list; - - psymtab_include_list = (char **) - alloca ((includes_allocated *= 2) * - sizeof (char *)); - bcopy (orig, psymtab_include_list, - includes_used * sizeof (char *)); -#ifdef DEBUG_INFO - fprintf (stderr, "Had to realloc includes. New size: %d\n", - includes_allocated); -#endif - } - continue; - - case N_FUN: - case N_SSYM: - case N_GSYM: - case N_LSYM: - case N_STSYM: - case N_LCSYM: - case N_ENTRY: -#ifdef N_MAIN - case N_MAIN: -#endif -#ifdef N_BSLINE - case N_BSLINE: -#endif - case N_PC: -#ifdef N_M2C - case N_M2C: - case N_SCOPE: -#endif - /* Process a symbol as appropriate for the type (this - information is contained in the name of the symbol) */ - - if (namestring[0] != '\0') -#if 1 - process_symbol_for_psymtab (namestring); -#else - process_symbol_for_psymtab (namestring, tmp_symchain); -#endif - continue; - -#ifdef N_BINCL - case N_EXCL: - /* Find the corresponding bincl and mark that psymtab on the - psymtab dependency list */ - { - struct partial_symtab *needed_pst = - find_corresponding_bincl_psymtab (namestring, bufp->n_value); - - /* If this include file was defined earlier in this file, - leave it alone. */ - if (needed_pst == pst) continue; - - if (needed_pst) - { - int i; - int found = 0; - - for (i = 0; i < dependencies_used; i++) - if (dependency_list[i] == needed_pst) - { - found = 1; - break; - } - - /* If it's already in the list, skip the rest. */ - if (found) continue; - - dependency_list[dependencies_used++] = needed_pst; - if (dependencies_used >= dependencies_allocated) - { - struct partial_symtab **orig = dependency_list; - dependency_list = - (struct partial_symtab **) - alloca ((dependencies_allocated *= 2) - * sizeof (struct partial_symtab *)); - bcopy (orig, dependency_list, - (dependencies_used - * sizeof (struct partial_symtab *))); -#ifdef DEBUG_INFO - fprintf (stderr, "Had to reallocate dependency list.\n"); - fprintf (stderr, "New dependencies allocated: %d\n", - dependencies_allocated); -#endif - } - } - else - error ("Invalid symbol data: \"repeated\" header file not previously seen, at symtab pos %d.", - symnum); - } - continue; - - case N_EINCL: -#endif -#ifdef N_DSLINE - case N_DSLINE: -#endif - case N_LENG: - case N_BCOMM: - case N_ECOMM: - case N_ECOML: - case N_FNAME: - case N_SLINE: - case N_RSYM: - case N_PSYM: - case N_LBRAC: - case N_RBRAC: - /* These symbols aren't interesting; don't worry about them */ - - continue; - - default: - /* If we haven't found it yet, we've got problems */ - - if (IGNORE_SYMBOL (type)) - continue; - - fatal ("Bad symbol type 0x%x encountered in gdb scan", type); - } - } - - if (last_source_file) - { - end_psymtab (pst, psymtab_include_list, includes_used, - symnum * sizeof (struct nlist), end_of_text_addr, - dependency_list, dependencies_used, - next_ps_global, next_ps_static); - includes_used = 0; - dependencies_used = 0; - pst = (struct partial_symtab *) 0; - } - - free_bincl_list (); - discard_cleanups (old_chain); -} - -/* - * Take a single symbol (name: NAME) and process it (add it to the - * app psymbol list or not). - */ -static void -process_symbol_for_psymtab (name) - char *name; -{ - char *p = (char *) index(name, ':') + 1; - int deftype; - struct partial_symbol *sym; - enum { T_IGNORE, T_STATIC, T_GLOBAL } symbol_type; - enum namespace ns = UNDEF_NAMESPACE; - enum address_class class; - int hash; - - if (p == (char *) 0x1) - /* No ":" ; I guess it's not a debuggging symbol */ - return; - - if ((*p >= '0' && *p <= '9') || *p == '(') - deftype = 'l'; - else - deftype = *p; - - /* Figure out how to handle this symbol */ - switch (deftype) - { - /* T is a struct/union/enum, t is a typedef */ - case 'T': - symbol_type = T_STATIC; - ns = STRUCT_NAMESPACE; - class = LOC_TYPEDEF; - break; - case 't': - symbol_type = T_STATIC; - ns = VAR_NAMESPACE; - class = LOC_TYPEDEF; - break; - case 'c': - symbol_type = T_STATIC; - ns = VAR_NAMESPACE; - class = LOC_CONST; - break; - case 'S': - symbol_type = T_STATIC; - ns = VAR_NAMESPACE; - class = LOC_STATIC; - break; - case 'f': - symbol_type = T_STATIC; - ns = VAR_NAMESPACE; - class = LOC_BLOCK; - break; - case 'F': - symbol_type = T_GLOBAL; - ns = VAR_NAMESPACE; - class = LOC_BLOCK; - break; - case 'G': - symbol_type = T_GLOBAL; - ns = VAR_NAMESPACE; - class = LOC_STATIC; - break; - default: - return; - } - - /* Create the symbol and store it on the list */ - /* There's a better algorithm possible for the allocation; figure - out how far through the symbol table we are and do a reestimate */ - if (symbol_type == T_STATIC) - { - if (next_ps_static >= static_psymbols + static_psymbols_allocated) - { - static_psymbols = (struct partial_symbol *) - xrealloc (static_psymbols, - (static_psymbols_allocated * 2 - * sizeof (struct partial_symbol))); - /* Next assumes we only went one over. Should be good if - program works correctly */ - next_ps_static = static_psymbols + static_psymbols_allocated; - static_psymbols_allocated *= 2; -#ifdef DEBUGINFO - fprintf(stderr, "debuginfo: Had to realloc statics\n"); -#endif - } - sym = next_ps_static++; - } - else - { - if (next_ps_global >= global_psymbols + global_psymbols_allocated) - { - global_psymbols = (struct partial_symbol *) - xrealloc (global_psymbols, - (global_psymbols_allocated * 2 - * sizeof (struct partial_symbol))); - next_ps_global = global_psymbols + global_psymbols_allocated; - global_psymbols_allocated *= 2; -#ifdef DEBUGINFO - fprintf(stderr, "debuginfo: Had to realloc globals\n"); -#endif - } - sym = next_ps_global++; - } - - SYMBOL_NAME(sym) = (char *) obstack_alloc (psymbol_obstack, - p - name); - strncpy(SYMBOL_NAME(sym), name, p - name - 1); - SYMBOL_NAME(sym)[p - name - 1] = '\0'; - SYMBOL_NAMESPACE(sym) = ns; - SYMBOL_CLASS(sym) = class; -} -#undef HASH_OFFSET - -/* - * Allocate and partially fill a partial symtab. It will be - * completely filled at the end of the symbol list. - */ -static struct partial_symtab * -start_psymtab (filename, textlow, ldsymoff, global_syms, static_syms) - char *filename; - int textlow; - int ldsymoff; - struct partial_symbol *global_syms; - struct partial_symbol *static_syms; -{ - struct partial_symtab *result = - (struct partial_symtab *) obstack_alloc (psymbol_obstack, - sizeof (struct partial_symtab)); - - result->filename = - (char *) obstack_alloc (psymbol_obstack, - strlen (filename) + 1); - strcpy (result->filename, filename); - - result->textlow = textlow; - result->ldsymoff = ldsymoff; - - result->readin = 0; - - result->globals_offset = global_syms - global_psymbols; - result->statics_offset = static_syms - static_psymbols; - - result->n_global_syms = 0; - result->n_static_syms = 0; - - return result; -} - -static int -compare_psymbols (s1, s2) - register struct partial_symbol *s1, *s2; -{ - register char - *st1 = SYMBOL_NAME (s1), - *st2 = SYMBOL_NAME (s2); - - return (st1[0] - st2[0] ? st1[0] - st2[0] : - strcmp (st1 + 1, st2 + 1)); -} - - -/* Close off the current usage of a partial_symbol table entry. This - involves setting the correct number of includes (with a realloc), - setting the high text mark, setting the symbol length in the - executable, and setting the length of the global and static lists - of psymbols. - - The global symbols and static symbols are then seperately sorted. - - Then the partial symtab is put on the global list. - *** List variables and peculiarities of same. *** - */ -static void -end_psymtab (pst, include_list, num_includes, capping_symbol_offset, - capping_text, dependency_list, number_dependencies, - capping_global, capping_static) - struct partial_symtab *pst; - char **include_list; - int num_includes; - int capping_symbol_offset; - int capping_text; - struct partial_symtab **dependency_list; - int number_dependencies; - struct partial_symbol *capping_global, *capping_static; -{ - int i; - - pst->ldsymlen = capping_symbol_offset - pst->ldsymoff; - pst->texthigh = capping_text; - - pst->n_global_syms = - capping_global - (global_psymbols + pst->globals_offset); - pst->n_static_syms = - capping_static - (static_psymbols + pst->statics_offset); - - pst->dependencies = (struct partial_symtab **) - obstack_alloc (psymbol_obstack, - number_dependencies * sizeof (struct partial_symtab *)); - bcopy (dependency_list, pst->dependencies, - number_dependencies * sizeof (struct partial_symtab *)); - pst->number_of_dependencies = number_dependencies; - - for (i = 0; i < num_includes; i++) - { - /* Eventually, put this on obstack */ - struct partial_symtab *subpst = - (struct partial_symtab *) - obstack_alloc (psymbol_obstack, - sizeof (struct partial_symtab)); - - subpst->filename = - (char *) obstack_alloc (psymbol_obstack, - strlen (include_list[i]) + 1); - strcpy (subpst->filename, include_list[i]); - - subpst->ldsymoff = - subpst->ldsymlen = - subpst->textlow = - subpst->texthigh = 0; - subpst->readin = 0; - - subpst->dependencies = (struct partial_symtab **) - obstack_alloc (psymbol_obstack, - sizeof (struct partial_symtab *)); - subpst->dependencies[0] = pst; - subpst->number_of_dependencies = 1; - - subpst->globals_offset = - subpst->n_global_syms = - subpst->statics_offset = - subpst->n_static_syms = 0; - - subpst->next = partial_symtab_list; - partial_symtab_list = subpst; - } - - /* Sort the global list; don't sort the static list */ - qsort (global_psymbols + pst->globals_offset, pst->n_global_syms, - sizeof (struct partial_symbol), compare_psymbols); - - /* Put the psymtab on the psymtab list */ - pst->next = partial_symtab_list; - partial_symtab_list = pst; -} - -/* - * Read in all of the symbols for a given psymtab for real. Return - * the value of the symtab you create. Do not free the storage - * allocated to the psymtab; it may have pointers to it. - */ -static void scan_file_globals (); -static void read_ofile_symtab (); - -struct symtab * -psymtab_to_symtab(pst) - struct partial_symtab *pst; -{ - int desc; - DECLARE_FILE_HEADERS; - char *stringtab; - struct partial_symtab **list_patch; - int stsize, val; - struct stat statbuf; - struct cleanup *old_chain; - extern void close (); - int i; - struct symtab *result; - char *name = symfile; /* Some of the macros require the */ - /* variable "name" to be defined in */ - /* the context in which they execute */ - /* (Yech!) */ - - if (!pst) - return 0; - - if (pst->readin) - { - fprintf (stderr, "Psymtab for %s already read in. Shouldn't happen.\n", - pst->filename); - return 0; - } - - if (!name) - error("No symbol file currently specified; use command symbol-file"); - - /* Read in all partial symbtabs on which this one is dependent */ - for (i = 0; i < pst->number_of_dependencies; i++) - if (!pst->dependencies[i]->readin) - psymtab_to_symtab (pst->dependencies[i]); - - if (pst->ldsymlen) /* Otherwise it's a dummy */ - { - /* Open symbol file and read in string table */ - stat (name, &statbuf); - desc = open(name, O_RDONLY, 0); /* symbol_file_command - guarrantees that the symbol file name - will be absolute, so there is no - need for openp */ - - old_chain = make_cleanup (close, desc); - - if (desc < 0) - error("Symbol file not readable"); - - READ_FILE_HEADERS (desc, name); - - /* Read in the string table */ - lseek (desc, STRING_TABLE_OFFSET, L_SET); - READ_STRING_TABLE_SIZE (stsize); - if (stsize >= 0 && stsize < statbuf.st_size) - stringtab = (char *) alloca (stsize); - else - stringtab = NULL; - if (stringtab == NULL) - error ("ridiculous string table size: %d bytes", name, stsize); - - bcopy (&stsize, stringtab, sizeof stsize); - val = myread (desc, stringtab + sizeof stsize, stsize - sizeof stsize); - if (val < 0) - perror_with_name (name); - - /* Init stuff necessary for reading in symbols */ - free_pendings = 0; - pending_blocks = 0; - file_symbols = 0; - global_symbols = 0; - make_cleanup (really_free_pendings, 0); - - /* Read in this files symbols */ - lseek (desc, SYMBOL_TABLE_OFFSET, L_SET); - read_ofile_symtab (desc, stringtab, pst->ldsymoff, - pst->ldsymlen, pst->textlow, - pst->texthigh - pst->textlow, 0); - sort_symtab_syms (symtab_list); /* At beginning since just added */ - - /* Match with global symbols */ - lseek (desc, SYMBOL_TABLE_OFFSET, L_SET); - scan_file_globals (desc, stringtab, - first_global_sym * sizeof(struct nlist), - last_global_sym - first_global_sym + 1); - - do_cleanups (old_chain); - } - - /* Find pst in list, prune it, and free it's storage */ - for (list_patch = &partial_symtab_list; - *list_patch && *list_patch != pst; - list_patch = &((*list_patch)->next)) - ; - - if (!(*list_patch)) /* pst not in list. Don't worry about it? */ - fatal ("internal: psymtab_to_symtab called with non-listed pst"); - - *list_patch = (*list_patch)->next; /* Prune */ - - pst->readin = 1; /* Mark as read in */ - - /* It's the last one if we actually read something in */ - if (pst->ldsymlen) - return symtab_list; - else - /* Search through list for correct name. */ - for (result = symtab_list; result; result = result->next) - if (!strcmp (result->filename, pst->filename)) - return result; - - return 0; -} - -/* - * Scan through all of the global symbols defined in the object file, - * assigning values to the debugging symbols that need to be assigned - * to. - * - * DESC is the file descriptor of the symbol file, with the seek - * pointer pointing at the beginning of the symbol table. - * STRINGTAB is the file's string table, already read in. - * OFFSET is the offset (in bytes) of the beginning of the global - * symbols from the beginning of the symbol table. - * NUMSYMS is the number of symbols that have to be checked. - */ -static void -scan_file_globals (desc, stringtab, offset, numsyms) - int desc; - char *stringtab; - int offset; - int numsyms; -{ - int hash; - - lseek(desc, offset, L_INCR); - symtab_input_desc = desc; - symbuf_end = symbuf_idx = 0; - - for (symnum = 0; symnum < numsyms; symnum++) - { - struct nlist *bufp; - unsigned char type; - char *namestring; - - QUIT; - if (symbuf_idx == symbuf_end) - fill_symbuf (); - - bufp = &symbuf[symbuf_idx++]; - type = bufp->n_type; - - if (type & N_EXT && type != N_EXT) - { - struct symbol *sym, *prev; - - namestring = bufp->n_un.n_strx ? - bufp->n_un.n_strx + stringtab : ""; - prev = (struct symbol *) 0; - - /* Get the hash index and check all the symbols - under that hash index. */ - -#ifdef NAMES_HAVE_UNDERSCORE - hash = hashname (namestring + 1); -#else /* ! NAMES_HAVE_UNDERSCORE */ - hash = hashname (namestring); -#endif /* ! NAMES_HAVE_UNDERSCORE */ - for (sym = global_sym_chain[hash]; sym;) - { - if ( -#ifdef NAMES_HAVE_UNDERSCORE - *namestring == '_' - && namestring[1] == SYMBOL_NAME (sym)[0] - && !strcmp(namestring + 2, SYMBOL_NAME (sym) + 1) -#else /* ! NAMES_HAVE_UNDERSCORE */ - namestring[0] == SYMBOL_NAME (sym) [0] - && !strcmp(namestring + 1, SYMBOL_NAME(sym) + 1) -#endif /* ! NAMES_HAVE_UNDERSCORE */ - ) - { - /* Splice this symbol out of the hash chain and - assign the value we have to it. */ - if (prev) - SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym); - else - global_sym_chain[hash] - = (struct symbol *) SYMBOL_VALUE (sym); - SYMBOL_VALUE (sym) = bufp->n_value; - if (prev) - sym = (struct symbol *) SYMBOL_VALUE (prev); - else - sym = global_sym_chain[hash]; - break; /* Only one reference per file */ - } - else - { - prev = sym; - sym = (struct symbol *) SYMBOL_VALUE (sym); - } - } - } - } - /* There shouldn't be anything left on the hash list at this point. - If there is, we have done something wrong. For right now it's - worth checking, until I get the bugs out. */ - /* Sigh. Unfortunately, the above is not true. If an extern - variable is mentioned in an include file (or a program) and the - variable is never either referenced or defined, there will be a - debugger symbol with no "real" symbol. Oh well. */ -} - -/* - * Read in a defined section of a specific object file's symbols. - * - * DESC is the file descriptor for the file, positioned at the - * beginning of the symtab - * STRINGTAB is a pointer to the files string - * table, already read in - * SYM_OFFSET is the offset within the file of - * the beginning of the symbols we want to read, NUM_SUMBOLS is the - * number of symbols to read - * TEXT_OFFSET is the offset to be added to - * all values of symbols coming in and - * TEXT_SIZE is the size of the text segment read in. - * OFFSET is a flag which indicates that the value of all of the - * symbols should be offset by TEXT_OFFSET (for the purposes of - * incremental linking). - */ - -static void -read_ofile_symtab (desc, stringtab, sym_offset, - sym_size, text_offset, text_size, offset) - int desc; - register char *stringtab; - int sym_offset; - int sym_size; - int text_offset; - int text_size; - int offset; -{ - register char *namestring; - register struct symbol *sym, *prev; - int hash; - struct cleanup *old_chain; - struct nlist *bufp; - unsigned char type; -#ifdef N_BINCL - subfile_stack = 0; -#endif - - stringtab_global = stringtab; - last_source_file = 0; - - symtab_input_desc = desc; - symbuf_end = symbuf_idx = 0; - lseek(desc, sym_offset, L_INCR); - - fill_symbuf(); - bufp = &symbuf[symbuf_idx]; - if ((unsigned char) bufp->n_type != N_SO) - fatal("First symbol in segment of executable not a source symbol"); - - for (symnum = 0; - symnum < sym_size / sizeof(struct nlist); - symnum++) - { - QUIT; /* Allow this to be interruptable */ - if (symbuf_idx == symbuf_end) - fill_symbuf(); - bufp = &symbuf[symbuf_idx++]; - type = bufp->n_type; - - if (offset && - (type == N_TEXT || type == N_DATA || type == N_BSS)) - bufp->n_value += text_offset; - - namestring = bufp->n_un.n_strx ? bufp->n_un.n_strx + stringtab : ""; - - if (type & N_STAB) - process_one_symbol(type, bufp->n_desc, - bufp->n_value, namestring); - /* We skip checking for a new .o or -l file; that should never - happen in this routine. */ - else if (type == N_TEXT - && !strcmp (namestring, GCC_COMPILED_FLAG_SYMBOL)) - processing_gcc_compilation = 1; - else if (type & N_EXT || type == N_TEXT -#ifdef N_NBTEXT - || type == N_NBTEXT -#endif - ) - /* Global symbol: see if we came across a dbx defintion for - a corresponding symbol. If so, store the value. Remove - syms from the chain when their values are stored, but - search the whole chain, as there may be several syms from - different files with the same name. */ - /* This is probably not true. Since the files will be read - in one at a time, each reference to a global symbol will - be satisfied in each file as it appears. So we skip this - section. */ - &stringtab_global; /* For debugger; am I right? */ - } - end_symtab (text_offset + text_size); -} - -static int -hashname (name) - char *name; -{ - register char *p = name; - register int total = p[0]; - register int c; - - c = p[1]; - total += c << 2; - if (c) - { - c = p[2]; - total += c << 4; - if (c) - total += p[3] << 6; - } - - /* Ensure result is positive. */ - if (total < 0) total += (1000 << 6); - return total % HASHSIZE; -} - -/* Put all appropriate global symbols in the symseg data - onto the hash chains so that their addresses will be stored - when seen later in loader global symbols. */ - -static void -hash_symsegs () -{ - /* Look at each symbol in each block in each symseg symtab. */ - struct symtab *s; - for (s = symseg_chain; s; s = s->next) - { - register int n; - for (n = BLOCKVECTOR_NBLOCKS (BLOCKVECTOR (s)) - 1; n >= 0; n--) - { - register struct block *b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), n); - register int i; - for (i = BLOCK_NSYMS (b) - 1; i >= 0; i--) - { - register struct symbol *sym = BLOCK_SYM (b, i); - - /* Put the symbol on a chain if its value is an address - that is figured out by the loader. */ - - if (SYMBOL_CLASS (sym) == LOC_EXTERNAL) - { - register int hash = hashname (SYMBOL_NAME (sym)); - SYMBOL_VALUE (sym) = (int) global_sym_chain[hash]; - global_sym_chain[hash] = sym; - SYMBOL_CLASS (sym) = LOC_STATIC; - } - } - } - } -} - -static void -process_one_symbol (type, desc, value, name) - int type, desc; - CORE_ADDR value; - char *name; -{ - register struct context_stack *new; - - /* Something is wrong if we see real data before - seeing a source file name. */ - - if (last_source_file == 0 && type != N_SO) - { - /* Currently this ignores N_ENTRY on Gould machines, N_NSYM on machines - where that code is defined, and all symbols on the Convex. */ - if (IGNORE_SYMBOL (type)) - return; - - error ("Invalid symbol data: does not start by identifying a source file."); - } - - switch (type) - { - case N_FUN: - case N_FNAME: - /* Either of these types of symbols indicates the start of - a new function. We must process its "name" normally for dbx, - but also record the start of a new lexical context, and possibly - also the end of the lexical context for the previous function. */ - - within_function = 1; - if (context_stack_depth > 0) - { - new = &context_stack[--context_stack_depth]; - /* Make a block for the local symbols within. */ - finish_block (new->name, &local_symbols, new->old_blocks, - new->start_addr, value); - } - /* Stack must be empty now. */ - if (context_stack_depth != 0) - error ("Invalid symbol data: unmatched N_LBRAC before symtab pos %d.", - symnum); - - new = &context_stack[context_stack_depth++]; - new->old_blocks = pending_blocks; - new->start_addr = value; - new->name = define_symbol (value, name, desc); - local_symbols = 0; - break; - - case N_LBRAC: - /* This "symbol" just indicates the start of an inner lexical - context within a function. */ - - if (context_stack_depth == context_stack_size) - { - context_stack_size *= 2; - context_stack = (struct context_stack *) - xrealloc (context_stack, - (context_stack_size - * sizeof (struct context_stack))); - } - - new = &context_stack[context_stack_depth++]; - new->depth = desc; - new->locals = local_symbols; - new->old_blocks = pending_blocks; - new->start_addr = value; - new->name = 0; - local_symbols = 0; - break; - - case N_RBRAC: - /* This "symbol" just indicates the end of an inner lexical - context that was started with N_RBRAC. */ - new = &context_stack[--context_stack_depth]; - if (desc != new->depth) - error ("Invalid symbol data: N_LBRAC/N_RBRAC symbol mismatch, symtab pos %d.", symnum); - local_symbols = new->locals; - - /* If this is not the outermost LBRAC...RBRAC pair in the - function, its local symbols preceded it, and are the ones - just recovered from the context stack. Defined the block for them. - - If this is the outermost LBRAC...RBRAC pair, there is no - need to do anything; leave the symbols that preceded it - to be attached to the function's own block. */ - if (local_symbols && context_stack_depth > 1) - { - /* Muzzle a compiler bug that makes end > start. */ - if (new->start_addr > value) - new->start_addr = value; - /* Make a block for the local symbols within. */ - finish_block (0, &local_symbols, new->old_blocks, - new->start_addr + last_source_start_addr, - value + last_source_start_addr); - } - break; - - case N_FN: - /* This kind of symbol supposedly indicates the start - of an object file. In fact this type does not appear. */ - break; - - case N_SO: - /* This type of symbol indicates the start of data - for one source file. - Finish the symbol table of the previous source file - (if any) and start accumulating a new symbol table. */ - if (last_source_file) - end_symtab (value); - start_symtab (name, value); - break; - - case N_SOL: - /* This type of symbol indicates the start of data for - a sub-source-file, one whose contents were copied or - included in the compilation of the main source file - (whose name was given in the N_SO symbol.) */ - start_subfile (name); - break; - -#ifdef N_BINCL - case N_BINCL: - push_subfile (); - add_new_header_file (name, value); - start_subfile (name); - break; - - case N_EINCL: - start_subfile (pop_subfile ()); - break; - - case N_EXCL: - add_old_header_file (name, value); - break; -#endif /* have N_BINCL */ - - case N_SLINE: - /* This type of "symbol" really just records - one line-number -- core-address correspondence. - Enter it in the line list for this symbol table. */ - record_line (desc, value); - break; - - case N_BCOMM: - case N_ECOMM: - case N_ECOML: - case N_LENG: - break; - - default: - if (name) - define_symbol (value, name, desc); - } -} - -/* This function was added for C++ functionality. I presume that it - condenses the bunches formed by reading in an additional .o file - (incremental linking). */ - -static void -condense_addl_misc_bunches () -{ - register int i, j; - register struct misc_bunch *bunch; -#ifdef NAMES_HAVE_UNDERSCORE - int offset = 1; -#else - int offset = 0; -#endif - - misc_function_vector - = (struct misc_function *) xrealloc (misc_function_vector, - (misc_count + misc_function_count) * sizeof (struct misc_function)); - - j = misc_function_count; - bunch = misc_bunch; - while (bunch) - { - for (i = 0; i < misc_bunch_index; i++) - { - misc_function_vector[j] = bunch->contents[i]; - misc_function_vector[j].name - = concat (misc_function_vector[j].name - + (misc_function_vector[j].name[0] == '_' ? offset : 0), - "", ""); - j++; - } - bunch = bunch->next; - misc_bunch_index = MISC_BUNCH_SIZE; - } - - misc_function_count += misc_count; - - /* Sort the misc functions by address. */ - - qsort (misc_function_vector, misc_function_count, - sizeof (struct misc_function), compare_misc_functions); -} - - -/* Read in another .o file and create a symtab entry for it.*/ - -static void -read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size) - int desc; - register char *stringtab; - register int nlistlen; - unsigned text_addr; - int text_size; -{ - FILE *stream = fdopen (desc, "r"); - register char *namestring; - register struct symbol *sym, *prev; - int hash; - int num_object_files = 0; - -#ifdef N_BINCL - subfile_stack = 0; -#endif - - last_source_file = 0; - bzero (global_sym_chain, sizeof global_sym_chain); - symtab_input_desc = desc; - stringtab_global = stringtab; - fill_symbuf (); - - for (symnum = 0; symnum < nlistlen; symnum++) - { - struct nlist *bufp; - unsigned char type; - - QUIT; /* allow this to be interruptable */ - if (symbuf_idx == symbuf_end) - fill_symbuf (); - bufp = &symbuf[symbuf_idx++]; - type = bufp->n_type & N_TYPE; - namestring = bufp->n_un.n_strx ? bufp->n_un.n_strx + stringtab : ""; - - if( (type == N_TEXT) || (type == N_DATA) || (type == N_BSS) ) - { - /* Relocate this file's symbol table information - to the address it has been loaded into. */ - bufp->n_value += text_addr; - } - - type = bufp->n_type; - - if (type & N_STAB) - process_one_symbol (type, bufp->n_desc, - bufp->n_value, namestring); - /* A static text symbol whose name ends in ".o" - can only mean the start of another object file. - So end the symtab of the source file we have been processing. - This is how we avoid counting the libraries as part - or the last source file. - Also this way we find end of first object file (crt0). */ - else if ((type == N_TEXT -#ifdef N_NBTEXT - || type == N_NBTEXT -#endif - ) - && (!strcmp (namestring + strlen (namestring) - 2, ".o")) - || ! strcmp (namestring, "-l", 2)) - { - if (num_object_files++ == 1) - first_object_file_end = bufp->n_value; - if (last_source_file) - end_symtab (bufp->n_value); - } - else if (type & N_EXT || type == N_TEXT -#ifdef N_NBTEXT - || type == N_NBTEXT -#endif - ) - { - int used_up = 0; - - /* Record the location of _etext. */ - if (type == (N_TEXT | N_EXT) - && !strcmp (namestring, "_etext")) - end_of_text_addr = bufp->n_value; - - /* Global symbol: see if we came across a dbx definition - for a corresponding symbol. If so, store the value. - Remove syms from the chain when their values are stored, - but search the whole chain, as there may be several syms - from different files with the same name. */ - if (type & N_EXT) - { - prev = 0; -#ifdef NAMES_HAVE_UNDERSCORE - hash = hashname (namestring + 1); -#else /* not NAMES_HAVE_UNDERSCORE */ - hash = hashname (namestring); -#endif /* not NAMES_HAVE_UNDERSCORE */ - for (sym = global_sym_chain[hash]; - sym;) - { - if ( -#ifdef NAMES_HAVE_UNDERSCORE - *namestring == '_' - && namestring[1] == SYMBOL_NAME (sym)[0] - && - !strcmp (namestring + 2, SYMBOL_NAME (sym) + 1) -#else /* NAMES_HAVE_UNDERSCORE */ - namestring[0] == SYMBOL_NAME (sym)[0] - && - !strcmp (namestring + 1, SYMBOL_NAME (sym) + 1) -#endif /* NAMES_HAVE_UNDERSCORE */ - ) - { - if (prev) - SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym); - else - global_sym_chain[hash] - = (struct symbol *) SYMBOL_VALUE (sym); - SYMBOL_VALUE (sym) = bufp->n_value; - if (prev) - sym = (struct symbol *) SYMBOL_VALUE (prev); - else - sym = global_sym_chain[hash]; - - used_up = 1; - } - else - { - prev = sym; - sym = (struct symbol *) SYMBOL_VALUE (sym); - } - } - } - - /* Defined global or text symbol: record as a misc function - if it didn't give its address to a debugger symbol above. */ - if (type <= (N_TYPE | N_EXT) - && type != N_EXT - && ! used_up) - record_misc_function (namestring, bufp->n_value); - } - } - - if (last_source_file) - end_symtab (text_addr + text_size); - - fclose (stream); -} - -/* C++: - This function allows the addition of incrementally linked object files. - Since this has a fair amount of code in common with symbol_file_command, - it might be worthwhile to consolidate things, as was done with - read_dbx_symtab and condense_misc_bunches. */ - -void -add_file_command (arg_string) - char* arg_string; -{ - register int desc; - DECLARE_FILE_HEADERS; - struct nlist *nlist; - char *stringtab; - long buffer; - register int val; - extern void close (); - struct cleanup *old_chain; - struct symtab *symseg; - struct stat statbuf; - char *name; - unsigned text_addr; - - if (arg_string == 0) - error ("add-file takes a file name and an address"); - - for( ; *arg_string == ' '; arg_string++ ); - name = arg_string; - for( ; *arg_string && *arg_string != ' ' ; arg_string++ ); - *arg_string++ = (char) 0; - - if (name[0] == 0) - error ("add-file takes a file name and an address"); - - text_addr = parse_and_eval_address (arg_string); - - dont_repeat (); - - if (!query ("add symbol table from filename \"%s\" at text_addr = 0x%x\n", - name, text_addr)) - error ("Not confirmed."); - - desc = open (name, O_RDONLY); - if (desc < 0) - perror_with_name (name); - - old_chain = make_cleanup (close, desc); - make_cleanup (free_current_contents, &name); - - READ_FILE_HEADERS (desc, name); - - if (NUMBER_OF_SYMBOLS == 0) - { - printf ("%s does not have a symbol-table.\n", name); - fflush (stdout); - return; - } - - printf ("Reading symbol data from %s...", name); - fflush (stdout); - - /* Now read the string table, all at once. */ - val = lseek (desc, STRING_TABLE_OFFSET, 0); - if (val < 0) - perror_with_name (name); - stat (name, &statbuf); - READ_STRING_TABLE_SIZE (buffer); - if (buffer >= 0 && buffer < statbuf.st_size) - stringtab = (char *) alloca (buffer); - else - stringtab = NULL; - if (stringtab == NULL) - error ("ridiculous string table size: %d bytes", name, buffer); - - bcopy (&buffer, stringtab, sizeof buffer); - val = myread (desc, stringtab + sizeof buffer, buffer - sizeof buffer); - if (val < 0) - perror_with_name (name); - -#ifdef READ_GDB_SYMSEGS - /* That puts us at the symsegs. Read them. */ - symseg_chain = read_symsegs (desc, name); - hash_symsegs (); - - /* Free the symtabs made by read_symsegs, but not their contents, - which have been copied into symtabs on symtab_list. */ - for (symseg = symseg_chain; symseg; symseg = symseg->next) - { - int i; - struct sourcevector *sv = (struct sourcevector *) symseg->linetable; - - for (i = 0; i < sv->length; i++) - { - int j; - struct source *source = sv->source[i]; - struct symtab *sp1 - = (struct symtab *) xxmalloc (sizeof (struct symtab)); - - bcopy (symseg, sp1, sizeof (struct symtab)); - sp1->filename = savestring (source->name, strlen (source->name)); - sp1->linetable = &source->contents; - sp1->free_code = free_nothing; - sp1->free_ptr = (i == 0) ? (char *) symseg : 0; - - sp1->next = symtab_list; - symtab_list = sp1; - } - } -#else - /* Where people are using the 4.2 ld program, must not check for - symsegs, because that ld puts randonm garbage at the end of - the output file and that would trigger an error message. */ - symseg_chain = 0; -#endif - - /* Position to read the symbol table. Do not read it all at once. */ - val = lseek (desc, SYMBOL_TABLE_OFFSET, 0); - if (val < 0) - perror_with_name (name); - - init_misc_functions (); - make_cleanup (discard_misc_bunches, 0); - init_header_files (); - make_cleanup (free_header_files, 0); - free_pendings = 0; - pending_blocks = 0; - file_symbols = 0; - global_symbols = 0; - make_cleanup (really_free_pendings, 0); - - read_addl_syms (desc, stringtab, NUMBER_OF_SYMBOLS, text_addr, - SIZE_OF_TEXT_SEGMENT); - - - /* Sort symbols alphabetically within each block. */ - - sort_syms (); - - /* Go over the misc functions and install them in vector. */ - - condense_addl_misc_bunches (1); - - /* Don't allow char * to have a typename (else would get caddr_t.) */ - - TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0; - - /* Make a default for file to list. */ - /* Hmmm. I'd say we don't want this in add_file_command, but . . . */ - - select_source_symtab (symtab_list); - - do_cleanups (old_chain); - - /* Free the symtabs made by read_symsegs, but not their contents, - which have been copied into symtabs on symtab_list. */ - while (symseg_chain) - { - register struct symtab *s = symseg_chain->next; - free (symseg_chain); - symseg_chain = s; - } - - printf ("done.\n"); - fflush (stdout); -} - -static struct symbol * -define_symbol (value, string, desc) - int value; - char *string; - int desc; -{ - register struct symbol *sym - = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol)); - char *p = (char *) index (string, ':'); - int deftype; - register int i; - - /* Ignore syms with empty names. */ - if (string[0] == 0) - return 0; - - SYMBOL_NAME (sym) - = (char *) obstack_alloc (symbol_obstack, ((p - string) + 1)); - /* Open-coded bcopy--saves function call time. */ - { - register char *p1 = string; - register char *p2 = SYMBOL_NAME (sym); - while (p1 != p) - *p2++ = *p1++; - *p2++ = '\0'; - } - p++; - /* Determine the type of name being defined. */ - if ((*p >= '0' && *p <= '9') || *p == '(') - deftype = 'l'; - else - deftype = *p++; - - /* c is a special case, not followed by a type-number. - SYMBOL:c=iVALUE for an integer constant symbol. - SYMBOL:c=rVALUE for a floating constant symbol. */ - if (deftype == 'c') - { - if (*p++ != '=') - error ("Invalid symbol data at symtab pos %d.", symnum); - switch (*p++) - { - case 'r': - { - double d = atof (p); - char *value; - - SYMBOL_TYPE (sym) = builtin_type_double; - value = (char *) obstack_alloc (symbol_obstack, sizeof (double)); - bcopy (&d, value, sizeof (double)); - SYMBOL_VALUE_BYTES (sym) = value; - SYMBOL_CLASS (sym) = LOC_CONST; - } - break; - case 'i': - { - SYMBOL_TYPE (sym) = builtin_type_int; - SYMBOL_VALUE (sym) = atoi (p); - SYMBOL_CLASS (sym) = LOC_CONST_BYTES; - } - break; - default: - error ("Invalid symbol data at symtab pos %d.", symnum); - } - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &file_symbols); - return sym; - } - - /* Now usually comes a number that says which data type, - and possibly more stuff to define the type - (all of which is handled by read_type) */ - - if (deftype == 'p' && *p == 'F') - /* pF is a two-letter code that means a function parameter in Fortran. - The type-number specifies the type of the return value. - Translate it into a pointer-to-function type. */ - { - p++; - SYMBOL_TYPE (sym) - = lookup_pointer_type (lookup_function_type (read_type (&p))); - } - else - { - struct type *type = read_type (&p); - - if ((deftype == 'F' || deftype == 'f') - && TYPE_CODE (type) != TYPE_CODE_FUNC) - SYMBOL_TYPE (sym) = lookup_function_type (type); - else - SYMBOL_TYPE (sym) = type; - } - - switch (deftype) - { - case 'f': - SYMBOL_CLASS (sym) = LOC_BLOCK; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &file_symbols); - break; - - case 'F': - SYMBOL_CLASS (sym) = LOC_BLOCK; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &global_symbols); - break; - - case 'G': - /* For a class G (global) symbol, it appears that the - value is not correct. It is necessary to search for the - corresponding linker definition to find the value. - These definitions appear at the end of the namelist. */ - i = hashname (SYMBOL_NAME (sym)); - SYMBOL_VALUE (sym) = (int) global_sym_chain[i]; - global_sym_chain[i] = sym; - SYMBOL_CLASS (sym) = LOC_STATIC; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &global_symbols); - break; - - /* This case is faked by a conditional above, - when there is no code letter in the dbx data. - Dbx data never actually contains 'l'. */ - case 'l': - SYMBOL_CLASS (sym) = LOC_LOCAL; - SYMBOL_VALUE (sym) = value; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &local_symbols); - break; - - case 'p': - SYMBOL_CLASS (sym) = LOC_ARG; - SYMBOL_VALUE (sym) = value; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &local_symbols); - /* DESC == 0 implies compiled with GCC. - In this case, if it says `short', believe it. */ - if (desc == 0) - break; - /* If PCC says a parameter is a short or a char, - it is really an int. */ - if (SYMBOL_TYPE (sym) == builtin_type_char - || SYMBOL_TYPE (sym) == builtin_type_short) - SYMBOL_TYPE (sym) = builtin_type_int; - else if (SYMBOL_TYPE (sym) == builtin_type_unsigned_char - || SYMBOL_TYPE (sym) == builtin_type_unsigned_short) - SYMBOL_TYPE (sym) = builtin_type_unsigned_int; - break; - - case 'P': - SYMBOL_CLASS (sym) = LOC_REGPARM; - SYMBOL_VALUE (sym) = value; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &local_symbols); - break; - - case 'r': - SYMBOL_CLASS (sym) = LOC_REGISTER; - SYMBOL_VALUE (sym) = value; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &local_symbols); - break; - - case 'S': - /* Static symbol at top level of file */ - SYMBOL_CLASS (sym) = LOC_STATIC; - SYMBOL_VALUE (sym) = value; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &file_symbols); - break; - - case 't': - SYMBOL_CLASS (sym) = LOC_TYPEDEF; - SYMBOL_VALUE (sym) = value; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0 - && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0) - TYPE_NAME (SYMBOL_TYPE (sym)) = - obsavestring (SYMBOL_NAME (sym), - strlen (SYMBOL_NAME (sym))); - /* C++ vagaries: we may have a type which is derived from - a base type which did not have its name defined when the - derived class was output. We fill in the derived class's - base part member's name here in that case. */ - else if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT - || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION) - && TYPE_N_BASECLASSES (SYMBOL_TYPE (sym))) - { - int i; - for (i = TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)); i > 0; i--) - if (TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i - 1) == 0) - TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i - 1) = - TYPE_NAME (TYPE_BASECLASS (SYMBOL_TYPE (sym), i)); - } - - add_symbol_to_list (sym, &file_symbols); - break; - - case 'T': - SYMBOL_CLASS (sym) = LOC_TYPEDEF; - SYMBOL_VALUE (sym) = value; - SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE; - if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0 - && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0) - TYPE_NAME (SYMBOL_TYPE (sym)) - = obconcat ("", - (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_ENUM - ? "enum " - : (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT - ? "struct " : "union ")), - SYMBOL_NAME (sym)); - add_symbol_to_list (sym, &file_symbols); - break; - - case 'V': - case 'v': - /* Static symbol of local scope */ - SYMBOL_CLASS (sym) = LOC_STATIC; - SYMBOL_VALUE (sym) = value; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &local_symbols); - break; - - default: - error ("Invalid symbol data: unknown symbol-type code `%c' at symtab pos %d.", deftype, symnum); - } - return sym; -} - -/* Read a number by which a type is referred to in dbx data, - or perhaps read a pair (FILENUM, TYPENUM) in parentheses. - Just a single number N is equivalent to (0,N). - Return the two numbers by storing them in the vector TYPENUMS. - TYPENUMS will then be used as an argument to dbx_lookup_type. */ - -static void -read_type_number (pp, typenums) - register char **pp; - register int *typenums; -{ - if (**pp == '(') - { - (*pp)++; - typenums[0] = read_number (pp, ','); - typenums[1] = read_number (pp, ')'); - } - else - { - typenums[0] = 0; - typenums[1] = read_number (pp, 0); - } -} - -/* Read a dbx type reference or definition; - return the type that is meant. - This can be just a number, in which case it references - a type already defined and placed in type_vector. - Or the number can be followed by an =, in which case - it means to define a new type according to the text that - follows the =. */ - -static -struct type * -read_type (pp) - register char **pp; -{ - register struct type *type = 0; - register int n; - struct type *type1; - int typenums[2]; - int xtypenums[2]; - - read_type_number (pp, typenums); - - /* Detect random reference to type not yet defined. - Allocate a type object but leave it zeroed. */ - if (**pp != '=') - return dbx_alloc_type (typenums); - - *pp += 2; - switch ((*pp)[-1]) - { - case 'x': - type = dbx_alloc_type (typenums); - /* Set the type code according to the following letter. */ - switch ((*pp)[0]) - { - case 's': - TYPE_CODE (type) = TYPE_CODE_STRUCT; - break; - case 'u': - TYPE_CODE (type) = TYPE_CODE_UNION; - break; - case 'e': - TYPE_CODE (type) = TYPE_CODE_ENUM; - break; - } - /* Skip the name the cross-ref points to. */ - /* Note: for C++, the cross reference may be to a base type which - has not yet been seen. In this case, we skip to the comma, - which will mark the end of the base class name. (The ':' - at the end of the base class name will be skipped as well.) */ - *pp = (char *) index (*pp, ','); - /* Just allocate the type and leave it zero if nothing known */ - return dbx_alloc_type (typenums); - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '(': - (*pp)--; - read_type_number (pp, xtypenums); - type = *dbx_lookup_type (xtypenums); - if (type == 0) - type = builtin_type_void; - *dbx_lookup_type (typenums) = type; - break; - - case '*': - type1 = read_type (pp); - if (TYPE_POINTER_TYPE (type1)) - { - type = TYPE_POINTER_TYPE (type1); - *dbx_lookup_type (typenums) = type; - } - else - { - type = dbx_alloc_type (typenums); - smash_to_pointer_type (type, type1); - } - break; - - case '@@': - { - struct type *domain = read_type (pp); - char c; - struct type *memtype; - - if (*(*pp)++ != ',') - error ("invalid member type data format, at symtab pos %d.", - symnum); - - memtype = read_type (pp); - type = dbx_alloc_type (typenums); - smash_to_member_type (type, domain, memtype); - } - break; - - case '&': - type1 = read_type (pp); - if (TYPE_REFERENCE_TYPE (type1)) - { - type = TYPE_REFERENCE_TYPE (type1); - *dbx_lookup_type (typenums) = type; - } - else - { - type = dbx_alloc_type (typenums); - smash_to_reference_type (type, type1); - } - break; - - case 'f': - type1 = read_type (pp); - if (TYPE_FUNCTION_TYPE (type1)) - { - type = TYPE_FUNCTION_TYPE (type1); - *dbx_lookup_type (typenums) = type; - } - else - { - type = dbx_alloc_type (typenums); - smash_to_function_type (type, type1); - } - break; - - case 'r': - type = read_range_type (pp, typenums); - *dbx_lookup_type (typenums) = type; - break; - - case 'e': - type = dbx_alloc_type (typenums); - type = read_enum_type (pp, type); - *dbx_lookup_type (typenums) = type; - break; - - case 's': - type = dbx_alloc_type (typenums); - type = read_struct_type (pp, type); - break; - - case 'u': - type = dbx_alloc_type (typenums); - type = read_struct_type (pp, type); - TYPE_CODE (type) = TYPE_CODE_UNION; - break; - - case 'a': - if (*(*pp)++ != 'r') - error ("Invalid symbol data: unrecognized type-code `a%c' %s %d.", - (*pp)[-1], "at symtab position", symnum); - - type = dbx_alloc_type (typenums); - type = read_array_type (pp, type); - break; - -#if 0 - /* Format of an array type: - "ar;lower;upper;". Put code - in to handle this. */ - - /* dbx expresses array types in terms of a range type for the index, - and that range type is specified right inside the array type spec - making ar1;MIN;MAX;VALTYPE */ - if (!strncmp (*pp, "r1;0;", 5)) - (*pp) += 5; - else if (!strncmp (*pp, "r(0,1);0;", 9)) - (*pp) += 9; - else break; - - TYPE_CODE (type) = TYPE_CODE_ARRAY; - /* In Fortran, an upper bound may be T... meaning a parameter specifies - the length of the data. In this case, just pretend the bound is 1. - This happens only for array parameters, which are really passed - as pointers anyway, and we will translate them into such. */ - if (**pp == 'T') - { - n = 1; - while (**pp != ';') - (*pp)++; - } - else - n = read_number (pp, ';') + 1; - TYPE_TARGET_TYPE (type) = read_type (pp); - TYPE_LENGTH (type) = TYPE_LENGTH (TYPE_TARGET_TYPE (type)) * n; - break; -#endif - - default: - error ("Invalid symbol data: unrecognized type-code `%c' at symtab pos %d.", - (*pp)[-1], symnum); - } - - if (type == 0) - abort (); - -#if 0 - /* If this is an overriding temporary alteration for a header file's - contents, and this type number is unknown in the global definition, - put this type into the global definition at this type number. */ - if (header_file_prev_index >= 0) - { - register struct type **tp - = explicit_lookup_type (header_file_prev_index, typenums[1]); - if (*tp == 0) - *tp = type; - } -#endif - return type; -} - -/* This page contains subroutines of read_type. */ - -/* Read the description of a structure (or union type) - and return an object describing the type. */ - -static struct type * -read_struct_type (pp, type) - char **pp; - register struct type *type; -{ - struct nextfield - { - struct nextfield *next; - int visibility; - struct field field; - }; - - struct next_fnfield - { - struct next_fnfield *next; - int visibility; - struct fn_field fn_field; - }; - - struct next_fnfieldlist - { - struct next_fnfieldlist *next; - struct fn_fieldlist fn_fieldlist; - }; - - register struct nextfield *list = 0; - struct nextfield *new; - int totalsize; - char *name; - register char *p; - int nfields = 0; - register int n; - - register struct next_fnfieldlist *mainlist = 0; - int nfn_fields = 0; - struct type *baseclass = NULL; - int read_possible_virtual_info = 0; - - TYPE_CODE (type) = TYPE_CODE_STRUCT; - - /* First comes the total size in bytes. */ - - TYPE_LENGTH (type) = read_number (pp, 0); - - /* C++: Now, if the class is a derived class, then the next character - will be a '!', followed by the number of base classes derived from. - Each element in the list contains visibility information, - the offset of this base class in the derived structure, - and then the base type. */ - if (**pp == '!') - { - int i, n_baseclasses, offset; - struct type **baseclass_vec; - struct type *baseclass; - int via_public, via_virtual; - - *pp += 1; - - n_baseclasses = read_number (pp, ','); - baseclass_vec = (struct type **) - obstack_alloc (symbol_obstack, - (n_baseclasses) * sizeof (struct type **)) - 1; - - for (i = 1; i <= n_baseclasses; i++) - { - if (**pp == '\\') - *pp = next_symbol_text (); - - switch (*(*pp)++) - { - case '0': - via_virtual = 0; - break; - case '1': - via_virtual = 1; - break; - default: - error ("Invalid symbol data: bad visibility format at symtab pos %d", - symnum); - } - - switch (*(*pp)++) - { - case '0': - via_public = 0; - break; - case '2': - via_public = 1; - break; - default: - error ("Invalid symbol data: bad visibility format at symtab pos %d.", - symnum); - } - offset = read_number (pp, ','); - baseclass = read_type (pp); - *pp += 1; /* skip trailing ';' */ - baseclass_vec[i] = lookup_basetype_type (baseclass, offset, via_virtual, via_public); - - /* Make this baseclass visible for structure-printing purposes. */ - new = (struct nextfield *) alloca (sizeof (struct nextfield)); - new->next = list; - list = new; - list->field.type = baseclass_vec[i]; - list->field.name = TYPE_NAME (baseclass_vec[i]); - list->field.bitpos = offset; - list->field.bitsize = 0; /* this should be an unpacked field! */ - nfields++; - } - TYPE_N_BASECLASSES (type) = n_baseclasses; - TYPE_BASECLASSES (type) = baseclass_vec; - } - - /* Now come the fields, as NAME:?TYPENUM,BITPOS,BITSIZE; for each one. - At the end, we see a semicolon instead of a field. - - In C++, this may wind up being NAME:?TYPENUM:PHYSNAME; for - a static field. - - The `?' is a placeholder for one of '+' (public visibility), - '0' (protected visibility), and '-' (private visibility). */ - - while (**pp != ';') - { - int visibility; - - /* Check for and handle cretinous dbx symbol name continuation! */ - if (**pp == '\\') *pp = next_symbol_text (); - - /* Get space to record the next field's data. */ - new = (struct nextfield *) alloca (sizeof (struct nextfield)); - new->next = list; - list = new; - - /* Read the data. */ - p = *pp; - while (*p != ':') p++; - list->field.name = obsavestring (*pp, p - *pp); - - /* C++: Check to see if we have hit the methods yet. */ - if (p[1] == ':') - break; - - *pp = p + 1; - - /* This means we have a visibility for a field coming. */ - if (**pp == '/') - { - switch (*++*pp) - { - case '0': - visibility = 0; - *pp += 1; - break; - - case '1': - visibility = 1; - *pp += 1; - break; - - case '2': - visibility = 2; - *pp += 1; - break; - } - } - /* else normal dbx-style format. */ - - list->field.type = read_type (pp); - if (**pp == ':') - { - list->field.bitpos = (long)-1; - p = ++(*pp); - while (*p != ';') p++; - list->field.bitsize = (long) savestring (*pp, p - *pp); - *pp = p + 1; - nfields++; - continue; - } - else if (**pp != ',') - error ("Invalid symbol data: bad structure-type format at symtab pos %d.", - symnum); - (*pp)++; /* Skip the comma. */ - list->field.bitpos = read_number (pp, ','); - list->field.bitsize = read_number (pp, ';'); - /* Detect an unpacked field and mark it as such. - dbx gives a bit size for all fields. - Note that forward refs cannot be packed, - and treat enums as if they had the width of ints. */ - if (TYPE_CODE (list->field.type) != TYPE_CODE_INT - && TYPE_CODE (list->field.type) != TYPE_CODE_ENUM) - list->field.bitsize = 0; - if ((list->field.bitsize == 8 * TYPE_LENGTH (list->field.type) - || (TYPE_CODE (list->field.type) == TYPE_CODE_ENUM - && list->field.bitsize == 8 * TYPE_LENGTH (builtin_type_int))) - && - list->field.bitpos % 8 == 0) - list->field.bitsize = 0; - nfields++; - } - - /* Now come the method fields, as NAME::methods - where each method is of the form TYPENUM,ARGS,...:PHYSNAME; - At the end, we see a semicolon instead of a field. - - For the case of overloaded operators, the format is - OPERATOR::*.methods, where OPERATOR is the string "operator", - `*' holds the place for an operator name (such as `+=') - and `.' marks the end of the operator name. */ - if (p[1] == ':') - { - /* Now, read in the methods. To simplify matters, we - "unread" the name that has been read, so that we can - start from the top. */ - - p = *pp; - - /* chill the list of fields: the last entry (at the head) - is a partially constructed entry which we now scrub. */ - list = list->next; - - /* For each list of method lists... */ - do - { - int i; - struct next_fnfield *sublist = 0; - struct fn_field *fn_fields = 0; - int length = 0; - struct next_fnfieldlist *new_mainlist = - (struct next_fnfieldlist *)alloca (sizeof (struct next_fnfieldlist)); - - /* read in the name. */ - while (*p != ':') p++; - if ((*pp)[0] == 'o' && (*pp)[1] == 'p' && (*pp)[2] == '$') - { - static char opname[32] = "operator "; - char *o = opname + 9; - - /* Skip past '::'. */ - p += 2; - while (*p != '.') - *o++ = *p++; - new_mainlist->fn_fieldlist.name = savestring (opname, o - opname); - /* Skip past '.' */ - *pp = p + 1; - } - else - { - i = 0; - new_mainlist->fn_fieldlist.name = savestring (*pp, p - *pp); - /* Skip past '::'. */ - *pp = p + 2; - } - - do - { - struct next_fnfield *new_sublist = - (struct next_fnfield *)alloca (sizeof (struct next_fnfield)); - - /* Check for and handle cretinous dbx symbol name continuation! */ - if (**pp == '\\') *pp = next_symbol_text (); - - new_sublist->fn_field.type = read_type (pp); - new_sublist->fn_field.args = read_args (pp, ':'); - p = *pp; - while (*p != ';') p++; - new_sublist->fn_field.physname = savestring (*pp, p - *pp); - *pp = p + 1; - new_sublist->visibility = *(*pp)++ - '0'; - if (**pp == '\\') *pp = next_symbol_text (); - - if (*(*pp)++ == '*') - new_sublist->fn_field.voffset = read_number (pp, ';') + 1; - else - new_sublist->fn_field.voffset = 0; - - new_sublist->next = sublist; - sublist = new_sublist; - length++; - } - while (**pp != ';'); - - *pp += 1; - - new_mainlist->fn_fieldlist.fn_fields = - (struct fn_field *) obstack_alloc (symbol_obstack, - sizeof (struct fn_field) * length); - TYPE_FN_PRIVATE_BITS (new_mainlist->fn_fieldlist) = - (int *) obstack_alloc (symbol_obstack, - sizeof (int) * (1 + (length >> 5))); - - TYPE_FN_PROTECTED_BITS (new_mainlist->fn_fieldlist) = - (int *) obstack_alloc (symbol_obstack, - sizeof (int) * (1 + (length >> 5))); - - for (i = length; sublist; sublist = sublist->next) - { - new_mainlist->fn_fieldlist.fn_fields[--i] = sublist->fn_field; - if (sublist->visibility == 0) - B_SET (new_mainlist->fn_fieldlist.private_fn_field_bits, i); - else if (sublist->visibility == 1) - B_SET (new_mainlist->fn_fieldlist.protected_fn_field_bits, i); - } - - new_mainlist->fn_fieldlist.length = length; - new_mainlist->next = mainlist; - mainlist = new_mainlist; - nfn_fields++; - } - while (**pp != ';'); - } - - *pp += 1; - - /* Now create the vector of fields, and record how big it is. */ - - TYPE_NFIELDS (type) = nfields; - TYPE_FIELDS (type) = (struct field *) obstack_alloc (symbol_obstack, - sizeof (struct field) * nfields); - TYPE_FIELD_PRIVATE_BITS (type) = - (int *) obstack_alloc (symbol_obstack, - sizeof (int) * (1 + (nfields >> 5))); - TYPE_FIELD_PROTECTED_BITS (type) = - (int *) obstack_alloc (symbol_obstack, - sizeof (int) * (1 + (nfields >> 5))); - - TYPE_NFN_FIELDS (type) = nfn_fields; - TYPE_NFN_FIELDS_TOTAL (type) = nfn_fields; - if (baseclass) - TYPE_NFN_FIELDS_TOTAL (type) += TYPE_NFN_FIELDS_TOTAL (baseclass); - - TYPE_FN_FIELDLISTS (type) = - (struct fn_fieldlist *) obstack_alloc (symbol_obstack, - sizeof (struct fn_fieldlist) * nfn_fields); - - /* Copy the saved-up fields into the field vector. */ - - for (n = nfields; list; list = list->next) - { - TYPE_FIELD (type, --n) = list->field; - if (list->visibility == 0) - SET_TYPE_FIELD_PRIVATE (type, n); - else if (list->visibility == 1) - SET_TYPE_FIELD_PROTECTED (type, n); - } - - for (n = nfn_fields; mainlist; mainlist = mainlist->next) - TYPE_FN_FIELDLISTS (type)[--n] = mainlist->fn_fieldlist; - - if (**pp == '~') - { - *pp += 1; - - if (**pp == '=') - { - TYPE_FLAGS (type) - |= TYPE_FLAG_HAS_CONSTRUCTOR | TYPE_FLAG_HAS_DESTRUCTOR; - *pp += 1; - } - else if (**pp == '+') - { - TYPE_FLAGS (type) |= TYPE_FLAG_HAS_CONSTRUCTOR; - *pp += 1; - } - else if (**pp == '-') - { - TYPE_FLAGS (type) |= TYPE_FLAG_HAS_DESTRUCTOR; - *pp += 1; - } - - /* Read either a '%' or the final ';'. */ - if (*(*pp)++ == '%') - { - /* Now we must record the virtual function table pointer's - field information. */ - - struct type *t; - int i; - - t = read_type (pp); - p = (*pp)++; - while (*p != ';') p++; - TYPE_VPTR_BASETYPE (type) = t; - if (type == t) - { - if (TYPE_FIELD_NAME (t, 0) == 0) - TYPE_VPTR_FIELDNO (type) = i = 0; - else for (i = TYPE_NFIELDS (t) - 1; i >= 0; --i) - if (! strncmp (TYPE_FIELD_NAME (t, i), *pp, - strlen (TYPE_FIELD_NAME (t, i)))) - { - TYPE_VPTR_FIELDNO (type) = i; - break; - } - if (i < 0) - error ("virtual function table field not found"); - } - else - TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (TYPE_BASECLASS (type, 1)); - *pp = p + 1; - } - else - { - TYPE_VPTR_BASETYPE (type) = 0; - TYPE_VPTR_FIELDNO (type) = -1; - } - } - else - { - TYPE_VPTR_BASETYPE (type) = 0; - TYPE_VPTR_FIELDNO (type) = -1; - } - - return type; -} - -/* Read a definition of an enumberation type, - and create and return a suitable type object. - Also creates a range type which represents the bounds of that - array. */ -static struct type * -read_array_type (pp, type) - register char **pp; - register struct type *type; -{ - struct type *index_type, *element_type, *range_type; - int lower, upper; - - /* Format of an array type: - "ar;lower;upper;". Put code in - to handle this. */ - - index_type = read_type (pp); - if (*(*pp)++ != ';') - error ("Invalid symbol data; improper format of array type decl."); - lower = read_number (pp, ';'); - upper = read_number (pp, ';'); - element_type = read_type (pp); - - { - /* Create range type. */ - range_type = (struct type *) obstack_alloc (symbol_obstack, - sizeof (struct type)); - TYPE_CODE (range_type) = TYPE_CODE_RANGE; - TYPE_TARGET_TYPE (range_type) = index_type; - - /* This should never be needed. */ - TYPE_LENGTH (range_type) = sizeof (int); - - TYPE_NFIELDS (range_type) = 2; - TYPE_FIELDS (range_type) = - (struct field *) obstack_alloc (symbol_obstack, - 2 * sizeof (struct field)); - TYPE_FIELD_BITPOS (range_type, 0) = lower; - TYPE_FIELD_BITPOS (range_type, 1) = upper; - } - - TYPE_CODE (type) = TYPE_CODE_ARRAY; - TYPE_TARGET_TYPE (type) = element_type; - TYPE_LENGTH (type) = (upper - lower + 1) * TYPE_LENGTH (element_type); - TYPE_NFIELDS (type) = 1; - TYPE_FIELDS (type) = - (struct field *) obstack_alloc (symbol_obstack, - sizeof (struct field)); - TYPE_FIELD_TYPE (type, 0) = range_type; - - return type; -} - - -/* Read a definition of an enumeration type, - and create and return a suitable type object. - Also defines the symbols that represent the values of the type. */ - -static struct type * -read_enum_type (pp, type) - register char **pp; - register struct type *type; -{ - register char *p; - char *name; - register long n; - register struct symbol *sym; - int nsyms = 0; - struct pending **symlist; - struct pending *osyms, *syms; - int o_nsyms; - - if (within_function) - symlist = &local_symbols; - else - symlist = &file_symbols; - osyms = *symlist; - o_nsyms = osyms ? osyms->nsyms : 0; - - /* Read the value-names and their values. - The input syntax is NAME:VALUE,NAME:VALUE, and so on. - A semicolon instead of a NAME means the end. */ - while (**pp && **pp != ';') - { - /* Check for and handle cretinous dbx symbol name continuation! */ - if (**pp == '\\') *pp = next_symbol_text (); - - p = *pp; - while (*p != ':') p++; - name = obsavestring (*pp, p - *pp); - *pp = p + 1; - n = read_number (pp, ','); - - sym = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol)); - bzero (sym, sizeof (struct symbol)); - SYMBOL_NAME (sym) = name; - SYMBOL_CLASS (sym) = LOC_CONST; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - SYMBOL_VALUE (sym) = n; - add_symbol_to_list (sym, symlist); - nsyms++; - } - - (*pp)++; /* Skip the semicolon. */ - - /* Now fill in the fields of the type-structure. */ - - TYPE_LENGTH (type) = sizeof (int); - TYPE_CODE (type) = TYPE_CODE_ENUM; - TYPE_NFIELDS (type) = nsyms; - TYPE_FIELDS (type) = (struct field *) obstack_alloc (symbol_obstack, sizeof (struct field) * nsyms); - - /* Find the symbols for the values and put them into the type. - The symbols can be found in the symlist that we put them on - to cause them to be defined. osyms contains the old value - of that symlist; everything up to there was defined by us. */ - - for (syms = *symlist, n = nsyms; syms; syms = syms->next) - { - int j = 0; - if (syms == osyms) - j = o_nsyms; - for (; j < syms->nsyms; j++) - { - struct symbol *sym = syms->symbol[j]; - SYMBOL_TYPE (sym) = type; - TYPE_FIELD_NAME (type, --n) = SYMBOL_NAME (sym); - TYPE_FIELD_VALUE (type, n) = 0; - TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (sym); - TYPE_FIELD_BITSIZE (type, n) = 0; - } - if (syms == osyms) - break; - } - - return type; -} - -#define MAX_OF_TYPE(t) ((1 << (sizeof (t) - 1)) - 1) -#define MIN_OF_TYPE(t) (-(1 << (sizeof (t) - 1))) - -static struct type * -read_range_type (pp, typenums) - char **pp; - int typenums[2]; -{ - char *errp = *pp; - int rangenums[2]; - int n2, n3; - int self_subrange; - struct type *result_type; - - /* First comes a type we are a subrange of. - In C it is usually 0, 1 or the type being defined. */ - read_type_number (pp, rangenums); - self_subrange = (rangenums[0] == typenums[0] && - rangenums[1] == typenums[1]); - - /* A semicolon should now follow; skip it. */ - if (**pp == ';') - (*pp)++; - - /* The remaining two operands are usually lower and upper bounds - of the range. But in some special cases they mean something else. */ - n2 = read_number (pp, ';'); - n3 = read_number (pp, ';'); - - /* A type defined as a subrange of itself, with bounds both 0, is void. */ - if (self_subrange && n2 == 0 && n3 == 0) - return builtin_type_void; - - /* If n3 is zero and n2 is not, we want a floating type, - and n2 is the width in bytes. - - Fortran programs appear to use this for complex types also, - and they give no way to distinguish between double and single-complex! - We don't have complex types, so we would lose on all fortran files! - So return type `double' for all of those. It won't work right - for the complex values, but at least it makes the file loadable. */ - - if (n3 == 0 && n2 > 0) - { - if (n2 == sizeof (float)) - return builtin_type_float; - return builtin_type_double; - } - - /* If the upper bound is -1, it must really be an unsigned int. */ - - else if (n2 == 0 && n3 == -1) - { - if (sizeof (int) == sizeof (long)) - return builtin_type_unsigned_int; - else - return builtin_type_unsigned_long; - } - - /* Special case: char is defined (Who knows why) as a subrange of - itself with range 0-127. */ - else if (self_subrange && n2 == 0 && n3 == 127) - return builtin_type_char; - - /* Assumptions made here: Subrange of self is equivalent to subrange - of int. */ - else if (n2 == 0 - && (self_subrange || - *dbx_lookup_type (rangenums) == builtin_type_int)) - { - /* an unsigned type */ - if (n3 == (1 << (8 * sizeof (int))) - 1) - return builtin_type_unsigned_int; - if (n3 == (1 << (8 * sizeof (short))) - 1) - return builtin_type_unsigned_short; - if (n3 == (1 << (8 * sizeof (char))) - 1) - return builtin_type_unsigned_char; - } - else if (n2 == -n3 -1) - { - /* a signed type */ - if (n3 == (1 << (8 * sizeof (int) - 1)) - 1) - return builtin_type_int; - if (n3 == (1 << (8 * sizeof (long) - 1)) - 1) - return builtin_type_long; - if (n3 == (1 << (8 * sizeof (short) - 1)) - 1) - return builtin_type_short; - if (n3 == (1 << (8 * sizeof (char) - 1)) - 1) - return builtin_type_char; - } - - /* We have a real range type on our hands. Allocate space and - return a real pointer. */ - - /* At this point I don't have the faintest idea how to deal with - a self_subrange type; I'm going to assume that this is used - as an idiom, and that all of them are special cases. So . . . */ - if (self_subrange) - error ("Type defined as subrange of itself."); - - result_type = (struct type *) obstack_alloc (symbol_obstack, - sizeof (struct type)); - bzero (result_type, sizeof (struct type)); - - TYPE_TARGET_TYPE (result_type) = (self_subrange ? - builtin_type_int : - *dbx_lookup_type(rangenums)); - - /* We have to figure out how many bytes it takes to hold this - range type. I'm going to assume that anything that is pushing - the bounds of a long was taken care of above. */ - if (n2 >= MIN_OF_TYPE(char) && n3 <= MAX_OF_TYPE(char)) - TYPE_LENGTH (result_type) = 1; - else if (n2 >= MIN_OF_TYPE(short) && n3 <= MAX_OF_TYPE(short)) - TYPE_LENGTH (result_type) = sizeof (short); - else if (n2 >= MIN_OF_TYPE(int) && n3 <= MAX_OF_TYPE(int)) - TYPE_LENGTH (result_type) = sizeof (int); - else if (n2 >= MIN_OF_TYPE(long) && n3 <= MAX_OF_TYPE(long)) - TYPE_LENGTH (result_type) = sizeof (long); - else - error ("Ranged type doesn't fit within known sizes."); - - TYPE_LENGTH (result_type) = TYPE_LENGTH (TYPE_TARGET_TYPE (result_type)); - TYPE_CODE (result_type) = TYPE_CODE_RANGE; - TYPE_NFIELDS (result_type) = 2; - TYPE_FIELDS (result_type) = - (struct field *) obstack_alloc (symbol_obstack, - 2 * sizeof (struct field)); - bzero (TYPE_FIELDS (result_type), 2 * sizeof (struct field)); - TYPE_FIELD_BITPOS (result_type, 0) = n2; - TYPE_FIELD_BITPOS (result_type, 1) = n3; - - return result_type; -} - -/* Read a number from the string pointed to by *PP. - The value of *PP is advanced over the number. - If END is nonzero, the character that ends the - number must match END, or an error happens; - and that character is skipped if it does match. - If END is zero, *PP is left pointing to that character. */ - -static long -read_number (pp, end) - char **pp; - int end; -{ - register char *p = *pp; - register long n = 0; - register int c; - int sign = 1; - - /* Handle an optional leading minus sign. */ - - if (*p == '-') - { - sign = -1; - p++; - } - - /* Read the digits, as far as they go. */ - - while ((c = *p++) >= '0' && c <= '9') - { - n *= 10; - n += c - '0'; - } - if (end) - { - if (c && c != end) - error ("Invalid symbol data: invalid character \\%03o at symbol pos %d.", c, symnum); - } - else - --p; - - *pp = p; - return n * sign; -} - -/* Read in an argument list. This is a list of types. It is terminated with - a ':', FYI. Return the list of types read in. */ -static struct type ** -read_args (pp, end) - char **pp; - int end; -{ - struct type *types[1024], **rval; /* allow for fns of 1023 parameters */ - int n = 0; - - while (**pp != end) - { - if (**pp != ',') - error ("Invalid argument list: no ',', at symtab pos %d", symnum); - *pp += 1; - - /* Check for and handle cretinous dbx symbol name continuation! */ - if (**pp == '\\') - *pp = next_symbol_text (); - - types[n++] = read_type (pp); - } - *pp += 1; /* get past `end' (the ':' character) */ - - if (n == 1) - { - rval = (struct type **) xmalloc (2 * sizeof (struct type *)); - } - else if (TYPE_CODE (types[n-1]) != TYPE_CODE_VOID) - { - rval = (struct type **) xmalloc ((n + 1) * sizeof (struct type *)); - bzero (rval + n, sizeof (struct type *)); - } - else - { - rval = (struct type **) xmalloc (n * sizeof (struct type *)); - } - bcopy (types, rval, n * sizeof (struct type *)); - return rval; -} - -/* This function is really horrible, but to avoid it, there would need - to be more filling in of forward references. THIS SHOULD BE MOVED OUT - OF COFFREAD.C AND DBXREAD.C TO SOME PLACE WHERE IT CAN BE SHARED */ -int -fill_in_vptr_fieldno (type) - struct type *type; -{ - if (TYPE_VPTR_FIELDNO (type) < 0) - TYPE_VPTR_FIELDNO (type) = - fill_in_vptr_fieldno (TYPE_BASECLASS (type, 1)); - return TYPE_VPTR_FIELDNO (type); -} - -void -_initialize_dbxread () -{ - symfile = 0; - header_files = (struct header_file *) 0; - this_object_header_files = (int *) 0; - - add_com ("symbol-file", class_files, symbol_file_command, - "Load symbol table (in dbx format) from executable file FILE."); - - add_com ("add-file", class_files, add_file_command, - "Load the symbols from FILE, assuming its code is at TEXT_START.") ; -} - -#endif /* READ_DBX_FORMAT */ -@ - - -1.2 -log -@If discarding the symbol table, discard its name too, so "info files" -will give the right answer. -@ -text -@d27 1 -a27 1 -#include -@ - - -1.1 -log -@Initial revision -@ -text -@d2 1 -a2 1 - Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. -d1457 3 -@ diff --git a/gdb/RCS/findvar.c,v b/gdb/RCS/findvar.c,v deleted file mode 100644 index 9095f2b903..0000000000 --- a/gdb/RCS/findvar.c,v +++ /dev/null @@ -1,584 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.04.26.01.06.46; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.04.25.15.38.48; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@use XXX_BIG_ENDIAN macros rather than runtime tests. -@ -text -@/* Find a variable's value in memory, for GDB, the GNU debugger. - Copyright (C) 1986, 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! -*/ - -#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 dissapears 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. */ - - if (REGISTER_IN_WINDOW_P(regnum)) - { - fi = get_frame_info (frame); - 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 address, 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; - - case LOC_ARG: - fi = get_frame_info (frame); - addr = val + FRAME_ARGS_ADDRESS (fi); - 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: - v = value_from_register (type, val, frame); - 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 address, - 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); - - 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_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; - } - - return value_cast (lookup_pointer_type (type), - value_from_long (builtin_type_long, (LONGEST) addr)); -} - -@ - - -1.1 -log -@Initial revision -@ -text -@d448 2 -a449 5 - union { int i; char c; } test; - /* If we want less than the full size, we need to - test for a big-endian or little-endian machine. */ - test.i = 1; - if (test.c != 1 && len < REGISTER_RAW_SIZE (regnum)) -d454 2 -a455 1 - -a490 1 - union { int i; char c; } test; -d492 2 -a493 4 - /* If var is less than the full size of register, we need to - test for a big-endian or little-endian machine. */ - test.i = 1; - if (test.c != 1 && len < REGISTER_RAW_SIZE (val)) -d496 1 -@ diff --git a/gdb/RCS/gdb.texinfo,v b/gdb/RCS/gdb.texinfo,v deleted file mode 100644 index ff38f18727..0000000000 --- a/gdb/RCS/gdb.texinfo,v +++ /dev/null @@ -1,3009 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @@; - - -1.2 -date 89.02.10.01.41.38; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.10.00.33.03; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Improve doc in various ways, mostly xref{Expressions} so you can -find out what an expression is (I had trouble finding it, since -it's in a nested menu somewhere.) -@ -text -@\input texinfo -@@setfilename ../info/gdb -@@settitle GDB, The GNU Debugger -@@ifinfo -This file documents the GNU debugger GDB. - -Copyright (C) 1988 Free Software Foundation, Inc. - -Permission is granted to make and distribute verbatim copies of -this manual provided the copyright notice and this permission notice -are preserved on all copies. - -@@ignore -Permission is granted to process this file through Tex and print the -results, provided the printed document carries copying permission -notice identical to this one except for the removal of this paragraph -(this paragraph not being relevant to the printed manual). - -@@end ignore -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided also that the -sections entitled ``Distribution'' and ``GDB General Public License'' are -included exactly as in the original, and provided that the entire resulting -derived work is distributed under the terms of a permission notice -identical to this one. - -Permission is granted to copy and distribute translations of this manual -into another language, under the above conditions for modified versions, -except that the sections entitled ``Distribution'' and ``GDB General Public -License'' may be included in a translation approved by the author instead -of in the original English. -@@end ifinfo - -@@setchapternewpage odd -@@settitle GDB Manual -@@titlepage -@@sp 6 -@@center @@titlefont{GDB Manual} -@@sp 1 -@@center The GNU Source-Level Debugger -@@sp 4 -@@center Third Edition, GDB version 3.1 -@@sp 1 -@@center January 1989 -@@sp 5 -@@center Richard M. Stallman -@@page -@@vskip 0pt plus 1filll -Copyright @@copyright{} 1988, 1989 Free Software Foundation, Inc. - -Permission is granted to make and distribute verbatim copies of -this manual provided the copyright notice and this permission notice -are preserved on all copies. - -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided also that the -sections entitled ``Distribution'' and ``GDB General Public License'' are -included exactly as in the original, and provided that the entire resulting -derived work is distributed under the terms of a permission notice -identical to this one. - -Permission is granted to copy and distribute translations of this manual -into another language, under the above conditions for modified versions, -except that the sections entitled ``Distribution'' and ``GDB General Public -License'' may be included in a translation approved by the author instead -of in the original English. -@@end titlepage -@@page - -@@node Top, Commands,, (DIR) -@@unnumbered Summary of GDB - -The purpose of a debugger such as GDB is to allow you to execute another -program while examining what is going on inside it. We call the other -program ``your program'' or ``the program being debugged''. - -GDB can do four kinds of things (plus other things in support of these): - -@@enumerate -@@item -Start the program, specifying anything that might affect its behavior. - -@@item -Make the program stop on specified conditions. - -@@item -Examine what has happened, when the program has stopped, so that you -can see bugs happen. - -@@item -Change things in the program, so you can correct the effects of one bug -and go on to learn about another without having to recompile first. -@@end enumerate - -GDB can be used to debug programs written in C and C++. Pascal support -is being implemented, and Fortran support will be added when a GNU -Fortran compiler is written. - -@@menu -* License:: The GDB General Public License gives you permission - to redistribute GDB on certain terms; and also - explains that there is no warranty. -* Input:: GDB command syntax and input conventions. -* Files:: Specifying files for GDB to operate on. -* Options:: GDB arguments and options. -* Compilation::Compiling your program so you can debug it. -* Running:: Running your program under GDB. -* Stopping:: Making your program stop. Why it may stop. What to do then. -* Stack:: Examining your program's stack. -* Source:: Examining your program's source files. -* Data:: Examining data in your program. -* Symbols:: Examining the debugger's symbol table. -* Altering:: Altering things in your program. -* Sequences:: Canned command sequences for repeated use. -* Emacs:: Using GDB through GNU Emacs. -* Remote:: Remote kernel debugging across a serial line. -* Commands:: Index of GDB commands. -* Concepts:: Index of GDB concepts. -@@end menu - -@@node License, Input, Top, Top -@@unnumbered GDB General Public License -@@center (Clarified 11 Feb 1988) - - The license agreements of most software companies keep you at the mercy -of those companies. By contrast, our general public license is intended to -give everyone the right to share GDB. To make sure that you get the rights -we want you to have, we need to make restrictions that forbid anyone to -deny you these rights or to ask you to surrender the rights. Hence this -license agreement. - - Specifically, we want to make sure that you have the right to give away -copies of GDB, that you receive source code or else can get it if you want -it, that you can change GDB or use pieces of it in new free programs, and -that you know you can do these things. - - To make sure that everyone has such rights, we have to forbid you to -deprive anyone else of these rights. For example, if you distribute copies -of GDB, 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. - - Also, for our own protection, we must make certain that everyone finds -out that there is no warranty for GDB. If GDB is modified by someone else -and passed on, we want its recipients to know that what they have is not -what we distributed, so that any problems introduced by others will not -reflect on our reputation. - - Therefore we (Richard Stallman and the Free Software Foundation, -Inc.) make the following terms which say what you must do to be -allowed to distribute or change GDB. - -@@unnumberedsec Copying Policies - -@@enumerate -@@item -You may copy and distribute verbatim copies of GDB source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each file a valid copyright notice ``Copyright -@@copyright{} 1988 Free Software Foundation, Inc.'' (or with whatever year -is appropriate); keep intact the notices on all files that -refer to this License Agreement and to the absence of any warranty; and -give any other recipients of the GDB program a copy of this License -Agreement along with the program. You may charge a distribution fee -for the physical act of transferring a copy. - -@@item -You may modify your copy or copies of GDB source code 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: - -@@itemize @@bullet -@@item -cause the modified files to carry prominent notices stating -that you changed the files and the date of any change; and - -@@item -cause the whole of any work that you distribute or publish, that -in whole or in part contains or is a derivative of GDB or any -part thereof, to be licensed at no charge to all third parties on -terms identical to those contained in this License Agreement -(except that you may choose to grant more extensive warranty -protection to some or all third parties, at your option). - -@@item -if the modified program serves as a debugger, cause it, when -started running in the simplest and usual way, to print an -announcement including a valid copyright notice ``Copyright -@@copyright{} 1988 Free Software Foundation, Inc.'' (or with the -year that is appropriate), saying 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 License Agreement. - -@@item -You may charge a distribution fee for the physical act of -transferring a copy, and you may at your option offer warranty -protection in exchange for a fee. -@@end itemize - -Mere aggregation of another unrelated program with this program (or its -derivative) on a volume of a storage or distribution medium does not bring -the other program under the scope of these terms. - -@@item -You may copy and distribute GDB (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: - -@@itemize @@bullet -@@item -accompany it with the complete corresponding machine-readable -source code, which must be distributed under the terms of -Paragraphs 1 and 2 above; or, - -@@item -accompany it with a written offer, valid for at least three -years, to give any third party free (except for a nominal -shipping charge) a complete machine-readable copy of the -corresponding source code, to be distributed under the terms of -Paragraphs 1 and 2 above; or, - -@@item -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.) -@@end itemize - -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. - -@@item -You may not copy, sublicense, distribute or transfer GDB except as -expressly provided under this License Agreement. Any attempt -otherwise to copy, sublicense, distribute or transfer GDB is void and -your rights to use GDB under this License agreement shall be -automatically terminated. However, parties who have received computer -software programs from you with this License Agreement will not have -their licenses terminated so long as such parties remain in full -compliance. - -@@item -If you wish to incorporate parts of GDB into other free programs whose -distribution conditions are different, write to the Free Software -Foundation. We have not yet worked out a simple rule that can be -stated here, but we will often permit this. We will be guided by the -two goals of preserving the free status of all derivatives our free -software and of promoting the sharing and reuse of software. -@@end enumerate - -@@iftex -@@vfil -@@eject -@@end iftex -@@unnumberedsec NO WARRANTY - - BECAUSE GDB IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY -NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT -WHEN OTHERWISE STATED IN WRITING, THE FREE SOFTWARE FOUNDATION, INC, -RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE GDB ``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 GDB -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY -SERVICING, REPAIR OR CORRECTION. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL FREE SOFTWARE -FOUNDATION, INC., RICHARD M. STALLMAN, AND/OR ANY OTHER PARTY WHO MAY -MODIFY AND REDISTRIBUTE GDB AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER -SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR -INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA -BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A -FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY -FREE SOFTWARE FOUNDATION, INC.) THE PROGRAM, EVEN IF YOU HAVE BEEN -ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY -OTHER PARTY. - -@@node Input, Files, License, Top -@@chapter GDB Input Conventions - -GDB is invoked with the shell command @@samp{gdb}. Once started, it reads -commands from the terminal until you tell it to exit. - -A GDB command is a single line of input. There is no limit on how long -it can be. It starts with a command name, which is followed by arguments -whose meaning depends on the command name. Some command names do not -allow arguments. - -GDB command names may always be abbreviated if the abbreviation is -unambiguous. Sometimes even ambiguous abbreviations are allowed; for -example, @@samp{s} is specially defined as equivalent to @@samp{step} -even though there are other commands whose names start with @@samp{s}. -Possible command abbreviations are often stated in the documentation -of the individual commands. - -A blank line as input to GDB means to repeat the previous command verbatim. -Certain commands do not allow themselves to be repeated this way; these are -commands for which unintentional repetition might cause trouble and which -you are unlikely to want to repeat. Certain others (@@samp{list} and -@@samp{x}) act differently when repeated because that is more useful. - -A line of input starting with @@samp{#} is a comment; it does nothing. -This is useful mainly in command files (@@xref{Command Files}). - -Occasionally it is useful to execute a shell command from within gdb. -This can be done with the @@samp{shell} command, or the shell escape -character @@samp{!}. - -@@table @@code -@@item shell @@var{shell command string} -@@kindex shell -@@item !@@var{shell command string} -@@kindex ! -@@cindex shell escape -Directs GDB to invoke an inferior shell to execute @@samp{shell command string}. -The environmental variable @@samp{SHELL} is used if it exists, otherwise gdb -uses @@samp{/bin/sh}. -@@end table - -GDB @@dfn{prompts} for commands with a string that is normally @@samp{(gdb)}. -When debugging GDB with GDB, it is useful to change the prompt in one of -the GDBs so that you can distinguish them. This can be done with the -@@samp{set prompt} command. - -@@table @@code -@@item set prompt @@var{newprompt} -@@kindex set prompt -Directs GDB to use @@var{newprompt} as its prompt string henceforth. -@@end table - -@@cindex exiting GDB -@@kindex quit -To exit GDB, use the @@samp{quit} command (abbreviated @@samp{q}). -@@kbd{Ctrl-c} will not exit from GDB, but rather will terminate the action -of any GDB command that is in progress and return to GDB command level. -It is safe to type @@kbd{Ctrl-c} at any time because GDB does not allow -it to take effect until a time when it is safe. - -@@node Files, Options, Input, Top -@@chapter Specifying GDB's Files - -@@cindex core dump file -@@cindex executable file -@@cindex symbol table -GDB needs to know the filename of the program to be debugged. To debug a -core dump of a previous run, GDB must be told the filename of the core -dump. - -@@menu -* Arguments: File Arguments. Specifying files with arguments - (when you start GDB). -* Commands: File Commands. Specifying files with GDB commands. -@@end menu - -@@node File Arguments, File Commands, Files, Files -@@section Specifying Files with Arguments - -The usual way to specify the executable and core dump file names is with -two command arguments given when you start GDB. The first argument is used -as the file for execution and symbols, and the second argument (if any) is -used as the core dump file name. Thus, - -@@example -gdb progm core -@@end example - -@@noindent -specifies @@file{progm} as the executable program and @@file{core} as a core -dump file to examine. (You do not need to have a core dump file if what -you plan to do is debug the program interactively.) - -@@xref{Options}, for full information on command options and arguments for -GDB. - -@@node File Commands,, File Arguments, Files -@@section Specifying Files with Commands - -Usually you specify the files for GDB to work with by giving arguments when -you invoke GDB. But occasionally it is necessary to change to a different -file during a GDB session. Or you may run GDB and forget to specify the -files you want to use. In these situations the GDB commands to specify new -files are useful. - -@@table @@code -@@item exec-file @@var{filename} -@@kindex exec-file -Specify that the program to be run is found in @@var{filename}. If you -do not specify a directory and the file is not found in GDB's working -directory, GDB will use the environment variable @@samp{PATH} as a list -of directories to search, just as the shell does when looking for a -program to run. - -@@item symbol-file @@var{filename} -@@kindex symbol-file -Read symbol table information from file @@var{filename}. @@samp{PATH} -is searched when necessary. Most of the time you will use both the -@@samp{exec-file} and @@samp{symbol-file} commands on the same file. - -@@samp{symbol-file} with no argument clears out GDB's symbol table. - -@@item core-file @@var{filename} -@@kindex core-file -Specify the whereabouts of a core dump file to be used as the -``contents of memory''. Note that the core dump contains only the -writable parts of memory; the read-only parts must come from the -executable file. - -@@samp{core-file} with no argument specifies that no core file is -to be used. - -@@item add-file @@var{filename} @@var{address} -@@kindex add-file -The @@samp{add-file} command takes two arguments, a file name, and the -address at which that file has been (or should be) dynamically loaded. -GDB will then treat that file as though it had always been dynamically -linked, and provide the user with all the normal GDB features, including -symbolic debugging. - -With the @@samp{add-file} command, it is possible to debug code which was -not present in the initial load image of the program under test. -Suppose you have a program which can, while running, dynamically link a -program fragment into its address space. One program which does this is -KCL, a free common lisp implementation. The fragment will be loaded -into the main program's address space at some address, and the main -program can then call functions within the fragment by calculating (or -otherwise obtaining) their addresses. - -@@item kill -@@kindex kill -Cancel running the program under GDB. This could be used if you wish -to debug a core dump instead. GDB ignores any core dump file if it is -actually running the program, so the @@samp{kill} command is the only -sure way to go back to using the core dump file. - -@@item info files -@@kindex info files -Print the names of the executable and core dump files currently in -use by GDB, and the file from which symbols were loaded. -@@end table - -While all three file-specifying commands allow both absolute and relative -file names as arguments, GDB always converts the file name to an absolute -one and remembers it that way. - -The @@samp{symbol-file} command causes GDB to forget the contents of its -convenience variables, the value history, and all breakpoints and -auto-display expressions. This is because they may contain pointers to the -internal data recording symbols and data types, which are part of the old -symbol table data being discarded inside GDB. - -@@node Options, Compilation, Files, Top -@@chapter Options and Arguments for GDB - -When you invoke GDB, you can pass commands telling it what files to -operate on and what other things to do. - -@@menu -* Mode Options:: Options controlling modes of operation. -* File Options:: Options to specify files (executable, coredump, commands) -* Other Arguments:: Any other arguments without options - also specify files. -@@end menu - -@@node Mode Options, File Options, Options, Options -@@section Mode Options - -@@table @@samp -@@item -nx -Do not execute commands from the init files @@file{.gdbinit}. -Normally, the commands in these files are executed after all the -command options and arguments have been processed. @@xref{Command -Files}. - -@@item -q -``Quiet''. Do not print the usual introductory messages. - -@@item -batch -Run in batch mode. Exit with code 1 after processing all the command -files specified with @@samp{-x} (and @@file{.gdbinit}, if not -inhibited). Exit also if, due to an error, GDB would otherwise -attempt to read a command from the terminal. - -@@item -fullname -This option is used when Emacs runs GDB as a subprocess. It tells GDB -to output the full file name and line number in a standard, -recognizable fashion each time a stack frame is displayed (which -includes each time the program stops). This recognizable format looks -like two @@samp{\032} characters, followed by the filename, line number -and character position separated by colons, and a newline. The -Emacs-to-GDB interface program uses the two @@samp{\032} characters as -a signal to display the source code for the frame. -@@end table - -@@node File Options, Other Arguments, Mode Options, Options -@@section File-specifying Options - -All the options and command line arguments given are processed -in sequential order. The order makes a difference when the -@@samp{-x} command is used. - -@@table @@samp -@@item -s @@var{file} -Read symbol table from file @@var{file}. - -@@item -e @@var{file} -Use file @@var{file} as the executable file to execute when -appropriate, and for examining pure data in conjunction with a core -dump. - -@@item -se @@var{file} -Read symbol table from file @@var{file} and use it as the executable -file. - -@@item -c @@var{file} -Use file @@var{file} as a core dump to examine. - -@@item -x @@var{file} -Execute GDB commands from file @@var{file}. - -@@item -d @@var{directory} -Add @@var{directory} to the path to search for source files. -@@end table - -@@node Other Arguments,, File Options, Options -@@section Other Arguments - -If there are arguments to GDB that are not options or associated with -options, the first one specifies the symbol table and executable file name -(as if it were preceded by @@samp{-se}) and the second one specifies a core -dump file name (as if it were preceded by @@samp{-c}). - -@@node Compilation, Running, Options, Top -@@chapter Compiling Your Program for Debugging - -In order to debug a program effectively, you need to ask for debugging -information when you compile it. This information in the object file -describes the data type of each variable or function and the correspondence -between source line numbers and addresses in the executable code. - -To request debugging information, specify the @@samp{-g} option when you run -the compiler. - -The Unix C compiler is unable to handle the @@samp{-g} and @@samp{-O} options -together. This means that you cannot ask for optimization if you ask for -debugger information. - -The GNU C compiler supports @@samp{-g} with or without @@samp{-O}, making it -possible to debug optimized code. We recommend that you @@emph{always} use -@@samp{-g} whenever you compile a program. You may think the program is -correct, but there's no sense in pushing your luck. - -If you are using the GNU C compiler, the GNU assembler and the GNU linker, -you can choose between two formats of debugging information: the standard -Unix format, which is what you get with @@samp{-g}, and GDB's own format, -which you request by using @@samp{-gg} instead of @@samp{-g}. This stores -debugging information in the executable file in a format much like that -which is used inside GDB. This has these advantages and disadvantages: - -@@itemize @@bullet -@@item -GDB can read @@samp{-gg} format more than twice as fast as Unix -@@samp{-g} format. - -@@item -The @@samp{-gg} format uses much more disk space than Unix format. - -@@item -The Unix debuggers can understand only Unix format, so you cannot use -Unix source-level debuggers if you compile with @@samp{-gg}. (The -@@code{adb} debugger works with either format; it does not use this -information in any case.) -@@end itemize - -@@node Running, Stopping, Compilation, Top -@@chapter Running Your Program Under GDB - -@@cindex running -@@kindex run -To start your program under GDB, use the @@samp{run} command. The program -must already have been specified using the @@samp{exec-file} command or with -an argument to GDB (@@pxref{Files}); what @@samp{run} does is create an -inferior process, load the program into it, and set it in motion. - -The execution of a program is affected by certain information it receives -from its superior. GDB provides ways to specify them, which you must do -@@i{before} starting the program. (You can change them after starting the -program, but such changes do not affect the program unless you start it -over again.) - -@@table @@asis -@@item The @@i{arguments.} -You specify the arguments to give the program as the arguments of the -@@samp{run} command. - -@@item The @@i{environment.} -The program normally inherits its environment from GDB, but you can -use the GDB commands @@samp{set environment} and -@@samp{unset environment} to change parts of the environment that will -be given to the program.@@refill - -@@item The @@i{working directory.} -The program inherits its working directory from GDB. You can set GDB's -working directory with the @@samp{cd} command in GDB. -@@end table - -After the @@samp{run} command, the debugger does nothing but wait for your -program to stop. @@xref{Stopping}. - -Note that once your program has been started by the @@samp{run} command, -you may evaluate expressions that involve calls to functions in the -inferior. @@xref{Expressions}. If you wish to evaluate a function -simply for it's side affects, you may use the @@samp{set} command. -@@xref{Assignment}. - -@@menu -* Arguments:: Specifying the arguments for your program. -* Environment:: Specifying the environment for your program. -* Working Directory:: Specifying the working directory for giving - to your program when it is run. -* Input/Output:: Specifying the program's standard input and output. -* Attach:: Debugging a process started outside GDB. -@@end menu - -@@node Arguments, Environment, Running, Running -@@section Your Program's Arguments - -@@cindex arguments (to your program) -You specify the arguments to give the program as the arguments of the -@@samp{run} command. They are passed to a shell, which expands wildcard -characters and performs redirection of I/O, and thence to the program. - -@@samp{run} with no arguments uses the same arguments used by the previous -@@samp{run}. - -@@kindex set args -The command @@samp{set args} can be used to specify the arguments to be used -the next time the program is run. If @@samp{set args} has no arguments, it -means to use no arguments the next time the program is run. If you have -run your program with arguments and want to run it again with no arguments, -this is the only way to do so. - -@@node Environment, Working Directory, Arguments, Running -@@section Your Program's Environment - -@@cindex environment (of your program) -The @@dfn{environment} consists of a set of @@dfn{environment variables} and -their values. Environment variables conventionally record such things as -your user name, your home directory, your terminal type, and your search -path for programs to run. Usually you set up environment variables with -the shell and they are inherited by all the other programs you run. When -debugging, it can be useful to try running the program with different -environments without having to start the debugger over again. - -@@table @@code -@@item info environment @@var{varname} -@@kindex info environment -Print the value of environment variable @@var{varname} to be given to -your program when it is started. This command can be abbreviated -@@samp{i env @@var{varname}}. - -@@item info environment -Print the names and values of all environment variables to be given to -your program when it is started. This command can be abbreviated -@@samp{i env}. - -@@item set environment @@var{varname} @@var{value} -@@item set environment @@var{varname} = @@var{value} -@@kindex set environment -Sets environment variable @@var{varname} to @@var{value}, for your program -only, not for GDB itself. @@var{value} may be any string; the values of -environment variables are just strings, and any interpretation is -supplied by your program itself. The @@var{value} parameter is optional; -if it is eliminated, the variable is set to a null value. This command -can be abbreviated as short as @@samp{set e}. - -@@item delete environment @@var{varname} -@@kindex delete environment -@@item unset environment @@var{varname} -@@kindex unset environment -Remove variable @@var{varname} from the environment to be passed to -your program. This is different from @@samp{set env @@var{varname} =} -because @@samp{delete environment} makes a variable not be defined at -all, which is distinguishable from an empty value. This command can -be abbreviated @@samp{d e}. -@@end table - -@@node Working Directory, Input/Output, Environment, Running -@@section Your Program's Working Directory - -@@cindex working directory (of your program) -Each time you start your program with @@samp{run}, it inherits its working -directory from the current working directory of GDB. GDB's working -directory is initially whatever it inherited from its superior, but you can -specify the working directory for GDB with the @@samp{cd} command. - -The GDB working directory also serves as a default for the commands -that specify files for GDB to operate on. @@xref{Files}. - -@@table @@code -@@item cd @@var{directory} -@@kindex cd -Set GDB's working directory to @@var{directory}. - -@@item pwd -@@kindex pwd -Print GDB's working directory. -@@end table - -@@node Input/Output, Attach, Working Directory, Running -@@section Your Program's Input and Output - -@@cindex redirection -@@cindex controlling terminal -By default, the program you run under GDB does input and output to the same -terminal that GDB uses. - -You can redirect the program's input and/or output using @@samp{sh}-style -redirection commands in the @@samp{run} command. For example, - -@@example -run > outfile -@@end example - -@@noindent -starts the program, diverting its output to the file @@file{outfile}. - -@@kindex tty -Another way to specify where the program should do input and output is with -the @@samp{tty} command. This command accepts a file name as argument, and -causes this file to be the default for future @@samp{run} commands. It also -resets the controlling terminal for future @@samp{run} commands. For -example, - -@@example -tty /dev/ttyb -@@end example - -@@noindent -directs that processes started with subsequent @@samp{run} commands default -to do input and output on the terminal @@file{/dev/ttyb} and sets the -controlling terminal to @@file{/dev/ttyb}. An explicit redirection in -@@samp{run} overrides the @@samp{tty} command's effect on input/output -redirection. - -When you use the @@samp{tty} command or redirect input in the @@samp{run} -command, the @@emph{input for your program} comes from the specified file, -but the input for GDB still comes from your terminal. - -@@node Attach,, Input/Output, Running -@@section Debugging an Already-Running Process -@@kindex detach -@@kindex attach -@@cindex attach - -Some operating systems (in particular, Sun) allow GDB to begin debugging an -already-running process that was started outside of GDB. To do this you -must use the @@samp{attach} command instead of the @@samp{run} command. - -The @@samp{attach} command requires one argument, which is the process-id of -the process you want to debug. (The usual way to find out the process-id -of the process is with the @@samp{ps} utility.) - -The first thing GDB does after arranging to debug the process is to stop -it. You can examine and modify an attached process with all the GDB -commands that ordinarily available when you start processes with -@@samp{run}. You can insert breakpoints; you can step and continue; you -can modify storage. If you would rather the process continue running, -use the @@samp{continue} command after attaching. - -When you are finished debugging the attached process, you can use the -@@samp{detach} command to release it from GDB's control. Detaching -the process continues its execution. After the @@samp{detach} command, -that process and GDB become completely independent once more, and you -are ready to @@samp{attach} another process or start one with @@samp{run}. - -If you exit GDB or use the @@samp{run} command while you have an attached -process, you kill that process. You will be asked for confirmation if you -try to do either of these things. - -@@node Stopping, Stack, Running, Top -@@chapter Stopping and Continuing - -When you run a program normally, it runs until exiting. The purpose -of using a debugger is so that you can stop it before that point; -or so that if the program runs into trouble you can find out why. - -@@menu -* Signals:: Fatal signals in your program just stop it; - then you can use GDB to see what is going on. -* Breakpoints:: Breakpoints let you stop your program when it - reaches a specified point in the code. -* Continuing:: Resuming execution until the next signal or breakpoint. -* Stepping:: Stepping runs the program a short distance and - then stops it wherever it has come to. -@@end menu - -@@node Signals, Breakpoints, Stopping, Stopping -@@section Signals - -A signal is an asynchronous event that can happen in a program. The -operating system defines the possible kinds of signals, and gives each kind -a name and a number. For example, @@code{SIGINT} is the signal a program -gets when you type @@kbd{Ctrl-c}; @@code{SIGSEGV} is the signal a program -gets from referencing a place in memory far away from all the areas in use; -@@code{SIGALRM} occurs when the alarm clock timer goes off (which happens -only if the program has requested an alarm). - -Some signals, including @@code{SIGALRM}, are a normal part of the -functioning of the program. Others, such as @@code{SIGSEGV}, indicate -errors; these signals are @@dfn{fatal} (kill the program immediately) if the -program has not specified in advance some other way to handle the signal. -@@code{SIGINT} does not indicate an error in the program, but it is normally -fatal so it can carry out the purpose of @@kbd{Ctrl-c}: to kill the program. - -GDB has the ability to detect any occurrence of a signal in the program -running under GDB's control. You can tell GDB in advance what to do for -each kind of signal. - -Normally, GDB is set up to ignore non-erroneous signals like @@code{SIGALRM} -(so as not to interfere with their role in the functioning of the program) -but to stop the program immediately whenever an error signal happens. -You can change these settings with the @@samp{handle} command. You must -specify which signal you are talking about with its number. - -@@table @@code -@@item info signal -@@kindex info signal -Print a table of all the kinds of signals and how GDB has been told to -handle each one. You can use this to see the signal numbers of all -the defined types of signals. - -@@item handle @@var{signalnum} @@var{keywords}@@dots{} -@@kindex handle -Change the way GDB handles signal @@var{signalnum}. The @@var{keywords} -say what change to make. -@@end table - -To use the @@samp{handle} command you must know the code number of the -signal you are concerned with. To find the code number, type @@samp{info -signal} which prints a table of signal names and numbers. - -The keywords allowed by the handle command can be abbreviated. Their full -names are - -@@table @@code -@@item stop -GDB should stop the program when this signal happens. This implies -the @@samp{print} keyword as well. - -@@item print -GDB should print a message when this signal happens. - -@@item nostop -GDB should not stop the program when this signal happens. It may -still print a message telling you that the signal has come in. - -@@item noprint -GDB should not mention the occurrence of the signal at all. This -implies the @@samp{nostop} keyword as well. - -@@item pass -GDB should allow the program to see this signal; the program will be -able to handle the signal, or may be terminated if the signal is fatal -and not handled. - -@@item nopass -GDB should not allow the program to see this signal. -@@end table - -When a signal has been set to stop the program, the program cannot see the -signal until you continue. It will see the signal then, if @@samp{pass} is -in effect for the signal in question @@i{at that time}. In other words, -after GDB reports a signal, you can use the @@samp{handle} command with -@@samp{pass} or @@samp{nopass} to control whether that signal will be seen by -the program when you later continue it. - -You can also use the @@samp{signal} command to prevent the program from -seeing a signal, or cause it to see a signal it normally would not see, -or to give it any signal at any time. @@xref{Signaling}. - -@@node Breakpoints, Continuing, Signals, Stopping -@@section Breakpoints - -@@cindex breakpoints -A @@dfn{breakpoint} makes your program stop whenever a certain point in the -program is reached. You set breakpoints explicitly with GDB commands, -specifying the place where the program should stop by line number, function -name or exact address in the program. You can add various other conditions -to control whether the program will stop. - -Each breakpoint is assigned a number when it is created; these numbers are -successive integers starting with 1. In many of the commands for controlling -various features of breakpoints you use the breakpoint number to say which -breakpoint you want to change. Each breakpoint may be @@dfn{enabled} or -@@dfn{disabled}; if disabled, it has no effect on the program until you -enable it again. - -@@kindex info break -@@kindex $_ -The command @@samp{info break} prints a list of all breakpoints set and not -cleared, showing their numbers, where in the program they are, and any -special features in use for them. Disabled breakpoints are included in the -list, but marked as disabled. @@samp{info break} with a breakpoint number -as argument lists only that breakpoint. The convenience variable @@samp{$_} -and the default examining-address for the @@samp{x} command are set to the -address of the last breakpoint listed (@@pxref{Memory}). - -@@menu -* Set Breaks:: How to establish breakpoints. -* Clear Breaks:: How to remove breakpoints no longer needed. -* Disabling:: How to disable breakpoints (turn them off temporarily). -* Conditions:: Making extra conditions on whether to stop. -* Break Commands:: Commands to be executed at a breakpoint. -* Error in Breakpoints:: "Cannot insert breakpoints" error--why, what to do. -@@end menu - -@@node Set Breaks, Clear Breaks, Breakpoints, Breakpoints -@@subsection Setting Breakpoints - -@@kindex break -Breakpoints are set with the @@samp{break} command (abbreviated @@samp{b}). -You have several ways to say where the breakpoint should go. - -@@table @@code -@@item break @@var{function} -Set a breakpoint at entry to function @@var{function}. - -@@item break @@var{linenum} -Set a breakpoint at line @@var{linenum} in the current source file. -That file is the last file whose source text was printed. This -breakpoint will stop the program just before it executes any of the -code on that line. - -@@item break @@var{filename}:@@var{linenum} -Set a breakpoint at line @@var{linenum} in source file @@var{filename}. - -@@item break @@var{filename}:@@var{function} -Set a breakpoint at entry to function @@var{function} found in file -@@var{filename}. Specifying a filename as well as a function name is -superfluous except when multiple files contain similarly named -functions. - -@@item break *@@var{address} -Set a breakpoint at address @@var{address}. You can use this to set -breakpoints in parts of the program which do not have debugging -information or source files. - -@@item break -Set a breakpoint at the next instruction to be executed in the selected -stack frame (@@pxref{Stack}). In any selected frame but the innermost, -this will cause the program to stop as soon as control returns to that -frame. This is equivalent to a @@samp{finish} command in the frame -inside the selected frame. If this is done in the innermost frame gdb -will stop the next time it reaches the current location; this may be -useful inside of loops. It does not stop at this breakpoint immediately -upon continuation of the program since no code would be executed if it -did. - -@@item break @@dots{} if @@var{cond} -Set a breakpoint with condition @@var{cond}; evaluate the expression -@@var{cond} each time the breakpoint is reached, and stop only if the -value is nonzero. @@samp{@@dots{}} stands for one of the possible -arguments described above (or no argument) specifying where to break. -@@xref{Conditions}, for more information on breakpoint conditions. - -@@item tbreak @@var{args} -@@kindex tbreak -Set a breakpoint enabled only for one stop. @@var{args} are the -same as in the @@samp{break} command, and the breakpoint is set in the same -way, but the breakpoint is automatically @@dfn{disabled} the first time it -is hit. -@@end table - -GDB allows you to set any number of breakpoints at the same place in the -program. There is nothing silly or meaningless about this. When the -breakpoints are conditional, this is even useful (@@pxref{Conditions}). - -@@node Clear Breaks, Disabling, Set Breaks, Breakpoints -@@subsection Clearing Breakpoints - -@@cindex clear breakpoint -@@cindex delete breakpoints -It is often necessary to eliminate a breakpoint once it has done its job -and you no longer want the program to stop there. This is called -@@dfn{clearing} or @@samp{deleting} the breakpoint. A breakpoint that -has been cleared no longer exists in any sense. - -With the @@samp{clear} command you can clear breakpoints according to where -they are in the program. With the @@samp{delete} command you can clear -individual breakpoints by specifying their breakpoint numbers. - -@@b{It is not necessary to clear a breakpoint to proceed past it.} GDB -automatically ignores breakpoints in the first instruction to be executed -when you continue execution at the same address where the program stopped. - -@@table @@code -@@item clear -@@kindex clear -Clear any breakpoints at the next instruction to be executed in the -selected stack frame (@@pxref{Selection}). When the innermost frame -is selected, this is a good way to clear a breakpoint that the program -just stopped at. - -@@item clear @@var{function} -@@itemx clear @@var{filename}:@@var{function} -Clear any breakpoints set at entry to the function @@var{function}. - -@@item clear @@var{linenum} -@@item clear @@var{filename}:@@var{linenum} -Clear any breakpoints set at or within the code of the specified line. - -@@item delete @@var{bnums}@@dots{} -@@kindex delete -Delete the breakpoints of the numbers specified as arguments. -A breakpoint deleted is forgotten completely. -@@end table - -@@node Disabling, Conditions, Clear Breaks, Breakpoints -@@subsection Disabling Breakpoints - -@@cindex disabled breakpoints -@@cindex enabled breakpoints -Rather than clearing a breakpoint, you might prefer to @@dfn{disable} it. -This makes the breakpoint inoperative as if it had been cleared, but -remembers the information on the breakpoint so that you can @@dfn{enable} -it again later. - -You disable and enable breakpoints with the @@samp{enable} and -@@samp{disable} commands, specifying one or more breakpoint numbers as -arguments. Use @@samp{info break} to print a list of breakpoints if you -don't know which breakpoint numbers to use. - -A breakpoint can have any of four different states of enablement: - -@@itemize @@bullet -@@item -Enabled. The breakpoint will stop the program. A breakpoint made -with the @@samp{break} command starts out in this state. -@@item -Disabled. The breakpoint has no effect on the program. -@@item -Enabled once. The breakpoint will stop the program, but -when it does so it will become disabled. A breakpoint made -with the @@samp{tbreak} command starts out in this state. -@@item -Enabled for deletion. The breakpoint will stop the program, but -immediately after it does so it will be deleted permanently. -@@end itemize - -You change the state of enablement of a breakpoint with the following -commands: - -@@table @@code -@@item disable breakpoints @@var{bnums}@@dots{} -@@kindex disable breakpoints -@@item disable @@var{bnums}@@dots{} -@@kindex disable -Disable the specified breakpoints. A disabled breakpoint has no -effect but is not forgotten. All options such as ignore-counts, -conditions and commands are remembered in case the breakpoint is -enabled again later. - -@@item enable breakpoints @@var{bnums}@@dots{} -@@kindex enable breakpoints -@@item enable @@var{bnums}@@dots{} -@@kindex enable -Enable the specified breakpoints. They become effective once again in -stopping the program, until you specify otherwise. - -@@item enable breakpoints once @@var{bnums}@@dots{} -@@item enable once @@var{bnums}@@dots{} -Enable the specified breakpoints temporarily. Each will be disabled -again the next time it stops the program (unless you have used one of -these commands to specify a different state before that time comes). - -@@item enable breakpoints delete @@var{bnums}@@dots{} -@@item enable delete @@var{bnums}@@dots{} -Enable the specified breakpoints to work once and then die. Each of -the breakpoints will be deleted the next time it stops the program -(unless you have used one of these commands to specify a different -state before that time comes). -@@end table - -Aside from the automatic disablement or deletion of a breakpoint when it -stops the program, which happens only in certain states, the state of -enablement of a breakpoint changes only when one of the commands above -is used. - -@@node Conditions, Break Commands, Disabling, Breakpoints -@@subsection Break Conditions - -@@cindex conditions -The simplest sort of breakpoint breaks every time the program reaches a -specified place. You can also specify a @@dfn{condition} for a breakpoint. -A condition is just a boolean expression in your programming language -(@@xref{Expressions}). A breakpoint with a condition evaluates the -expression each time the program reaches it, and the program stops -only if the condition is true. - -Break conditions may have side effects, and may even call functions in your -program. These may sound like strange things to do, but their effects are -completely predictable unless there is another enabled breakpoint at the -same address. (In that case, GDB might see the other breakpoint first and -stop the program without checking the condition of this one.) Note that -breakpoint commands are usually more convenient and flexible for the -purpose of performing side effects when a breakpoint is reached -(@@pxref{Break Commands}). - -Break conditions can be specified when a breakpoint is set, by using -@@samp{if} in the arguments to the @@samp{break} command. @@xref{Set Breaks}. -They can also be changed at any time with the @@samp{condition} command: - -@@table @@code -@@item condition @@var{bnum} @@var{expression} -@@kindex condition -Specify @@var{expression} as the break condition for breakpoint number -@@var{bnum}. From now on, this breakpoint will stop the program only if -the value of @@var{expression} is true (nonzero, in C). @@var{expression} -is not evaluated at the time the @@samp{condition} command is given. -@@xref{Expressions}. - -@@item condition @@var{bnum} -Remove the condition from breakpoint number @@var{bnum}. It becomes -an ordinary unconditional breakpoint. -@@end table - -@@cindex ignore count (of breakpoint) -A special feature is provided for one kind of condition: to prevent the -breakpoint from doing anything until it has been reached a certain number -of times. This is done with the @@dfn{ignore count} of the breakpoint. -When the program reaches a breakpoint whose ignore count is positive, then -instead of stopping, it just decrements the ignore count by one and -continues. - -@@table @@code -@@item ignore @@var{bnum} @@var{count} -@@kindex ignore -Set the ignore count of breakpoint number @@var{bnum} to @@var{count}. -The next @@var{count} times the breakpoint is reached, it will not stop. - -To make the breakpoint stop the next time it is reached, specify -a count of zero. - -@@item cont @@var{count} -Continue execution of the program, setting the ignore count of the -breakpoint that the program stopped at to @@var{count} minus one. -Continuing through the breakpoint does not itself count as one of -@@var{count}. Thus, the program will not stop at this breakpoint until the -@@var{count}'th time it is hit. - -This command is allowed only when the program stopped due to a -breakpoint. At other times, the argument to @@samp{cont} is ignored. -@@end table - -If a breakpoint has a positive ignore count and a condition, the condition -is not checked. Once the ignore count reaches zero, the condition will -start to be checked. - -Note that you could achieve the effect of the ignore count with a condition -such as @@samp{$foo-- <= 0} using a debugger convenience variable that is -decremented each time. That is why the ignore count is considered a -special case of a condition. @@xref{Convenience Vars}. - -@@node Break Commands, Error in Breakpoints, Conditions, Breakpoints -@@subsection Commands Executed on Breaking - -@@cindex breakpoint commands -You can give any breakpoint a series of commands to execute when the -program stops due to that breakpoint. For example, you might want to -print the values of certain expressions, or enable other breakpoints. - -@@table @@code -@@item commands @@var{bnum} -Specify commands for breakpoint number @@var{bnum}. The commands -themselves appear on the following lines. Type a line containing just -@@samp{end} to terminate the commands. - -To remove all commands from a breakpoint, use the command -@@samp{commands} and follow it immediately by @@samp{end}; that is, give -no commands. - -With no arguments, @@samp{commands} refers to the last breakpoint set. -@@end table - -It is possible for breakpoint commands to start the program up again. -Simply use the @@samp{cont} command, or @@samp{step}, or any other command -to resume execution. However, any remaining breakpoint commands are -ignored. When the program stops again, GDB will act according to why -that stop took place. - -@@kindex silent -If the first command specified is @@samp{silent}, the usual message about -stopping at a breakpoint is not printed. This may be desirable for -breakpoints that are to print a specific message and then continue. -If the remaining commands too print nothing, you will see no sign that -the breakpoint was reached at all. @@samp{silent} is not really a command; -it is meaningful only at the beginning of the commands for a breakpoint. - -The commands @@samp{echo} and @@samp{output} that allow you to print precisely -controlled output are often useful in silent breakpoints. @@xref{Output}. - -For example, here is how you could use breakpoint commands to print the -value of @@code{x} at entry to @@code{foo} whenever it is positive. We -assume that the newly created breakpoint is number 4; @@samp{break} will -print the number that is assigned. - -@@example -break foo if x>0 -commands 4 -silent -echo x is\040 -output x -echo \n -cont -end -@@end example - -One application for breakpoint commands is to correct one bug so you can -test another. Put a breakpoint just after the erroneous line of code, give -it a condition to detect the case in which something erroneous has been -done, and give it commands to assign correct values to any variables that -need them. End with the @@samp{cont} command so that the program does not -stop, and start with the @@samp{silent} command so that no output is -produced. Here is an example: - -@@example -break 403 -commands 5 -silent -set x = y + 4 -cont -end -@@end example - -One deficiency in the operation of automatically continuing breakpoints -under Unix appears when your program uses raw mode for the terminal. -GDB switches back to its own terminal modes (not raw) before executing -commands, and then must switch back to raw mode when your program is -continued. This causes any pending terminal input to be lost. - -In the GNU system, this will be fixed by changing the behavior of -terminal modes. - -Under Unix, when you have this problem, you might be able to get around -it by putting your actions into the breakpoint condition instead of -commands. For example - -@@example -condition 5 (x = y + 4), 0 -@@end example - -@@noindent -is a condition expression (@@xref{Expressions}) that will change @@code{x} -as needed, then always have the value 0 so the program will not stop. -Loss of input is avoided here because break conditions are evaluated -without changing the terminal modes. When you want to have nontrivial -conditions for performing the side effects, the operators @@samp{&&}, -@@samp{||} and @@samp{?@@: @@dots{} :@@:} may be useful. - -@@node Error in Breakpoints,, Break Commands, Breakpoints -@@subsection ``Cannot Insert Breakpoints'' Error - -Under some Unix systems, breakpoints cannot be used in a program if any -other process is running that program. Attempting to run or continue -the program with a breakpoint in this case will cause GDB to stop it. - -When this happens, you have three ways to proceed: - -@@enumerate -@@item -Remove or disable the breakpoints, then continue. - -@@item -Suspend GDB, and copy the file containing the program to a new name. -Resume GDB and use the @@samp{exec-file} command to specify that GDB -should run the program under that name. Then start the program again. - -@@item -Recompile the program so that the text is non-sharable (a.out format -OMAGIC). -@@end enumerate - -@@node Continuing, Stepping, Breakpoints, Stopping -@@section Continuing - -After your program stops, most likely you will want it to run some more if -the bug you are looking for has not happened yet. - -@@table @@code -@@item cont -@@kindex cont -Continue running the program at the place where it stopped. -@@end table - -If the program stopped at a breakpoint, the place to continue running -is the address of the breakpoint. You might expect that continuing would -just stop at the same breakpoint immediately. In fact, @@samp{cont} -takes special care to prevent that from happening. You do not need -to clear the breakpoint to proceed through it after stopping at it. - -You can, however, specify an ignore-count for the breakpoint that the -program stopped at, by means of an argument to the @@samp{cont} command. -@@xref{Conditions}. - -If the program stopped because of a signal other than @@code{SIGINT} or -@@code{SIGTRAP}, continuing will cause the program to see that signal. -You may not want this to happen. For example, if the program stopped -due to some sort of memory reference error, you might store correct -values into the erroneous variables and continue, hoping to see more -execution; but the program would probably terminate immediately as -a result of the fatal signal once it sees the signal. To prevent this, -you can continue with @@samp{signal 0}. @@xref{Signaling}. You can -also act in advance to prevent the program from seeing certain kinds -of signals, using the @@samp{handle} command (@@pxref{Signals}). - -@@node Stepping,, Continuing, Stopping -@@section Stepping - -@@cindex stepping -@@dfn{Stepping} means setting your program in motion for a limited time, so -that control will return automatically to the debugger after one line of -code or one machine instruction. Breakpoints are active during stepping -and the program will stop for them even if it has not gone as far as the -stepping command specifies. - -@@table @@code -@@item step -@@kindex step -Proceed the program until control reaches a different line, then stop -it and return to the debugger. This command is abbreviated @@samp{s}. - -@@item step @@var{count} -Proceed as in @@samp{step}, but do so @@var{count} times. If a breakpoint -or a signal not related to stepping is reached before @@var{count} steps, -stepping stops right away. - -This command may be given when control is within a routine for which -there is no debugging information. In that case, execution will proceed -until control reaches a different routine, or is about to return from -this routine. An argument repeats this action. - -@@item next -@@kindex next -Similar to @@samp{step}, but any function calls appearing within the line of -code are executed without stopping. Execution stops when control reaches a -different line of code at the stack level which was executing when the -@@samp{next} command was given. This command is abbreviated @@samp{n}. - -An argument is a repeat count, as in @@samp{step}. - -@@samp{next} within a routine without debugging information acts as does -@@samp{step}, but any function calls appearing within the code of the -routine are executed without stopping. - -@@item finish -@@kindex finish -Continue running until just after the selected stack frame returns -(or until there is some other reason to stop, such as a fatal signal -or a breakpoint). Print value returned by the selected stack frame (if -any). - -Contrast this with the @@samp{return} command (@@pxref{Returning}). - -@@item until -@@kindex until -Proceed the program until control reaches a line greater than the current -line, then stop is and return to the debugger. Control is also returned to -the debugger if the program exits the current stack frame. Note that this -form of the command uses single stepping, and hence is slower than -@@samp{until} with an argument. This command is abbreviated @@samp{u}. - -@@item until @@var{location} -Proceed the program until either the specified location is reached, or the -current (innermost) stack frame returns. This form of the command uses -breakpoints, and hence is quicker than @@samp{until} without an argument. - -@@item stepi -@@itemx si -@@kindex stepi -@@kindex si -Proceed one machine instruction, then stop and return to the debugger. - -It is often useful to do @@samp{display/i $pc} when stepping by machine -instructions. This will cause the next instruction to be executed to -be displayed automatically at each stop. @@xref{Auto Display}. - -An argument is a repeat count, as in @@samp{step}. - -@@item nexti -@@itemx ni -@@kindex nexti -@@kindex ni -Proceed one machine instruction, but if it is a subroutine call, -proceed until the subroutine returns. - -An argument is a repeat count, as in @@samp{next}. -@@end table - -A typical technique for using stepping is to put a breakpoint -(@@pxref{Breakpoints}) at the beginning of the function or the section of -the program in which a problem is believed to lie, and then step through -the suspect area, examining the variables that are interesting, until the -problem happens. - -The @@samp{cont} command can be used after stepping to resume execution -until the next breakpoint or signal. - -@@node Stack, Source, Stopping, Top -@@chapter Examining the Stack - -When your program has stopped, the first thing you need to know is where it -stopped and how it got there. - -@@cindex call stack -Each time your program performs a function call, the information about -where in the program the call was made from is saved in a block of data -called a @@dfn{stack frame}. The frame also contains the arguments of the -call and the local variables of the function that was called. All the -stack frames are allocated in a region of memory called the @@dfn{call -stack}. - -When your program stops, the GDB commands for examining the stack allow you -to see all of this information. - -One of the stack frames is @@dfn{selected} by GDB and many GDB commands -refer implicitly to the selected frame. In particular, whenever you ask -GDB for the value of a variable in the program, the value is found in the -selected frame. There are special GDB commands to select whichever frame -you are interested in. - -When the program stops, GDB automatically selects the currently executing -frame and describes it briefly as the @@samp{frame} command does -(@@pxref{Frame Info, Info}). - -@@menu -* Frames:: Explanation of stack frames and terminology. -* Backtrace:: Summarizing many frames at once. -* Selection:: How to select a stack frame. -* Info: Frame Info, Commands to print information on stack frames. -@@end menu - -@@node Frames, Backtrace, Stack, Stack -@@section Stack Frames - -@@cindex frame -The call stack is divided up into contiguous pieces called @@dfn{frames}; -each frame is the data associated with one call to one function. The frame -contains the arguments given to the function, the function's local -variables, and the address at which the function is executing. - -@@cindex initial frame -@@cindex outermost frame -@@cindex innermost frame -When your program is started, the stack has only one frame, that of the -function @@code{main}. This is called the @@dfn{initial} frame or the -@@dfn{outermost} frame. Each time a function is called, a new frame is -made. Each time a function returns, the frame for that function invocation -is eliminated. If a function is recursive, there can be many frames for -the same function. The frame for the function in which execution is -actually occurring is called the @@dfn{innermost} frame. This is the most -recently created of all the stack frames that still exist. - -@@cindex frame pointer -Inside your program, stack frames are identified by their addresses. A -stack frame consists of many bytes, each of which has its own address; each -kind of computer has a convention for choosing one of those bytes whose -address serves as the address of the frame. Usually this address is kept -in a register called the @@dfn{frame pointer register} while execution is -going on in that frame. - -@@cindex frame number -GDB assigns numbers to all existing stack frames, starting with zero for -the innermost frame, one for the frame that called it, and so on upward. -These numbers do not really exist in your program; they are to give you a -way of talking about stack frames in GDB commands. - -@@cindex selected frame -Many GDB commands refer implicitly to one stack frame. GDB records a stack -frame that is called the @@dfn{selected} stack frame; you can select any -frame using one set of GDB commands, and then other commands will operate -on that frame. When your program stops, GDB automatically selects the -innermost frame. - -@@node Backtrace, Selection, Frames, Stack -@@section Backtraces - -A backtrace is a summary of how the program got where it is. It shows one -line per frame, for many frames, starting with the currently executing -frame (frame zero), followed by its caller (frame one), and on up the -stack. - -@@table @@code -@@item backtrace -@@itemx bt -Print a backtrace of the entire stack: one line per frame for all -frames in the stack. - -You can stop the backtrace at any time by typing the system interrupt -character, normally @@kbd{Control-C}. - -@@item backtrace @@var{n} -@@itemx bt @@var{n} -Similar, but stop after @@var{n} frames. - -@@item backtrace @@var{-n} -@@itemx bt @@var{-n} -Similar, but print the outermost @@var{n} frames instead of the -innermost. -@@end table - -Each line in a backtrace shows the frame number, the program counter, the -function and its arguments, and the source file name and line number (if -known). The program counter is omitted if is the beginning of the code for -the source line. This is the same as the first of the two lines printed -when you select a frame. - -@@node Selection, Frame Info, Backtrace, Stack -@@section Selecting a Frame - -Most commands for examining the stack and other data in the program work on -whichever stack frame is selected at the moment. Here are the commands for -selecting a stack frame; all of them finish by printing a brief description -of the stack frame just selected. - -@@table @@code -@@item frame @@var{n} -@@kindex frame -Select frame number @@var{n}. Recall that frame zero is the innermost -(currently executing) frame, frame one is the frame that called the -innermost one, and so on. The highest-numbered frame is @@code{main}'s -frame. - -@@item frame @@var{addr} -Select the frame at address @@var{addr}. This is useful mainly if the -chaining of stack frames has been damaged by a bug, making it -impossible for GDB to assign numbers properly to all frames. In -addition, this can be useful when the program has multiple stacks and -switches between them. - -@@item up @@var{n} -@@kindex up -Select the frame @@var{n} frames up from the frame previously selected. -For positive numbers @@var{n}, this advances toward the outermost -frame, to higher frame numbers, to frames that have existed longer. -@@var{n} defaults to one. - -@@item down @@var{n} -@@kindex down -Select the frame @@var{n} frames down from the frame previously -selected. For positive numbers @@var{n}, this advances toward the -innermost frame, to lower frame numbers, to frames that were created -more recently. @@var{n} defaults to one. -@@end table - -All of these commands end by printing some information on the frame that -has been selected: the frame number, the function name, the arguments, the -source file and line number of execution in that frame, and the text of -that source line. For example: - -@@example -#3 main (argc=3, argv=??, env=??) at main.c, line 67 -67 read_input_file (argv[i]); -@@end example - -After such a printout, the @@samp{list} command with no arguments will print -ten lines centered on the point of execution in the frame. @@xref{List}. - -@@node Frame Info,, Selection, Stack -@@section Information on a Frame - -There are several other commands to print information about the selected -stack frame. - -@@table @@code -@@item frame -This command prints a brief description of the selected stack frame. -It can be abbreviated @@samp{f}. With an argument, this command is -used to select a stack frame; with no argument, it does not change -which frame is selected, but still prints the same information. - -@@item info frame -@@kindex info frame -This command prints a verbose description of the selected stack frame, -including the address of the frame, the addresses of the next frame in -(called by this frame) and the next frame out (caller of this frame), -the address of the frame's arguments, the program counter saved in it -(the address of execution in the caller frame), and which registers -were saved in the frame. The verbose description is useful when -something has gone wrong that has made the stack format fail to fit -the usual conventions. - -@@item info frame @@var{addr} -Print a verbose description of the frame at address @@var{addr}, -without selecting that frame. The selected frame remains unchanged by -this command. - -@@item info args -@@kindex info args -Print the arguments of the selected frame, each on a separate line. - -@@item info locals -@@kindex info locals -Print the local variables of the selected frame, each on a separate -line. These are all variables declared static or automatic within all -program blocks that execution in this frame is currently inside of. -@@end table - -@@node Source, Data, Stack, Top -@@chapter Examining Source Files - -GDB knows which source files your program was compiled from, and -can print parts of their text. When your program stops, GDB -spontaneously prints the line it stopped in. Likewise, when you -select a stack frame (@@pxref{Selection}), GDB prints the line -which execution in that frame has stopped in. You can also -print parts of source files by explicit command. - -@@menu -* List:: Using the @@samp{list} command to print source files. -* Search:: Commands for searching source files. -* Source Path:: Specifying the directories to search for source files. -@@end menu - -@@node List, Search, Source, Source -@@section Printing Source Lines - -@@kindex list -To print lines from a source file, use the @@samp{list} command -(abbreviated @@samp{l}). There are several ways to specify what part -of the file you want to print. - -Here are the forms of the @@samp{list} command most commonly used: - -@@table @@code -@@item list @@var{linenum} -Print ten lines centered around line number @@var{linenum} in the -current source file. - -@@item list @@var{function} -Print ten lines centered around the beginning of function -@@var{function}. - -@@item list -Print ten more lines. If the last lines printed were printed with a -@@samp{list} command, this prints ten lines following the last lines -printed; however, if the last line printed was a solitary line printed -as part of displaying a stack frame (@@pxref{Stack}), this prints ten -lines centered around that line. - -@@item list @@minus{} -Print ten lines just before the lines last printed. -@@end table - -Repeating a @@samp{list} command with @@key{RET} discards the argument, -so it is equivalent to typing just @@samp{list}. This is more useful -than listing the same lines again. An exception is made for an -argument of @@samp{-}; that argument is preserved in repetition so that -each repetition moves up in the file. - -In general, the @@samp{list} command expects you to supply zero, one or two -@@dfn{linespecs}. Linespecs specify source lines; there are several ways -of writing them but the effect is always to specify some source line. -Here is a complete description of the possible arguments for @@samp{list}: - -@@table @@code -@@item list @@var{linespec} -Print ten lines centered around the line specified by @@var{linespec}. - -@@item list @@var{first},@@var{last} -Print lines from @@var{first} to @@var{last}. Both arguments are -linespecs. - -@@item list ,@@var{last} -Print ten lines ending with @@var{last}. - -@@item list @@var{first}, -Print ten lines starting with @@var{first}. - -@@item list + -Print ten lines just after the lines last printed. - -@@item list @@minus{} -Print ten lines just before the lines last printed. - -@@item list -As described in the preceding table. -@@end table - -Here are the ways of specifying a single source line---all the -kinds of linespec. - -@@table @@asis -@@item @@var{linenum} -Specifies line @@var{linenum} of the current source file. -When a @@samp{list} command has two linespecs, this refers to -the same source file as the first linespec. - -@@item +@@var{offset} -Specifies the line @@var{offset} lines after the last line printed. -When used as the second linespec in a @@samp{list} command that has -two, this specifies the line @@var{offset} lines down from the -first linespec. - -@@item @@minus{}@@var{offset} -Specifies the line @@var{offset} lines before the last line printed. - -@@item @@var{filename}:@@var{linenum} -Specifies line @@var{linenum} in the source file @@var{filename}. - -@@item @@var{function} -Specifies the line of the open-brace that begins the body of the -function @@var{function}. - -@@item @@var{filename}:@@var{function} -Specifies the line of the open-brace that begins the body of the -function @@var{function} in the file @@var{filename}. The file name is -needed with a function name only for disambiguation of identically -named functions in different source files. - -@@item *@@var{address} -Specifies the line containing the program address @@var{address}. -@@var{address} may be any expression. -@@end table - -One other command is used to map source lines to program addresses. - -@@table @@code -@@item info line @@var{linenum} -@@kindex info line -Print the starting and ending addresses of the compiled code for -source line @@var{linenum}. - -@@kindex $_ -The default examine address for the @@samp{x} command is changed to the -starting address of the line, so that @@samp{x/i} is sufficient to -begin examining the machine code (@@pxref{Memory}). Also, this address -is saved as the value of the convenience variable @@samp{$_} -(@@pxref{Convenience Vars}). -@@end table - -@@node Search, Source Path, List, Source -@@section Searching Source Files -@@cindex searching -@@kindex forward-search -@@kindex reverse-search - -There are two commands for searching through the current source file for a -regular expression. - -The command @@samp{forward-search @@var{regexp}} checks each line, starting -with the one following the last line listed, for a match for @@var{regexp}. -It lists the line that is found. You can abbreviate the command name -as @@samp{fo}. - -The command @@samp{reverse-search @@var{regexp}} checks each line, starting -with the one before the last line listed and going backward, for a match -for @@var{regexp}. It lists the line that is found. You can abbreviate -this command with as little as @@samp{rev}. - -@@node Source Path,, Search, Source -@@section Specifying Source Directories - -@@cindex source path -@@cindex directories for source files -Executable programs do not record the directories of the source files they -were compiled from, just the names. GDB remembers a list of directories to -search for source files; this is called the @@dfn{source path}. Each time -GDB wants a source file, it tries all the directories in the list, in the -order they are present in the list, until it finds a file with the desired -name. - -@@kindex directory -When you start GDB, its source path contains just the current working -directory. To add other directories, use the @@samp{directory} command. -@@b{Note that the search path for executable files and the working directory -are @@i{not} used for finding source files.} - -@@table @@code -@@item directory @@var{dirname} -Add directory @@var{dirname} to the end of the source path. - -@@item directory -Reset the source path to just the current working directory of GDB. -This requires confirmation. - -@@samp{directory} with no argument can cause source files previously -found by GDB to be found in a different directory. To make this work -correctly, this command also clears out the tables GDB maintains -about the source files it has already found. - -@@item info directories -@@kindex info directories -Print the source path: show which directories it contains. -@@end table - -Because the @@samp{directory} command adds to the end of the source path, -it does not affect any file that GDB has already found. If the source -path contains directories that you do not want, and these directories -contain misleading files with names matching your source files, the -way to correct the situation is as follows: - -@@enumerate -@@item -Choose the directory you want at the beginning of the source path. -Use the @@samp{cd} command to make that the current working directory. - -@@item -Use @@samp{directory} with no argument to reset the source path to just -that directory. - -@@item -Use @@samp{directory} with suitable arguments to add any other -directories you want in the source path. -@@end enumerate - -@@node Data, Symbols, Source, Top -@@chapter Examining Data - -@@cindex printing data -@@cindex examining data -@@kindex print -The usual way of examining data in your program is with the @@samp{print} -command (abbreviated @@samp{p}). It evaluates and prints the value of any -valid expression of the language the program is written in (for now, C). -You type - -@@example -print @@var{exp} -@@end example - -@@noindent -where @@var{exp} is any valid expression, and the value of @@var{exp} -is printed in a format appropriate to its data type. - -A more low-level way of examining data is with the @@samp{x} command. -It examines data in memory at a specified address and prints it in a -specified format. - -GDB supports one command to modify the default format of displayed data: - -@@table @@samp -@@item set array-max -@@kindex set array-max -@@samp{set array-max} sets the maximum number of elements of an array which -will be printed. This limit also applies to the display of strings. -@@end table - -@@menu -* Expressions:: Expressions that can be computed and printed. -* Variables:: Using your program's variables in expressions. -* Assignment:: Setting your program's variables. -* Arrays:: Examining part of memory as an array. -* Formats:: Specifying formats for printing values. -* Memory:: Examining memory explicitly. -* Auto Display:: Printing certain expressions whenever program stops. -* Value History:: Referring to values previously printed. -* Convenience Vars:: Giving names to values for future reference. -* Registers:: Referring to and storing in machine registers. -@@end menu - -@@node Expressions, Variables, Data, Data -@@section Expressions - -@@cindex expressions -Many different GDB commands accept an expression and compute its value. -Any kind of constant, variable or operator defined by the programming -language you are using is legal in an expression in GDB. This includes -conditional expressions, function calls, casts and string constants. -It unfortunately does not include symbols defined by preprocessor -#define commands. - -Casts are supported in all languages, not just in C, because it is so -useful to cast a number into a pointer so as to examine a structure -at that address in memory. - -GDB supports three kinds of operator in addition to those of programming -languages: - -@@table @@code -@@item @@@@ -@@samp{@@@@} is a binary operator for treating parts of memory as arrays. -@@xref{Arrays}, for more information. - -@@item :: -@@samp{::} allows you to specify a variable in terms of the file or -function it is defined in. @@xref{Variables}. - -@@item @@{@@var{type}@@} @@var{addr} -Refers to an object of type @@var{type} stored at address @@var{addr} in -memory. @@var{addr} may be any expression whose value is an integer or -pointer (but parentheses are required around nonunary operators, just as in -a cast). This construct is allowed regardless of what kind of data is -officially supposed to reside at @@var{addr}.@@refill -@@end table - -@@node Variables, Arrays, Expressions, Data -@@section Program Variables - -The most common kind of expression to use is the name of a variable -in your program. - -Variables in expressions are understood in the selected stack frame -(@@pxref{Selection}); they must either be global (or static) or be visible -according to the scope rules of the programming language from the point of -execution in that frame. This means that in the function - -@@example -foo (a) - int a; -@@{ - bar (a); - @@{ - int b = test (); - bar (b); - @@} -@@} -@@end example - -@@noindent -the variable @@code{a} is usable whenever the program is executing -within the function @@code{foo}, but the variable @@code{b} is visible -only while the program is executing inside the block in which @@code{b} -is declared. - -As a special exception, you can refer to a variable or function whose -scope is a single source file even if the current execution point is not -in this file. But it is possible to have more than one such variable -or function with the same name (if they are in different source files). -In such a case, it is not defined which one you will get. If you wish, -you can specify any one of them using the colon-colon construct: - -@@example -@@var{block}::@@var{variable} -@@end example - -@@noindent -Here @@var{block} is the name of the source file whose variable you want. - -@@node Arrays, Formats, Variables, Data -@@section Artificial Arrays - -@@cindex artificial array -It is often useful to print out several successive objects of the -same type in memory; a section of an array, or an array of -dynamically determined size for which only a pointer exists in the -program. - -This can be done by constructing an @@dfn{artificial array} with the -binary operator @@samp{@@@@}. The left operand of @@samp{@@@@} should be -the first element of the desired array, as an individual object. -The right operand should be the length of the array. The result is -an array value whose elements are all of the type of the left argument. -The first element is actually the left argument; the second element -comes from bytes of memory immediately following those that hold the -first element, and so on. Here is an example. If a program says - -@@example -int *array = (int *) malloc (len * sizeof (int)); -@@end example - -@@noindent -you can print the contents of @@code{array} with - -@@example -p *array@@@@len -@@end example - -The left operand of @@samp{@@@@} must reside in memory. Array values made -with @@samp{@@@@} in this way behave just like other arrays in terms of -subscripting, and are coerced to pointers when used in expressions. -(It would probably appear in an expression via the value history, -after you had printed it out.) - -@@node Formats, Memory, Arrays, Data -@@section Formats - -@@cindex formatted output -@@cindex output formats -GDB normally prints all values according to their data types. Sometimes -this is not what you want. For example, you might want to print a number -in hex, or a pointer in decimal. Or you might want to view data in memory -at a certain address as a character string or an instruction. These things -can be done with @@dfn{output formats}. - -The simplest use of output formats is to say how to print a value -already computed. This is done by starting the arguments of the -@@samp{print} command with a slash and a format letter. The format -letters supported are: - -@@table @@samp -@@item x -Regard the bits of the value as an integer, and print the integer in -hexadecimal. - -@@item d -Print as integer in signed decimal. - -@@item u -Print as integer in unsigned decimal. - -@@item o -Print as integer in octal. - -@@item a -Print as an address, both absolute in hex and then relative -to a symbol defined as an address below it. - -@@item c -Regard as an integer and print it as a character constant. - -@@item f -Regard the bits of the value as a floating point number and print -using typical floating point syntax. -@@end table - -For example, to print the program counter in hex (@@pxref{Registers}), type - -@@example -p/x $pc -@@end example - -@@noindent -Note that no space is required before the slash; this is because command -names in GDB cannot contain a slash. - -To reprint the last value in the value history with a different format, -you can use the @@samp{print} command with just a format and no -expression. For example, @@samp{p/x} reprints the last value in hex. - -@@node Memory, Auto Display, Formats, Data -@@subsection Examining Memory - -@@cindex examining memory -@@kindex x -The command @@samp{x} (for `examine') can be used to examine memory under -explicit control of formats, without reference to the program's data types. - -@@samp{x} is followed by a slash and an output format specification, -followed by an expression for an address. The expression need not have -a pointer value (though it may); it is used as an integer, as the -address of a byte of memory. @@xref{Expressions} for more information -on expressions. - -The output format in this case specifies both how big a unit of memory -to examine and how to print the contents of that unit. It is done -with one or two of the following letters: - -These letters specify just the size of unit to examine: - -@@table @@samp -@@item b -Examine individual bytes. - -@@item h -Examine halfwords (two bytes each). - -@@item w -Examine words (four bytes each). - -@@cindex word -Many assemblers and cpu designers still use `word' for a 16-bit quantity, -as a holdover from specific predecessor machines of the 1970's that really -did use two-byte words. But more generally the term `word' has always -referred to the size of quantity that a machine normally operates on and -stores in its registers. This is 32 bits for all the machines that GNU -runs on. - -@@item g -Examine giant words (8 bytes). -@@end table - -These letters specify just the way to print the contents: - -@@table @@samp -@@item x -Print as integers in unsigned hexadecimal. - -@@item d -Print as integers in signed decimal. - -@@item u -Print as integers in unsigned decimal. - -@@item o -Print as integers in unsigned octal. - -@@item a -Print as an address, both absolute in hex and then relative -to a symbol defined as an address below it. - -@@item c -Print as character constants. - -@@item f -Print as floating point. This works only with sizes @@samp{w} and -@@samp{g}. - -@@item s -Print a null-terminated string of characters. The specified unit size -is ignored; instead, the unit is however many bytes it takes to reach -a null character (including the null character). - -@@item i -Print a machine instruction in assembler syntax (or nearly). The -specified unit size is ignored; the number of bytes in an instruction -varies depending on the type of machine, the opcode and the addressing -modes used. -@@end table - -If either the manner of printing or the size of unit fails to be specified, -the default is to use the same one that was used last. If you don't want -to use any letters after the slash, you can omit the slash as well. - -You can also omit the address to examine. Then the address used is -just after the last unit examined. This is why string and instruction -formats actually compute a unit-size based on the data: so that the -next string or instruction examined will start in the right place. -The @@samp{print} command sometimes sets the default address for -the @@samp{x} command; when the value printed resides in memory, the -default is set to examine the same location. @@samp{info line} also -sets the default for @@samp{x}, to the address of the start of the -machine code for the specified line and @@samp{info breakpoints} sets -it to the address of the last breakpoint listed. - -When you use @@key{RET} to repeat an @@samp{x} command, it does not repeat -exactly the same: the address specified previously (if any) is ignored, so -that the repeated command examines the successive locations in memory -rather than the same ones. - -You can examine several consecutive units of memory with one command by -writing a repeat-count after the slash (before the format letters, if any). -The repeat count must be a decimal integer. It has the same effect as -repeating the @@samp{x} command that many times except that the output may -be more compact with several units per line. - -@@example -x/10i $pc -@@end example - -@@noindent -Prints ten instructions starting with the one to be executed next in the -selected frame. After doing this, you could print another ten following -instructions with - -@@example -x/10 -@@end example - -@@noindent -in which the format and address are allowed to default. - -@@kindex $_ -@@kindex $__ -The addresses and contents printed by the @@samp{x} command are not put in -the value history because there is often too much of them and they would -get in the way. Instead, GDB makes these values available for subsequent -use in expressions as values of the convenience variables @@samp{$_} and -@@samp{$__}. - -After an @@samp{x} command, the last address examined is available for use -in expressions in the convenience variable @@samp{$_}. The contents of that -address, as examined, are available in the convenience variable @@samp{$__}. - -If the @@samp{x} command has a repeat count, the address and contents saved -are from the last memory unit printed; this is not the same as the last -address printed if several units were printed on the last line of output. - -@@node Auto Display, Value History, Memory, Data -@@section Automatic Display - -If you find that you want to print the value of an expression frequently -(to see how it changes), you might want to add it to the @@dfn{automatic -display list} so that GDB will print its value each time the program stops. -Each expression added to the list is given a number to identify it; -to remove an expression from the list, you specify that number. -The automatic display looks like this: - -@@example -2: foo = 38 -3: bar[5] = (struct hack *) 0x3804 -@@end example - -@@noindent -showing item numbers, expressions and their current values. - -@@table @@code -@@item display @@var{exp} -@@kindex display -Add the expression @@var{exp} to the list of expressions to display -each time the program stops. @@xref{Expressions}. - -@@item display/@@var{fmt} @@var{exp} -For @@var{fmt} specifying only a display format and not a size or -count, add the expression @@var{exp} to the auto-display list but -arranges to display it each time in the specified format @@var{fmt}. - -@@item display/@@var{fmt} @@var{addr} -For @@var{fmt} @@samp{i} or @@samp{s}, or including a unit-size or a -number of units, add the expression @@var{addr} as a memory address to -be examined each time the program stops. Examining means in effect -doing @@samp{x/@@var{fmt} @@var{addr}}. @@xref{Memory}. - -@@item undisplay @@var{dnums}@@dots{} -@@kindex undisplay -@@item delete display @@var{dnums}@@dots{} -@@kindex delete display -Remove item numbers @@var{dnums} from the list of expressions to display. - -@@item disable display @@var{dnums}@@dots{} -@@kindex disable display -Disable the display of item numbers @@var{dnums}. A disabled display item -has no effect but is not forgotten. It may be later enabled. - -@@item enable display @@var{dnums}@@dots{} -@@kindex enable display -Enable display of item numbers @@var{dnums}. It becomes effective once -again in auto display of its expression, until you specify otherwise. - -@@item display -Display the current values of the expressions on the list, just as is -done when the program stops. - -@@item info display -@@kindex info display -Print the list of expressions to display automatically, each one -with its item number, but without showing the values. -@@end table - -@@node Value History, Convenience Vars, Auto Display, Data -@@section Value History - -@@cindex value history -Every value printed by the @@samp{print} command is saved for the entire -session in GDB's @@dfn{value history} so that you can refer to it in -other expressions. - -@@cindex $ -@@cindex $$ -The values printed are given @@dfn{history numbers} for you to refer to them -by. These are successive integers starting with 1. @@samp{print} shows you -the history number assigned to a value by printing @@samp{$@@var{n} = } -before the value; here @@var{n} is the history number. - -To refer to any previous value, use @@samp{$} followed by the value's -history number. The output printed by @@samp{print} is designed to remind -you of this. Just @@samp{$} refers to the most recent value in the history, -and @@samp{$$} refers to the value before that. - -For example, suppose you have just printed a pointer to a structure and -want to see the contents of the structure. It suffices to type - -@@example -p *$ -@@end example - -If you have a chain of structures where the component @@samp{next} points -to the next one, you can print the contents of the next one with - -@@example -p *$.next -@@end example - -It might be useful to repeat this command many times by typing @@key{RET}. - -Note that the history records values, not expressions. If the value of -@@code{x} is 4 and you type - -@@example -print x -set x=5 -@@end example - -@@noindent -then the value recorded in the value history by the @@samp{print} command -remains 4 even though @@code{x}'s value has changed. - -@@table @@code -@@item info history -@@kindex info history -Print the last ten values in the value history, with their item -numbers. This is like @@samp{p $$9} repeated ten times, except that -@@samp{info history} does not change the history. - -@@item info history @@var{n} -Print ten history values centered on history item number @@var{n}. -@@end table - -@@node Convenience Vars, Registers, Value History, Data -@@section Convenience Variables - -@@cindex convenience variables -GDB provides @@dfn{convenience variables} that you can use within GDB to -hold on to a value and refer to it later. These variables exist entirely -within GDB; they are not part of your program, and setting a convenience -variable has no effect on further execution of your program. That's why -you can use them freely. - -Convenience variables have names starting with @@samp{$}. Any name starting -with @@samp{$} can be used for a convenience variable, unless it is one of -the predefined set of register names (@@pxref{Registers}). - -You can save a value in a convenience variable with an assignment -expression, just as you would set a variable in your program. Example: - -@@example -set $foo = *object_ptr -@@end example - -@@noindent -would save in @@samp{$foo} the value contained in the object pointed to by -@@code{object_ptr}. - -Using a convenience variable for the first time creates it; but its value -is @@code{void} until you assign a new value. You can alter the value with -another assignment at any time. - -Convenience variables have no fixed types. You can assign a convenience -variable any type of value, even if it already has a value of a different -type. The convenience variable as an expression has whatever type its -current value has. - -@@table @@code -@@item info convenience -@@kindex info convenience -Print a list of convenience variables used so far, and their values. -Abbreviated @@samp{i con}. -@@end table - -One of the ways to use a convenience variable is as a counter to be -incremented or a pointer to be advanced. For example: - -@@example -set $i = 0 -print bar[$i++]->contents -@@i{@@dots{}repeat that command by typing @@key{RET}.} -@@end example - -Some convenience variables are created automatically by GDB and given -values likely to be useful. - -@@table @@samp -@@item $_ -The variable @@samp{$_} is automatically set by the @@samp{x} command to -the last address examined (@@pxref{Memory}). Other commands which -provide a default address for @@samp{x} to examine also set @@samp{$_} -to that address; these commands include @@samp{info line} and @@samp{info -breakpoint}. - -@@item $__ -The variable @@samp{$__} is automatically set by the @@samp{x} command -to the value found in the last address examined. -@@end table - -@@node Registers,, Convenience Vars, Data -@@section Registers - -@@cindex registers -Machine register contents can be referred to in expressions as variables -with names starting with @@samp{$}. The names of registers are different -for each machine; use @@samp{info registers} to see the names used on your -machine. The names @@samp{$pc} and @@samp{$sp} are used on all machines for -the program counter register and the stack pointer. Often @@samp{$fp} is -used for a register that contains a pointer to the current stack frame. - -GDB always considers the contents of an ordinary register as an integer -when the register is examined in this way. Some machines have special -registers which can hold nothing but floating point; these registers are -considered floating point. There is no way to refer to the contents of an -ordinary register as floating point value (although you can @@emph{print} -it as a floating point value with @@samp{print/f $@@var{regname}}). - -Some registers have distinct ``raw'' and ``virtual'' data formats. This -means that the data format in which the register contents are saved by the -operating system is not the same one that your program normally sees. For -example, the registers of the 68881 floating point coprocessor are always -saved in ``extended'' format, but virtually all C programs expect to work with -``double'' format. In such cases, GDB normally works with the virtual -format only (the format that makes sense for your program), but the -@@samp{info registers} command prints the data in both formats. - -Register values are relative to the selected stack frame -(@@pxref{Selection}). This means that you get the value that the register -would contain if all stack frames farther in were exited and their saved -registers restored. In order to see the real contents of all registers, -you must select the innermost frame (with @@samp{frame 0}). - -Some registers are never saved (typically those numbered zero or one) -because they are used for returning function values; for these registers, -relativization makes no difference. - -@@table @@code -@@item info registers -@@kindex info registers -Print the names and relativized values of all registers. - -@@item info registers @@var{regname} -Print the relativized value of register @@var{regname}. @@var{regname} -may be any register name valid on the machine you are using, with -or without the initial @@samp{$}. -@@end table - -@@subsection Examples - -You could print the program counter in hex with - -@@example -p/x $pc -@@end example - -@@noindent -or print the instruction to be executed next with - -@@example -x/i $pc -@@end example - -@@noindent -or add four to the stack pointer with - -@@example -set $sp += 4 -@@end example - -@@noindent -The last is a way of removing one word from the stack, on machines where -stacks grow downward in memory (most machines, nowadays). This assumes -that the innermost stack frame is selected. Setting @@samp{$sp} is -not allowed when other stack frames are selected. - -@@node Symbols, Altering, Data, Top -@@chapter Examining the Symbol Table - -The commands described in this section allow you to make inquiries for -information about the symbols (names of variables, functions and types) -defined in your program. This information is found by GDB in the symbol -table loaded by the @@samp{symbol-file} command; it is inherent in the text -of your program and does not change as the program executes. - -@@table @@code -@@item whatis @@var{exp} -@@kindex whatis -Print the data type of expression @@var{exp}. @@var{exp} is not -actually evaluated, and any side-effecting operations (such as -assignments or function calls) inside it do not take place. -@@xref{Expressions}. - -@@item whatis -Print the data type of @@samp{$}, the last value in the value history. - -@@item info address @@var{symbol} -@@kindex info address -Describe where the data for @@var{symbol} is stored. For register -variables, this says which register. For other automatic variables, -this prints the stack-frame offset at which the variable is always -stored. Note the contrast with @@samp{print &@@var{symbol}}, which does -not work at all for register variables and for automatic variables -prints the exact address of the current instantiation of the variable. - -@@item ptype @@var{typename} -@@kindex ptype -Print a description of data type @@var{typename}. @@var{typename} may be -the name of a type, or for C code it may have the form -@@samp{struct @@var{struct-tag}}, @@samp{union @@var{union-tag}} or -@@samp{enum @@var{enum-tag}}.@@refill - -@@item info sources -@@kindex info sources -Print the names of all source files in the program for which there -is debugging information. - -@@item info functions -@@kindex info functions -Print the names and data types of all defined functions. - -@@item info functions @@var{regexp} -Print the names and data types of all defined functions -whose names contain a match for regular expression @@var{regexp}. -Thus, @@samp{info fun step} finds all functions whose names -include @@samp{step}; @@samp{info fun ^step} finds those whose names -start with @@samp{step}. - -@@item info variables -@@kindex info variables -Print the names and data types of all variables that are declared -outside of functions. - -@@item info variables @@var{regexp} -Print the names and data types of all variables, declared outside of -functions, whose names contain a match for regular expression -@@var{regexp}. - -@@item info types -@@kindex info types -Print all data types that are defined in the program. - -@@item info types @@var{regexp} -Print all data types that are defined in the program whose names -contain a match for regular expression @@var{regexp}. - -@@item info methods -@@item info methods @@var{regexp} -@@kindex info methods -The @@samp{info-methods} command permits the user to examine all defined -methods within C@@code{++} program, or (with the @@var{regexp} argument) a -specific set of methods found in the various C@@code{++} classes. Many -C@@code{++} classes which implement a large number of differently typed -methods implement a large number of methods as well. Thus, the -@@samp{ptype} command can give the user a tremendous overdose of -information about what methods are associated with a given class. The -@@samp{info-methods} command filters these methods do to only those -methods which match the regular-expression search key. - -@@item printsyms @@var{filename} -@@kindex printsyms -Write a complete dump of the debugger's symbol data into the -file @@var{filename}. -@@end table - -@@node Altering, Sequences, Symbols, Top -@@chapter Altering Execution - -There are several ways to alter the execution of your program with GDB -commands. - -@@menu -* Assignment:: Altering variable values or memory contents. -* Jumping:: Altering control flow. -* Signaling:: Making signals happen in the program. -* Returning:: Making a function return prematurely. -@@end menu - -@@node Assignment, Jumping, Altering, Altering -@@section Assignment to Variables - -@@cindex assignment -@@cindex setting variables -To alter the value of a variable, evaluate an assignment expression. -@@xref{Expressions}. For example, - -@@example -print x=4 -@@end example - -@@noindent -would store the value 4 into the variable @@code{x}, and then print -the value of the assignment expression (which is 4). - -@@kindex set -@@kindex set variable -If you are not interested in seeing the value of the assignment, use the -@@samp{set} command instead of the @@samp{print} command. @@samp{set} is -really the same as @@samp{print} except that the expression's value is not -printed and is not put in the value history (@@pxref{Value History}). The -expression is evaluated only for side effects. - -Note that if the beginning of the argument string of the @@samp{set} command -appears identical to a @@samp{set} subcommand, it may be necessary to use -the @@samp{set variable} command. This command is identical to @@samp{set} -except for its lack of subcommands. - -GDB allows more implicit conversions in assignments than C does; you can -freely store an integer value into a pointer variable or vice versa, and -any structure can be converted to any other structure that is the same -length or shorter. - -In C, all the other assignment operators such as @@samp{+=} and @@samp{++} -are supported as well. - -To store into arbitrary places in memory, use the @@samp{@@{@@dots{}@@}} -construct to generate a value of specified type at a specified address -(@@pxref{Expressions}). For example, - -@@example -set @@{int@@}0x83040 = 4 -@@end example - -@@node Jumping, Signaling, Assignment, Altering -@@section Continuing at a Different Address - -@@table @@code -@@item jump @@var{linenum} -@@kindex jump -Resume execution at line number @@var{linenum}. Execution may stop -immediately if there is a breakpoint there. - -The @@samp{jump} command does not change the current stack frame, or -the stack pointer, or the contents of any memory location or any -register other than the program counter. If line @@var{linenum} is in -a different function from the one currently executing, the results may -be wild if the two functions expect different patterns of arguments or -of local variables. For this reason, the @@samp{jump} command requests -confirmation if the specified line is not in the function currently -executing. However, even wild results are predictable based on -changing the program counter. - -@@item jump *@@var{address} -Resume execution at the instruction at address @@var{address}. -@@end table - -A similar effect can be obtained by storing a new value into the register -@@samp{$pc}, but not exactly the same. - -@@example -set $pc = 0x485 -@@end example - -@@noindent -specifies the address at which execution will resume, but does not resume -execution. That does not happen until you use the @@samp{cont} command or a -stepping command (@@pxref{Stepping}). - -@@node Signaling, Returning, Jumping, Altering -@@section Giving the Program a Signal - -@@table @@code -@@item signal @@var{signalnum} -@@kindex signal -Resume execution where the program stopped, but give it immediately -the signal number @@var{signalnum}. - -Alternatively, if @@var{signalnum} is zero, continue execution and give -no signal. This is useful when the program has received a signal -but you don't want the program to see that signal; the @@samp{cont} command -would signal the program. -@@end table - -@@node Returning,, Signaling, Altering -@@section Returning from a Function - -@@cindex returning from a function -@@kindex return -You can make any function call return immediately, using the @@samp{return} -command. - -First select the stack frame that you wish to return from -(@@pxref{Selection}). Then type the @@samp{return} command. If you wish to -specify the value to be returned, give that as an argument. - -This pops the selected stack frame (and any other frames inside of it), -leaving its caller as the innermost remaining frame. That frame becomes -selected. The specified value is stored in the registers used for -returning values of functions. - -The @@samp{return} command does not resume execution; it leaves the program -stopped in the state that would exist if the function had just returned. -Contrast this with the @@samp{finish} command (@@pxref{Stepping}), which -resumes execution @@i{until} the selected stack frame returns naturally. - -@@node Sequences, Emacs, Altering, Top -@@chapter Canned Sequences of Commands - -GDB provides two ways to store sequences of commands for execution as a -unit: user-defined commands and command files. - -@@menu -* Define:: User-defined commands. -* Command Files:: Command files. -* Output:: Controlled output commands useful in - user-defined commands and command files. -@@end menu - -@@node Define, Command Files, Sequences, Sequences -@@section User-Defined Commands - -@@cindex user-defined commands -A @@dfn{user-defined command} is a sequence of GDB commands to which you -assign a new name as a command. This is done with the @@samp{define} -command. - -@@table @@code -@@item define @@var{commandname} -@@kindex define -Define a command named @@var{commandname}. If there is already a command -by that name, you are asked to confirm that you want to redefine it. - -The definition of the command is made up of other GDB command lines, -which are given following the @@samp{define} command. The end of these -commands is marked by a line containing @@samp{end}. - -@@item document @@var{commandname} -@@kindex document -Give documentation to the user-defined command @@var{commandname}. The -command @@var{commandname} must already be defined. This command reads -lines of documentation just as @@samp{define} reads the lines of the -command definition, ending with @@samp{end}. After the @@samp{document} command is finished, -@@samp{help} on command @@var{commandname} will print the documentation -you have specified. - -You may use the @@samp{document} command again to change the -documentation of a command. Redefining the command with @@samp{define} -does not change the documentation. -@@end table - -User-defined commands do not take arguments. When they are executed, the -commands of the definition are not printed. An error in any command -stops execution of the user-defined command. - -Commands that would ask for confirmation if used interactively proceed -without asking when used inside a user-defined command. Many GDB commands -that normally print messages to say what they are doing omit the messages -when used in user-defined command. - -@@node Command Files, Output, Define, Sequences -@@section Command Files - -@@cindex command files -A command file for GDB is a file of lines that are GDB commands. Comments -(lines starting with @@samp{#}) may also be included. An empty line in a -command file does nothing; it does not mean to repeat the last command, as -it would from the terminal. - -@@cindex init file -@@cindex .gdbinit -When GDB starts, it automatically executes its @@dfn{init files}, command -files named @@file{.gdbinit}. GDB reads the init file (if any) in your home -directory and then the init file (if any) in the current working -directory. (The init files are not executed if the @@samp{-nx} option -is given.) You can also request the execution of a command file with the -@@samp{source} command: - -@@table @@code -@@item source @@var{filename} -@@kindex source -Execute the command file @@var{filename}. -@@end table - -The lines in a command file are executed sequentially. They are not -printed as they are executed. An error in any command terminates execution -of the command file. - -Commands that would ask for confirmation if used interactively proceed -without asking when used in a command file. Many GDB commands that -normally print messages to say what they are doing omit the messages -when used in a command file. - -@@node Output,, Command Files, Sequences -@@section Commands for Controlled Output - -During the execution of a command file or a user-defined command, the only -output that appears is what is explicitly printed by the commands of the -definition. This section describes three commands useful for generating -exactly the output you want. - -@@table @@code -@@item echo @@var{text} -@@kindex echo -Print @@var{text}. Nonprinting characters can be included in -@@var{text} using C escape sequences, such as @@samp{\n} to print a -newline. @@b{No newline will be printed unless you specify one.} - -A backslash at the end of @@var{text} is ignored. It is useful for -outputting a string ending in spaces, since trailing spaces are -trimmed from all arguments. A backslash at the beginning preserves -leading spaces in the same way, because @@samp{\ } as an escape -sequence stands for a space. Thus, to print @@samp{ and foo = }, do - -@@example -echo \ and foo = \ -@@end example - -@@item output @@var{expression} -@@kindex output -Print the value of @@var{expression} and nothing but that value: no -newlines, no @@samp{$@@var{nn} = }. The value is not entered in the -value history either. @@xref{Expressions} for more information -on expressions. - -@@item output/@@var{fmt} @@var{expression} -Print the value of @@var{expression} in format @@var{fmt}. -@@xref{Formats}, for more information. - -@@item printf @@var{string}, @@var{expressions}@@dots{} -@@kindex printf -Print the values of the @@var{expressions} under the control of -@@var{string}. The @@var{expressions} are separated by commas and may -be either numbers or pointers. Their values are printed as specified -by @@var{string}, exactly as if the program were to execute - -@@example -printf (@@var{string}, @@var{expressions}@@dots{}); -@@end example - -For example, you can print two values in hex like this: - -@@example -printf "foo, bar-foo = 0x%x, 0x%x\n", foo, bar-foo -@@end example - -The only backslash-escape sequences that you can use in the string are -the simple ones that consist of backslash followed by a letter. -@@end table - -@@node Emacs, Remote, Sequences, Top -@@chapter Using GDB under GNU Emacs - -A special interface allows you to use GNU Emacs to view (and -edit) the source files for the program you are debugging with -GDB. - -To use this interface, use the command @@kbd{M-x gdb} in Emacs. -Give the executable file you want to debug as an argument. This -command starts a GDB process as a subprocess of Emacs, with input -and output through a newly created Emacs buffer. - -Using this GDB process is just like using GDB normally except for two things: - -@@itemize @@bullet -@@item -All ``terminal'' input and output goes through the Emacs buffer. This -applies both to GDB commands and their output, and to the input and -output done by the program you are debugging. - -This is useful because it means that you can copy the text of previous -commands and input them again; you can even use parts of the output -in this way. - -All the facilities of Emacs's Shell mode are available for this purpose. - -@@item -GDB displays source code through Emacs. Each time GDB displays a -stack frame, Emacs automatically finds the source file for that frame -and puts an arrow (@@samp{=>}) at the left margin of the current line. - -Explicit GDB @@samp{list} or search commands still produce output as -usual, but you probably will have no reason to use them. -@@end itemize - -In the GDB I/O buffer, you can use these special Emacs commands: - -@@table @@kbd -@@item M-s -Execute to another source line, like the GDB @@samp{step} command. - -@@item M-n -Execute to next source line in this function, skipping all function -calls, like the GDB @@samp{next} command. - -@@item M-i -Execute one instruction, like the GDB @@samp{stepi} command. - -@@item M-u -Move up one stack frame (and display that frame's source file in -Emacs), like the GDB @@samp{up} command. - -@@item M-d -Move down one stack frame (and display that frame's source file in -Emacs), like the GDB @@samp{down} command. (This means that you cannot -delete words in the usual fashion in the GDB buffer; I am guessing you -won't often want to do that.) - -@@item C-c C-f -Execute until exit from the selected stack frame, like the GDB -@@samp{finish} command. -@@end table - -In any source file, the Emacs command @@kbd{C-x SPC} (@@code{gdb-break}) -tells GDB to set a breakpoint on the source line point is on. - -The source files displayed in Emacs are in ordinary Emacs buffers -which are visiting the source files in the usual way. You can edit -the files with these buffers if you wish; but keep in mind that GDB -communicates with Emacs in terms of line numbers. If you add or -delete lines from the text, the line numbers that GDB knows will cease -to correspond properly to the code. - -@@node Remote, Commands, Emacs, Top -@@chapter Remote Kernel Debugging - -GDB has a special facility for debugging a remote machine via a serial -connection. This can be used for kernel debugging. - -The program to be debugged on the remote machine needs to contain a -debugging device driver which talks to GDB over the serial line using the -protocol described below. The same version of GDB that is used ordinarily -can be used for this. - -@@menu -* Remote Commands:: Commands used to start and finish remote debugging. -@@end menu - -For details of the communication protocol, see the comments in the GDB -source file @@file{remote.c}. - -@@node Remote Commands,, Remote, Remote -@@section Commands for Remote Debugging - -To start remote debugging, first run GDB and specify as an executable file -the program that is running in the remote machine. This tells GDB how -to find the program's symbols and the contents of its pure text. Then -establish communication using the @@samp{attach} command with a device -name rather than a pid as an argument. For example: - -@@example -attach /dev/ttyd -@@end example - -@@noindent -if the serial line is connected to the device named @@file{/dev/ttyd}. This -will stop the remote machine if it is not already stopped. - -Now you can use all the usual commands to examine and change data and to -step and continue the remote program. - -To resume the remote program and stop debugging it, use the @@samp{detach} -command. - -@@node Commands, Concepts, Remote, Top -@@unnumbered Command Index - -@@printindex ky - -@@node Concepts,, Commands, Top -@@unnumbered Concept Index - -@@printindex cp - -@@contents -@@bye -@ - - -1.1 -log -@Initial revision -@ -text -@d617 3 -a619 2 -inferior. If you wish to evaluate a function simply for it's side -affects, you may use the @@samp{set} command. @@xref{Assignment}. -d1101 4 -a1104 3 -A condition is just a boolean expression in your programming language. -A breakpoint with a condition evaluates the expression each time the -program reaches it, and the program stops only if the condition is true. -d1126 1 -d1259 6 -a1264 5 -is a condition expression that will change @@code{x} as needed, then always -have the value 0 so the program will not stop. Loss of input is avoided -here because break conditions are evaluated without changing the terminal -modes. When you want to have nontrivial conditions for performing the side -effects, the operators @@samp{&&}, @@samp{||} and @@samp{?@@: @@dots{} :@@:} may be useful. -d1269 3 -a1271 3 -Under Unix, breakpoints cannot be used in a program if any other process -is running that program. Attempting to run or continue the program with -a breakpoint in this case will cause GDB to stop it. -d1875 2 -d2047 2 -a2048 1 -address of a byte of memory. -d2196 1 -a2196 1 -each time the program stops. -d2382 1 -a2382 1 -saved in ``extended'' format, but all C programs expect to work with -d2451 1 -d2544 1 -a2544 1 -For example, -d2628 3 -a2630 3 -no signal. This may be useful when the program has received a signal -and the @@samp{cont} command would allow the program to see that -signal. -d2691 1 -a2691 1 -command definition. After the @@samp{document} command is finished, -d2771 2 -a2772 1 -value history either. -@ diff --git a/gdb/RCS/gdbcore.h,v b/gdb/RCS/gdbcore.h,v deleted file mode 100644 index 872e5af92a..0000000000 --- a/gdb/RCS/gdbcore.h,v +++ /dev/null @@ -1,105 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.02.09.23.23.12; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.09.22.43.14; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Create gdbcore.h with external variables that relate to core files. -@ -text -@/* Machine independent variables that describe the core file under GDB. - Copyright (C) 1986, 1987, 1989 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! -*/ - -/* 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; -@ - - -1.1 -log -@Initial revision -@ -text -@d1 68 -@ diff --git a/gdb/RCS/inflow.c,v b/gdb/RCS/inflow.c,v deleted file mode 100644 index 972b6150d3..0000000000 --- a/gdb/RCS/inflow.c,v +++ /dev/null @@ -1,636 +0,0 @@ -head 1.3; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.3 -date 89.03.27.20.12.35; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.02.09.23.23.40; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.09.22.28.04; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.3 -log -@General portability changes. Make various local terminal control -parameter processing #ifdef the particular IOCTL used to get them. -This handles various Sys V/Berkeley merges. Also avoid vfork -and . -@ -text -@/* Low level interface to ptrace, for GDB when running under Unix. - Copyright (C) 1986, 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! -*/ -#include "defs.h" -#include "param.h" -#include "frame.h" -#include "inferior.h" - -#ifdef USG -#include -#include -#endif - -#include -#include -#include -#include - -#ifdef HAVE_TERMIO -#include -#undef TIOCGETP -#define TIOCGETP TCGETA -#undef TIOCSETN -#define TIOCSETN TCSETA -#undef TIOCSETP -#define TIOCSETP TCSETAF -#define TERMINAL struct termio -#else -#include -#include -#include -#define TERMINAL struct sgttyb -#endif - -#ifdef SET_STACK_LIMIT_HUGE -#include -#include -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; - -#ifdef TIOCGETC -static struct tchars tc_inferior; -static struct tchars tc_ours; -#endif - -#ifdef TIOCGLTC -static struct ltchars ltc_inferior; -static struct ltchars ltc_ours; -#endif /* TIOCGLTC */ - -#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; - -#ifdef TIOCGETC - 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); -#ifdef TIOCGETC - 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. */ - int (*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); - -#ifdef TIOCGETC - 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); - -#ifdef TIOCGETC - 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 ("No terminal status when remote debugging.\n"); - return; - } - - printf ("Inferior's terminal status (currently saved by GDB):\n"); - -#ifdef HAVE_TERMIO - - printf ("fcntl flags = 0x%x, c_iflag = 0x%x, c_oflag = 0x%x,\n", - tflags_inferior, sg_inferior.c_iflag, sg_inferior.c_oflag); - printf ("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 ("c_cc: "); - for (i = 0; (i < NCC); i += 1) - printf ("0x%x ", sg_inferior.c_cc[i]); - printf ("\n"); - -#else /* not HAVE_TERMIO */ - - printf ("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 */ - -#ifdef TIOCGETC - printf ("tchars: "); - for (i = 0; i < sizeof (struct tchars); i++) - printf ("0x%x ", ((char *)&tc_inferior)[i]); - printf ("\n"); -#endif - -#ifdef TIOCGLTC - printf ("ltchars: "); - for (i = 0; i < sizeof (struct ltchars); i++) - printf ("0x%x ", ((char *)<c_inferior)[i]); - printf ("\n"); - ioctl (0, TIOCSLTC, <c_ours); -#endif - -#ifdef TIOCLGET - printf ("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); - - dup2(tty, 0); - dup2(tty, 1); - dup2(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 (); - - pid = fork (); - if (pid < 0) - perror_with_name ("fork"); - - 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); - -/* 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); - } - return pid; -} - -/* Kill the inferior process. Make us have no inferior. */ - -static void -kill_command () -{ - if (remote_debugging) - 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 ())); -} - -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."); - - for (i = 0; ; 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); - } -} - -void -_initialize_inflow () -{ - add_com ("term-status", class_obscure, term_status_command, - "Print info on inferior's saved terminal status."); - - 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."); - - add_com ("kill", class_run, kill_command, - "Kill execution of program being debugged."); - - inferior_pid = 0; - - ioctl (0, TIOCGETP, &sg_ours); - fcntl (0, F_GETFL, tflags_ours); - -#ifdef TIOCGETC - 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; -} - -@ - - -1.2 -log -@When the inferior process dies, deselect the current frame so that -the "where" ("backtrace") command will not think there's a stack. -@ -text -@d27 1 -a27 1 -#include -a34 6 -/* May be unnecessary since many parts of inflow.c - have migrated to *-infdep.c */ -#ifdef USG -#include -#endif - -d73 1 -a73 1 -#ifdef TIOCGLTC -d76 3 -d81 3 -d86 1 -a86 1 -#endif /* TIOCGLTC */ -d117 4 -a121 1 - tc_inferior = tc_ours; -d123 3 -d127 1 -a127 1 -#endif /* TIOCGLTC */ -d150 3 -a153 1 - ioctl (0, TIOCSETC, &tc_inferior); -d155 2 -d158 1 -a158 1 -#endif /* TIOCGLTC */ -d228 3 -a231 1 - ioctl (0, TIOCGETC, &tc_inferior); -d233 2 -d236 1 -a236 1 -#endif /* TIOCGLTC */ -d253 3 -a256 1 - ioctl (0, TIOCSETC, &tc_ours); -d258 2 -d261 1 -a261 1 -#endif /* TIOCGLTC */ -d297 6 -a302 3 - printf ("fcntl flags = 0x%x, lmode = 0x%x,\nsgttyb.sg_flags = 0x%x, owner pid = %d.\n", - tflags_inferior, lmode_inferior, - sg_inferior.sg_flags, pgrp_inferior); -d307 3 -d314 2 -d317 3 -a319 1 -#endif /* not HAVE_TERMIO */ -d383 1 -a383 1 - pid = vfork (); -d385 1 -a385 1 - perror_with_name ("vfork"); -d497 3 -a500 1 - ioctl (0, TIOCGETC, &tc_ours); -d502 2 -d505 1 -a505 1 -#endif /* TIOCGLTC */ -@ - - -1.1 -log -@Initial revision -@ -text -@d418 1 -@ diff --git a/gdb/RCS/infrun.c,v b/gdb/RCS/infrun.c,v deleted file mode 100644 index 983922f5c9..0000000000 --- a/gdb/RCS/infrun.c,v +++ /dev/null @@ -1,1855 +0,0 @@ -head 1.3; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.3 -date 89.03.27.20.15.05; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.02.09.23.25.40; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.09.17.11.52; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.3 -log -@A/UX-specific change: define X_OK since Apple fucked it up. -@ -text -@/* Start and stop the inferior process, for GDB. - Copyright (C) 1986, 1987, 1988 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! -*/ - -/* Notes on the algorithm used in wait_for_inferior to determine if we - just did a subroutine call when stepping. We have the following - information at that point: - - Current and previous (just before this step) pc. - Current and previous sp. - Current and previous start of current function. - - If the start's of the functions don't match, then - - a) We did a subroutine call. - - In this case, the pc will be at the beginning of a function. - - b) We did a subroutine return. - - Otherwise. - - c) We did a longjmp. - - If we did a longjump, we were doing "nexti", since a next would - have attempted to skip over the assembly language routine in which - the longjmp is coded and would have simply been the equivalent of a - continue. I consider this ok behaivior. We'd like one of two - things to happen if we are doing a nexti through the longjmp() - routine: 1) It behaves as a stepi, or 2) It acts like a continue as - above. Given that this is a special case, and that anybody who - thinks that the concept of sub calls is meaningful in the context - of a longjmp, I'll take either one. Let's see what happens. - - Acts like a subroutine return. I can handle that with no problem - at all. - - -->So: If the current and previous beginnings of the current - function don't match, *and* the pc is at the start of a function, - we've done a subroutine call. If the pc is not at the start of a - function, we *didn't* do a subroutine call. - - -->If the beginnings of the current and previous function do match, - either: - - a) We just did a recursive call. - - In this case, we would be at the very beginning of a - function and 1) it will have a prologue (don't jump to - before prologue, or 2) (we assume here that it doesn't have - a prologue) there will have been a change in the stack - pointer over the last instruction. (Ie. it's got to put - the saved pc somewhere. The stack is the usual place. In - a recursive call a register is only an option if there's a - prologue to do something with it. This is even true on - register window machines; the prologue sets up the new - window. It might not be true on a register window machine - where the call instruction moved the register window - itself. Hmmm. One would hope that the stack pointer would - also change. If it doesn't, somebody send me a note, and - I'll work out a more general theory. - randy@@wheaties.ai.mit.edu). This is true (albeit slipperly - so) on all machines I'm aware of: - - m68k: Call changes stack pointer. Regular jumps don't. - - sparc: Recursive calls must have frames and therefor, - prologues. - - vax: All calls have frames and hence change the - stack pointer. - - b) We did a return from a recursive call. I don't see that we - have either the ability or the need to distinguish this - from an ordinary jump. The stack frame will be printed - when and if the frame pointer changes; if we are in a - function without a frame pointer, it's the users own - lookout. - - c) We did a jump within a function. We assume that this is - true if we didn't do a recursive call. - - d) We are in no-man's land ("I see no symbols here"). We - don't worry about this; it will make calls look like simple - jumps (and the stack frames will be printed when the frame - pointer moves), which is a reasonably non-violent response. - -#if 0 - We skip this; it causes more problems than it's worth. -#ifdef SUN4_COMPILER_FEATURE - We do a special ifdef for the sun 4, forcing it to single step - into calls which don't have prologues. This means that we can't - nexti over leaf nodes, we can probably next over them (since they - won't have debugging symbols, usually), and we can next out of - functions returning structures (with a "call .stret4" at the end). -#endif -#endif -*/ - - - - - -#include "defs.h" -#include "param.h" -#include "symtab.h" -#include "frame.h" -#include "inferior.h" -#include "wait.h" - -#include -#include - -/* unistd.h is needed to #define X_OK */ -#ifdef USG -#include -#else -#include -#endif - -/* The idiots at Apple only define X_OK if POSIX is defined. Fuck 'em. */ -#ifndef X_OK -#define X_OK 1 /* Execute permission for access() */ -#endif - -#ifdef UMAX_PTRACE -#include -#include -#endif /* UMAX_PTRACE */ - -extern char *sys_siglist[]; -extern int errno; - -/* Tables of how to react to signals; the user sets them. */ - -static char signal_stop[NSIG]; -static char signal_print[NSIG]; -static char signal_program[NSIG]; - -/* Nonzero if breakpoints are now inserted in the inferior. */ - -static int breakpoints_inserted; - -/* Function inferior was in as of last step command. */ - -static struct symbol *step_start_function; - -/* This is the sequence of bytes we insert for a breakpoint. */ - -static char break_insn[] = BREAKPOINT; - -/* Nonzero => address for special breakpoint for resuming stepping. */ - -static CORE_ADDR step_resume_break_address; - -/* Original contents of the byte where the special breakpoint is. */ - -static char step_resume_break_shadow[sizeof break_insn]; - -/* Nonzero means the special breakpoint is a duplicate - so it has not itself been inserted. */ - -static int step_resume_break_duplicate; - -/* Nonzero if we are expecting a trace trap and should proceed from it. - 2 means expecting 2 trace traps and should continue both times. - That occurs when we tell sh to exec the program: we will get - a trap after the exec of sh and a second when the program is exec'd. */ - -static int trap_expected; - -/* Nonzero if the next time we try to continue the inferior, it will - step one instruction and generate a spurious trace trap. - This is used to compensate for a bug in HP-UX. */ - -static int trap_expected_after_continue; - -/* Nonzero means expecting a trace trap - and should stop the inferior and return silently when it happens. */ - -int stop_after_trap; - -/* Nonzero means expecting a trace trap due to attaching to a process. */ - -int stop_after_attach; - -/* Nonzero if pc has been changed by the debugger - since the inferior stopped. */ - -int pc_changed; - -/* Nonzero if debugging a remote machine via a serial link or ethernet. */ - -int remote_debugging; - -/* Save register contents here when about to pop a stack dummy frame. */ - -char stop_registers[REGISTER_BYTES]; - -/* Nonzero if program stopped due to error trying to insert breakpoints. */ - -static int breakpoints_failed; - -/* Nonzero if inferior is in sh before our program got exec'd. */ - -static int running_in_shell; - -/* Nonzero after stop if current stack frame should be printed. */ - -static int stop_print_frame; - -#ifdef NO_SINGLE_STEP -extern int one_stepped; /* From machine dependent code */ -extern void single_step (); /* Same. */ -#endif /* NO_SINGLE_STEP */ - -static void insert_step_breakpoint (); -static void remove_step_breakpoint (); -static void wait_for_inferior (); -static void normal_stop (); - - -/* Clear out all variables saying what to do when inferior is continued. - First do this, then set the ones you want, then call `proceed'. */ - -void -clear_proceed_status () -{ - trap_expected = 0; - step_range_start = 0; - step_range_end = 0; - step_frame_address = 0; - step_over_calls = -1; - step_resume_break_address = 0; - stop_after_trap = 0; - stop_after_attach = 0; - - /* Discard any remaining commands left by breakpoint we had stopped at. */ - clear_breakpoint_commands (); -} - -/* Basic routine for continuing the program in various fashions. - - ADDR is the address to resume at, or -1 for resume where stopped. - SIGNAL is the signal to give it, or 0 for none, - or -1 for act according to how it stopped. - STEP is nonzero if should trap after one instruction. - -1 means return after that and print nothing. - You should probably set various step_... variables - before calling here, if you are stepping. - - You should call clear_proceed_status before calling proceed. */ - -void -proceed (addr, signal, step) - CORE_ADDR addr; - int signal; - int step; -{ - int oneproc = 0; - - if (step > 0) - step_start_function = find_pc_function (read_pc ()); - if (step < 0) - stop_after_trap = 1; - - if (addr == -1) - { - /* If there is a breakpoint at the address we will resume at, - step one instruction before inserting breakpoints - so that we do not stop right away. */ - - if (!pc_changed && breakpoint_here_p (read_pc ())) - oneproc = 1; - } - else - { - write_register (PC_REGNUM, addr); -#ifdef NPC_REGNUM - write_register (NPC_REGNUM, addr + 4); -#endif - } - - if (trap_expected_after_continue) - { - /* If (step == 0), a trap will be automatically generated after - the first instruction is executed. Force step one - instruction to clear this condition. This should not occur - if step is nonzero, but it is harmless in that case. */ - oneproc = 1; - trap_expected_after_continue = 0; - } - - if (oneproc) - /* We will get a trace trap after one instruction. - Continue it automatically and insert breakpoints then. */ - trap_expected = 1; - else - { - int temp = insert_breakpoints (); - if (temp) - { - print_sys_errmsg ("ptrace", temp); - error ("Cannot insert breakpoints.\n\ -The same program may be running in another process."); - } - breakpoints_inserted = 1; - } - - /* Install inferior's terminal modes. */ - terminal_inferior (); - - if (signal >= 0) - stop_signal = signal; - /* If this signal should not be seen by program, - give it zero. Used for debugging signals. */ - else if (stop_signal < NSIG && !signal_program[stop_signal]) - stop_signal= 0; - - /* Resume inferior. */ - resume (oneproc || step, stop_signal); - - /* Wait for it to stop (if not standalone) - and in any case decode why it stopped, and act accordingly. */ - - wait_for_inferior (); - normal_stop (); -} - -/* Writing the inferior pc as a register calls this function - to inform infrun that the pc has been set in the debugger. */ - -void -writing_pc (val) - CORE_ADDR val; -{ - stop_pc = val; - pc_changed = 1; -} - -/* Start an inferior process for the first time. - Actually it was started by the fork that created it, - but it will have stopped one instruction after execing sh. - Here we must get it up to actual execution of the real program. */ - -void -start_inferior () -{ - /* We will get a trace trap after one instruction. - Continue it automatically. Eventually (after shell does an exec) - it will get another trace trap. Then insert breakpoints and continue. */ - -#ifdef START_INFERIOR_TRAPS_EXPECTED - trap_expected = START_INFERIOR_TRAPS_EXPECTED; -#else - trap_expected = 2; -#endif - - running_in_shell = 0; /* Set to 1 at first SIGTRAP, 0 at second. */ - trap_expected_after_continue = 0; - breakpoints_inserted = 0; - mark_breakpoints_out (); - - /* Set up the "saved terminal modes" of the inferior - based on what modes we are starting it with. */ - terminal_init_inferior (); - - /* Install inferior's terminal modes. */ - terminal_inferior (); - - if (remote_debugging) - { - trap_expected = 0; - fetch_inferior_registers(); - set_current_frame (create_new_frame (read_register (FP_REGNUM), - read_pc ())); - stop_frame_address = FRAME_FP (get_current_frame()); - inferior_pid = 3; - if (insert_breakpoints()) - fatal("Can't insert breakpoints"); - breakpoints_inserted = 1; - proceed(-1, -1, 0); - } - else - { - wait_for_inferior (); - normal_stop (); - } -} - -/* Start remote-debugging of a machine over a serial link. */ - -void -start_remote () -{ - clear_proceed_status (); - running_in_shell = 0; - trap_expected = 0; - inferior_pid = 3; - breakpoints_inserted = 0; - mark_breakpoints_out (); - wait_for_inferior (); - normal_stop(); -} - -#ifdef ATTACH_DETACH - -/* Attach to process PID, then initialize for debugging it - and wait for the trace-trap that results from attaching. */ - -void -attach_program (pid) - int pid; -{ - attach (pid); - inferior_pid = pid; - - mark_breakpoints_out (); - terminal_init_inferior (); - clear_proceed_status (); - stop_after_attach = 1; - /*proceed (-1, 0, -2);*/ - wait_for_inferior (); - normal_stop (); -} -#endif /* ATTACH_DETACH */ - -/* Wait for control to return from inferior to debugger. - If inferior gets a signal, we may decide to start it up again - instead of returning. That is why there is a loop in this function. - When this function actually returns it means the inferior - should be left stopped and GDB should read more commands. */ - -static void -wait_for_inferior () -{ - register int pid; - WAITTYPE w; - CORE_ADDR pc; - int tem; - int another_trap; - int random_signal; - CORE_ADDR stop_sp, prev_sp; - CORE_ADDR prev_func_start, stop_func_start; - CORE_ADDR prologue_pc; - int stop_step_resume_break; - CORE_ADDR step_resume_break_sp; - int newmisc; - int newfun_pc; - struct symbol *newfun; - struct symtab_and_line sal; - int prev_pc; - extern CORE_ADDR text_end; - - prev_pc = read_pc (); - prev_func_start = get_pc_function_start (prev_pc) + FUNCTION_START_OFFSET; - prev_sp = read_register (SP_REGNUM); - - while (1) - { - /* Clean up saved state that will become invalid */ - pc_changed = 0; - flush_cached_frames (); - - if (remote_debugging) - remote_wait (&w); - else - { - pid = wait (&w); - if (pid != inferior_pid) - continue; - } - - /* See if the process still exists; clean up if it doesn't. */ - if (WIFEXITED (w)) - { - terminal_ours_for_output (); - if (WRETCODE (w)) - printf ("\nProgram exited with code 0%o.\n", WRETCODE (w)); - else - printf ("\nProgram exited normally.\n"); - fflush (stdout); - inferior_died (); -#ifdef NO_SINGLE_STEP - one_stepped = 0; /* Clear single_step state since proc gone */ -#endif /* NO_SINGLE_STEP */ - stop_print_frame = 0; - break; - } - else if (!WIFSTOPPED (w)) - { - kill_inferior (); - stop_print_frame = 0; - stop_signal = WTERMSIG (w); - terminal_ours_for_output (); - printf ("\nProgram terminated with signal %d, %s\n", - stop_signal, - stop_signal < NSIG - ? sys_siglist[stop_signal] - : "(undocumented)"); - printf ("The inferior process no longer exists.\n"); - fflush (stdout); -#ifdef NO_SINGLE_STEP - one_stepped = 0; /* Clear single_step state since proc gone */ -#endif /* NO_SINGLE_STEP */ - break; - } - -#ifdef NO_SINGLE_STEP - if (one_stepped) - single_step (0); /* This actually cleans up the ss */ -#endif /* NO_SINGLE_STEP */ - - fetch_inferior_registers (); - stop_pc = read_pc (); - set_current_frame ( create_new_frame (read_register (FP_REGNUM), - read_pc ())); -#ifdef CONVEX_PTRACE - /* pop frame stored by user-mode trap, if present */ - if (stop_pc == BREAK_TRAP_ADDR) - { - POP_FRAME; - stop_pc = read_pc () - 2; - write_register (PC_REGNUM, stop_pc); -#ifdef NPC_REGNUM - write_register (NPC_REGNUM, stop_pc + 4); -#endif - pc_changed = 0; - } - else if (stop_pc > STACK_END_ADDR) - { - POP_FRAME; - stop_pc = read_pc (); - } -#endif /* CONVEX_PTRACE */ - stop_frame_address = FRAME_FP (get_current_frame ()); - stop_sp = read_register (SP_REGNUM); - stop_func_start = - get_pc_function_start (stop_pc) + FUNCTION_START_OFFSET; - another_trap = 0; - stop_breakpoint = 0; - stop_step = 0; - stop_stack_dummy = 0; - stop_print_frame = 1; - stop_step_resume_break = 0; - random_signal = 0; - stopped_by_random_signal = 0; - breakpoints_failed = 0; - - /* Look at the cause of the stop, and decide what to do. - The alternatives are: - 1) break; to really stop and return to the debugger, - 2) drop through to start up again - (set another_trap to 1 to single step once) - 3) set random_signal to 1, and the decision between 1 and 2 - will be made according to the signal handling tables. */ - - stop_signal = WSTOPSIG (w); - - /* First, distinguish signals caused by the debugger from signals - that have to do with the program's own actions. - Note that breakpoint insns may cause SIGTRAP or SIGILL - or SIGEMT, depending on the operating system version. - Here we detect when a SIGILL or SIGEMT is really a breakpoint - and change it to SIGTRAP. */ - - if (stop_signal == SIGTRAP -#ifndef CONVEX_PTRACE - || (breakpoints_inserted && - (stop_signal == SIGILL - || stop_signal == SIGEMT)) -#endif /* not CONVEX_PTRACE */ - || stop_after_attach) - { - if (stop_signal == SIGTRAP && stop_after_trap) - { - stop_print_frame = 0; - break; - } - if (stop_after_attach) - break; - /* Don't even think about breakpoints - if still running the shell that will exec the program - or if just proceeded over a breakpoint. */ - if (stop_signal == SIGTRAP && trap_expected) - stop_breakpoint = 0; - else - { - /* See if there is a breakpoint at the current PC. */ -#if DECR_PC_AFTER_BREAK - /* Notice the case of stepping through a jump - that leads just after a breakpoint. - Don't confuse that with hitting the breakpoint. - What we check for is that 1) stepping is going on - and 2) the pc before the last insn does not match - the address of the breakpoint before the current pc. */ - if (!(prev_pc != stop_pc - DECR_PC_AFTER_BREAK - && step_range_end && !step_resume_break_address)) -#endif /* DECR_PC_AFTER_BREAK not zero */ - { - /* For condition exprs. */ - select_frame (get_current_frame (), 0); - stop_breakpoint = - breakpoint_stop_status (stop_pc, stop_frame_address); - /* Following in case break condition called a - function. */ - stop_print_frame = 1; - if (stop_breakpoint && DECR_PC_AFTER_BREAK) - { - stop_pc -= DECR_PC_AFTER_BREAK; - write_register (PC_REGNUM, stop_pc); -#ifdef NPC_REGNUM - write_register (NPC_REGNUM, stop_pc + 4); -#endif - pc_changed = 0; - } - } - /* See if we stopped at the special breakpoint for - stepping over a subroutine call. */ - if (stop_pc - DECR_PC_AFTER_BREAK - == step_resume_break_address) - { - stop_step_resume_break = 1; - if (DECR_PC_AFTER_BREAK) - { - stop_pc -= DECR_PC_AFTER_BREAK; - write_register (PC_REGNUM, stop_pc); - pc_changed = 0; - } - } - } - - if (stop_signal == SIGTRAP) - random_signal - = !(stop_breakpoint || trap_expected - || stop_step_resume_break -#ifndef CONVEX_PTRACE - || (stop_sp INNER_THAN stop_pc - && stop_pc INNER_THAN stop_frame_address) -#else - || stop_pc == text_end - 2 -#endif - || (step_range_end && !step_resume_break_address)); - else - { - random_signal - = !(stop_breakpoint - || stop_step_resume_break -#ifdef news800 - || (stop_sp INNER_THAN stop_pc - && stop_pc INNER_THAN stop_frame_address) -#endif - - ); - if (!random_signal) - stop_signal = SIGTRAP; - } - } - else - random_signal = 1; - - /* For the program's own signals, act according to - the signal handling tables. */ - - if (random_signal - && !(running_in_shell && stop_signal == SIGSEGV)) - { - /* Signal not for debugging purposes. */ - int printed = 0; - - stopped_by_random_signal = 1; - - if (stop_signal >= NSIG - || signal_print[stop_signal]) - { - printed = 1; - terminal_ours_for_output (); - printf ("\nProgram received signal %d, %s\n", - stop_signal, - stop_signal < NSIG - ? sys_siglist[stop_signal] - : "(undocumented)"); - fflush (stdout); - } - if (stop_signal >= NSIG - || signal_stop[stop_signal]) - break; - /* If not going to stop, give terminal back - if we took it away. */ - else if (printed) - terminal_inferior (); - } - - /* Handle cases caused by hitting a breakpoint. */ - - if (!random_signal - && (stop_breakpoint || stop_step_resume_break)) - { - /* Does a breakpoint want us to stop? */ - if (stop_breakpoint && stop_breakpoint != -1 - && stop_breakpoint != -0x1000001) - { - /* 0x1000000 is set in stop_breakpoint as returned by - breakpoint_stop_status to indicate a silent - breakpoint. */ - if ((stop_breakpoint > 0 ? stop_breakpoint : - -stop_breakpoint) - & 0x1000000) - { - stop_print_frame = 0; - if (stop_breakpoint > 0) - stop_breakpoint -= 0x1000000; - else - stop_breakpoint += 0x1000000; - } - break; - } - /* But if we have hit the step-resumption breakpoint, - remove it. It has done its job getting us here. - The sp test is to make sure that we don't get hung - up in recursive calls in functions without frame - pointers. If the stack pointer isn't outside of - where the breakpoint was set (within a routine to be - stepped over), we're in the middle of a recursive - call. Not true for reg window machines (sparc) - because the must change frames to call things and - the stack pointer doesn't have to change if it - the bp was set in a routine without a frame (pc can - be stored in some other window). - - The removal of the sp test is to allow calls to - alloca. Nasty things were happening. Oh, well, - gdb can only handle one level deep of lack of - frame pointer. */ - if (stop_step_resume_break - && (step_frame_address == 0 - || (stop_frame_address == step_frame_address -#if 0 -#ifndef HAVE_REGISTER_WINDOWS - && step_resume_break_sp INNER_THAN stop_sp -#endif -#endif - ))) - { - remove_step_breakpoint (); - step_resume_break_address = 0; - } - /* Otherwise, must remove breakpoints and single-step - to get us past the one we hit. */ - else - { - remove_breakpoints (); - remove_step_breakpoint (); - breakpoints_inserted = 0; - another_trap = 1; - } - - /* We come here if we hit a breakpoint but should not - stop for it. Possibly we also were stepping - and should stop for that. So fall through and - test for stepping. But, if not stepping, - do not stop. */ - } - - /* If this is the breakpoint at the end of a stack dummy, - just stop silently. */ -#ifndef CONVEX_PTRACE - if (stop_sp INNER_THAN stop_pc - && stop_pc INNER_THAN stop_frame_address) -#else - /* "stack" dummy must be in text segment for Convex Unix */ - if (stop_pc == text_end - 2) -#endif - { - stop_print_frame = 0; - stop_stack_dummy = 1; -#ifdef HP9K320 - trap_expected_after_continue = 1; -#endif - break; - } - - if (step_resume_break_address) - /* Having a step-resume breakpoint overrides anything - else having to do with stepping commands until - that breakpoint is reached. */ - ; - /* If stepping through a line, keep going if still within it. */ - else if (!random_signal - && step_range_end - && stop_pc >= step_range_start - && stop_pc < step_range_end - /* The step range might include the start of the - function, so if we are at the start of the - step range and either the stack or frame pointers - just changed, we've stepped outside */ - && !(stop_pc == step_range_start - && stop_frame_address - && (stop_sp != prev_sp - || stop_frame_address != step_frame_address))) - { - /* Don't step through the return from a function - unless that is the first instruction stepped through. */ - if (ABOUT_TO_RETURN (stop_pc)) - { - stop_step = 1; - break; - } - } - - /* We stepped out of the stepping range. See if that was due - to a subroutine call that we should proceed to the end of. */ - else if (!random_signal && step_range_end) - { - if (stop_func_start) - { - prologue_pc = stop_func_start; - SKIP_PROLOGUE (prologue_pc); - } - - /* ==> See comments at top of file on this algorithm. <==*/ - - if (stop_pc == stop_func_start - && (stop_func_start != prev_func_start - || prologue_pc != stop_func_start - || stop_sp != prev_sp)) - { - newfun = find_pc_function (stop_pc); - /* It's a subroutine call */ - if (step_over_calls > 0 || (step_over_calls && newfun == 0)) - { - /* A subroutine call has happened. */ - /* Set a special breakpoint after the return */ - step_resume_break_address = - SAVED_PC_AFTER_CALL (get_current_frame ()); - step_resume_break_duplicate - = breakpoint_here_p (step_resume_break_address); - step_resume_break_sp = stop_sp; - if (breakpoints_inserted) - insert_step_breakpoint (); - } - /* Subroutine call with source code we should not step over. - Do step to the first line of code in it. */ - else if (step_over_calls) - { - SKIP_PROLOGUE (stop_func_start); - sal = find_pc_line (stop_func_start, 0); - /* Use the step_resume_break to step until - the end of the prologue, even if that involves jumps - (as it seems to on the vax under 4.2). */ - /* If the prologue ends in the middle of a source line, - continue to the end of that source line. - Otherwise, just go to end of prologue. */ -#ifdef convex - /* no, don't either. It skips any code that's - legitimately on the first line. */ -#else - if (sal.end && sal.pc != stop_func_start) - stop_func_start = sal.end; -#endif - - if (stop_func_start == stop_pc) - { - /* We are already there: stop now. */ - stop_step = 1; - break; - } - else - /* Put the step-breakpoint there and go until there. */ - { - step_resume_break_address = stop_func_start; - step_resume_break_sp = stop_sp; - - step_resume_break_duplicate - = breakpoint_here_p (step_resume_break_address); - if (breakpoints_inserted) - insert_step_breakpoint (); - /* Do not specify what the fp should be when we stop - since on some machines the prologue - is where the new fp value is established. */ - step_frame_address = 0; - /* And make sure stepping stops right away then. */ - step_range_end = step_range_start; - } - } - else - { - /* We get here only if step_over_calls is 0 and we - just stepped into a subroutine. I presume - that step_over_calls is only 0 when we're - supposed to be stepping at the assembly - language level.*/ - stop_step = 1; - break; - } - } - /* No subroutince call; stop now. */ - else - { - stop_step = 1; - break; - } - } - - /* Save the pc before execution, to compare with pc after stop. */ - prev_pc = read_pc (); /* Might have been DECR_AFTER_BREAK */ - prev_func_start = stop_func_start; /* Ok, since if DECR_PC_AFTER - BREAK is defined, the - original pc would not have - been at the start of a - function. */ - prev_sp = stop_sp; - - /* If we did not do break;, it means we should keep - running the inferior and not return to debugger. */ - - /* If trap_expected is 2, it means continue once more - and insert breakpoints at the next trap. - If trap_expected is 1 and the signal was SIGSEGV, it means - the shell is doing some memory allocation--just resume it - with SIGSEGV. - Otherwise insert breakpoints now, and possibly single step. */ - - if (trap_expected > 1) - { - trap_expected--; - running_in_shell = 1; - resume (0, 0); - } - else if (running_in_shell && stop_signal == SIGSEGV) - { - resume (0, SIGSEGV); - } - else - { - /* Here, we are not awaiting another exec to get - the program we really want to debug. - Insert breakpoints now, unless we are trying - to one-proceed past a breakpoint. */ - running_in_shell = 0; - if (!breakpoints_inserted && !another_trap) - { - insert_step_breakpoint (); - breakpoints_failed = insert_breakpoints (); - if (breakpoints_failed) - break; - breakpoints_inserted = 1; - } - - trap_expected = another_trap; - - if (stop_signal == SIGTRAP) - stop_signal = 0; - - resume ((step_range_end && !step_resume_break_address) - || trap_expected, - stop_signal); - } - } -} - -/* Here to return control to GDB when the inferior stops for real. - Print appropriate messages, remove breakpoints, give terminal our modes. - - RUNNING_IN_SHELL nonzero means the shell got a signal before - exec'ing the program we wanted to run. - STOP_PRINT_FRAME nonzero means print the executing frame - (pc, function, args, file, line number and line text). - BREAKPOINTS_FAILED nonzero means stop was due to error - attempting to insert breakpoints. */ - -/* FIXME, normal_stop is ALWAYS called immediately after wait_for_inferior. - They should probably be merged into a single function, since that - would avoid numerous tests (e.g. of inferior_pid). */ - -static void -normal_stop () -{ - /* Make sure that the current_frame's pc is correct. This - is a correction for setting up the frame info before doing - DECR_PC_AFTER_BREAK */ - if (inferior_pid) - (get_current_frame ())->pc = read_pc (); - - if (breakpoints_failed) - { - terminal_ours_for_output (); - print_sys_errmsg ("ptrace", breakpoints_failed); - printf ("Stopped; cannot insert breakpoints.\n\ -The same program may be running in another process.\n"); - } - - if (inferior_pid) - remove_step_breakpoint (); - - if (inferior_pid && breakpoints_inserted) - if (remove_breakpoints ()) - { - terminal_ours_for_output (); - printf ("Cannot remove breakpoints because program is no longer writable.\n\ -It must be running in another process.\n\ -Further execution is probably impossible.\n"); - } - - breakpoints_inserted = 0; - - /* Delete the breakpoint we stopped at, if it wants to be deleted. - Delete any breakpoint that is to be deleted at the next stop. */ - - breakpoint_auto_delete (stop_breakpoint); - - /* If an auto-display called a function and that got a signal, - delete that auto-display to avoid an infinite recursion. */ - - if (stopped_by_random_signal) - delete_current_display (); - - if (step_multi && stop_step) - return; - - terminal_ours (); - - if (running_in_shell) - { - if (stop_signal == SIGSEGV) - { - char *exec_file = (char *) get_exec_file (1); - - if (access (exec_file, X_OK) != 0) - printf ("The file \"%s\" is not executable.\n", exec_file); - else - printf ("\ -You have just encountered a bug in \"sh\". GDB starts your program\n\ -by running \"sh\" with a command to exec your program.\n\ -This is so that \"sh\" will process wildcards and I/O redirection.\n\ -This time, \"sh\" crashed.\n\ -\n\ -One known bug in \"sh\" bites when the environment takes up a lot of space.\n\ -Try \"info env\" to see the environment; then use \"unset-env\" to kill\n\ -some variables whose values are large; then do \"run\" again.\n\ -\n\ -If that works, you might want to put those \"unset-env\" commands\n\ -into a \".gdbinit\" file in this directory so they will happen every time.\n"); - } - /* Don't confuse user with his program's symbols on sh's data. */ - stop_print_frame = 0; - } - - if (inferior_pid == 0) - return; - - /* Select innermost stack frame except on return from a stack dummy routine, - or if the program has exited. */ - if (!stop_stack_dummy) - { - select_frame (get_current_frame (), 0); - - if (stop_print_frame) - { - if (stop_breakpoint > 0) - printf ("\nBpt %d, ", stop_breakpoint); - print_sel_frame (stop_step - && step_frame_address == stop_frame_address - && step_start_function == find_pc_function (stop_pc)); - /* Display the auto-display expressions. */ - do_displays (); - } - } - - /* Save the function value return registers - We might be about to restore their previous contents. */ - read_register_bytes (0, stop_registers, REGISTER_BYTES); - - if (stop_stack_dummy) - { - /* Pop the empty frame that contains the stack dummy. - POP_FRAME ends with a setting of the current frame, so we - can use that next. */ - POP_FRAME; - select_frame (get_current_frame (), 0); - } -} - -static void -insert_step_breakpoint () -{ - if (step_resume_break_address && !step_resume_break_duplicate) - { - read_memory (step_resume_break_address, - step_resume_break_shadow, sizeof break_insn); - write_memory (step_resume_break_address, - break_insn, sizeof break_insn); - } -} - -static void -remove_step_breakpoint () -{ - if (step_resume_break_address && !step_resume_break_duplicate) - write_memory (step_resume_break_address, step_resume_break_shadow, - sizeof break_insn); -} - -/* Specify how various signals in the inferior should be handled. */ - -static void -handle_command (args, from_tty) - char *args; - int from_tty; -{ - register char *p = args; - int signum = 0; - register int digits, wordlen; - - if (!args) - error_no_arg ("signal to handle"); - - while (*p) - { - /* Find the end of the next word in the args. */ - for (wordlen = 0; p[wordlen] && p[wordlen] != ' ' && p[wordlen] != '\t'; - wordlen++); - for (digits = 0; p[digits] >= '0' && p[digits] <= '9'; digits++); - - /* If it is all digits, it is signal number to operate on. */ - if (digits == wordlen) - { - signum = atoi (p); - if (signum <= 0 || signum >= NSIG) - { - p[wordlen] = '\0'; - error ("Invalid signal %s given as argument to \"handle\".", p); - } - if (signum == SIGTRAP || signum == SIGINT) - { - if (!query ("Signal %d is used by the debugger.\nAre you sure you want to change it? ", signum)) - error ("Not confirmed."); - } - } - else if (signum == 0) - error ("First argument is not a signal number."); - - /* Else, if already got a signal number, look for flag words - saying what to do for it. */ - else if (!strncmp (p, "stop", wordlen)) - { - signal_stop[signum] = 1; - signal_print[signum] = 1; - } - else if (wordlen >= 2 && !strncmp (p, "print", wordlen)) - signal_print[signum] = 1; - else if (wordlen >= 2 && !strncmp (p, "pass", wordlen)) - signal_program[signum] = 1; - else if (!strncmp (p, "ignore", wordlen)) - signal_program[signum] = 0; - else if (wordlen >= 3 && !strncmp (p, "nostop", wordlen)) - signal_stop[signum] = 0; - else if (wordlen >= 4 && !strncmp (p, "noprint", wordlen)) - { - signal_print[signum] = 0; - signal_stop[signum] = 0; - } - else if (wordlen >= 4 && !strncmp (p, "nopass", wordlen)) - signal_program[signum] = 0; - else if (wordlen >= 3 && !strncmp (p, "noignore", wordlen)) - signal_program[signum] = 1; - /* Not a number and not a recognized flag word => complain. */ - else - { - p[wordlen] = 0; - error ("Unrecognized flag word: \"%s\".", p); - } - - /* Find start of next word. */ - p += wordlen; - while (*p == ' ' || *p == '\t') p++; - } - - if (from_tty) - { - /* Show the results. */ - printf ("Number\tStop\tPrint\tPass to program\tDescription\n"); - printf ("%d\t", signum); - printf ("%s\t", signal_stop[signum] ? "Yes" : "No"); - printf ("%s\t", signal_print[signum] ? "Yes" : "No"); - printf ("%s\t\t", signal_program[signum] ? "Yes" : "No"); - printf ("%s\n", sys_siglist[signum]); - } -} - -/* Print current contents of the tables set by the handle command. */ - -static void -signals_info (signum_exp) - char *signum_exp; -{ - register int i; - printf ("Number\tStop\tPrint\tPass to program\tDescription\n"); - - if (signum_exp) - { - i = parse_and_eval_address (signum_exp); - printf ("%d\t", i); - printf ("%s\t", signal_stop[i] ? "Yes" : "No"); - printf ("%s\t", signal_print[i] ? "Yes" : "No"); - printf ("%s\t\t", signal_program[i] ? "Yes" : "No"); - printf ("%s\n", sys_siglist[i]); - return; - } - - printf ("\n"); - for (i = 0; i < NSIG; i++) - { - QUIT; - if (i > 0 && i % 16 == 0) - { - printf ("[Type Return to see more]"); - fflush (stdout); - gdb_read_line (0, 0); - } - printf ("%d\t", i); - printf ("%s\t", signal_stop[i] ? "Yes" : "No"); - printf ("%s\t", signal_print[i] ? "Yes" : "No"); - printf ("%s\t\t", signal_program[i] ? "Yes" : "No"); - printf ("%s\n", sys_siglist[i]); - } - - printf ("\nUse the \"handle\" command to change these tables.\n"); -} - -/* Save all of the information associated with the inferior<==>gdb - connection. INF_STATUS is a pointer to a "struct inferior_status" - (defined in inferior.h). */ - -struct command_line *get_breakpoint_commands (); - -void -save_inferior_status (inf_status, restore_stack_info) - struct inferior_status *inf_status; - int restore_stack_info; -{ - inf_status->pc_changed = pc_changed; - inf_status->stop_signal = stop_signal; - inf_status->stop_pc = stop_pc; - inf_status->stop_frame_address = stop_frame_address; - inf_status->stop_breakpoint = stop_breakpoint; - inf_status->stop_step = stop_step; - inf_status->stop_stack_dummy = stop_stack_dummy; - inf_status->stopped_by_random_signal = stopped_by_random_signal; - inf_status->trap_expected = trap_expected; - inf_status->step_range_start = step_range_start; - inf_status->step_range_end = step_range_end; - inf_status->step_frame_address = step_frame_address; - inf_status->step_over_calls = step_over_calls; - inf_status->step_resume_break_address = step_resume_break_address; - inf_status->stop_after_trap = stop_after_trap; - inf_status->stop_after_attach = stop_after_attach; - inf_status->breakpoint_commands = get_breakpoint_commands (); - inf_status->restore_stack_info = restore_stack_info; - - bcopy (stop_registers, inf_status->stop_registers, REGISTER_BYTES); - - record_selected_frame (&(inf_status->selected_frame_address), - &(inf_status->selected_level)); - return; -} - -void -restore_inferior_status (inf_status) - struct inferior_status *inf_status; -{ - FRAME fid; - int level = inf_status->selected_level; - - pc_changed = inf_status->pc_changed; - stop_signal = inf_status->stop_signal; - stop_pc = inf_status->stop_pc; - stop_frame_address = inf_status->stop_frame_address; - stop_breakpoint = inf_status->stop_breakpoint; - stop_step = inf_status->stop_step; - stop_stack_dummy = inf_status->stop_stack_dummy; - stopped_by_random_signal = inf_status->stopped_by_random_signal; - trap_expected = inf_status->trap_expected; - step_range_start = inf_status->step_range_start; - step_range_end = inf_status->step_range_end; - step_frame_address = inf_status->step_frame_address; - step_over_calls = inf_status->step_over_calls; - step_resume_break_address = inf_status->step_resume_break_address; - stop_after_trap = inf_status->stop_after_trap; - stop_after_attach = inf_status->stop_after_attach; - set_breakpoint_commands (inf_status->breakpoint_commands); - - bcopy (inf_status->stop_registers, stop_registers, REGISTER_BYTES); - - if (inf_status->restore_stack_info) - { - fid = find_relative_frame (get_current_frame (), - &level); - - if (FRAME_FP (fid) != inf_status->selected_frame_address || - level != 0) - { - fprintf (stderr, "Unable to restore previously selected frame.\n"); - select_frame (get_current_frame (), 0); - return; - } - - select_frame (fid, inf_status->selected_level); - } - return; -} - - -void -_initialize_infrun () -{ - register int i; - - add_info ("signals", signals_info, - "What debugger does when program gets various signals.\n\ -Specify a signal number as argument to print info on that signal only."); - - add_com ("handle", class_run, handle_command, - "Specify how to handle a signal.\n\ -Args are signal number followed by flags.\n\ -Flags allowed are \"stop\", \"print\", \"pass\",\n\ - \"nostop\", \"noprint\" or \"nopass\".\n\ -Print means print a message if this signal happens.\n\ -Stop means reenter debugger if this signal happens (implies print).\n\ -Pass means let program see this signal; otherwise program doesn't know.\n\ -Pass and Stop may be combined."); - - for (i = 0; i < NSIG; i++) - { - signal_stop[i] = 1; - signal_print[i] = 1; - signal_program[i] = 1; - } - - /* Signals caused by debugger's own actions - should not be given to the program afterwards. */ - signal_program[SIGTRAP] = 0; - signal_program[SIGINT] = 0; - - /* Signals that are not errors should not normally enter the debugger. */ -#ifdef SIGALRM - signal_stop[SIGALRM] = 0; - signal_print[SIGALRM] = 0; -#endif /* SIGALRM */ -#ifdef SIGVTALRM - signal_stop[SIGVTALRM] = 0; - signal_print[SIGVTALRM] = 0; -#endif /* SIGVTALRM */ -#ifdef SIGPROF - signal_stop[SIGPROF] = 0; - signal_print[SIGPROF] = 0; -#endif /* SIGPROF */ -#ifdef SIGCHLD - signal_stop[SIGCHLD] = 0; - signal_print[SIGCHLD] = 0; -#endif /* SIGCHLD */ -#ifdef SIGCLD - signal_stop[SIGCLD] = 0; - signal_print[SIGCLD] = 0; -#endif /* SIGCLD */ -#ifdef SIGIO - signal_stop[SIGIO] = 0; - signal_print[SIGIO] = 0; -#endif /* SIGIO */ -#ifdef SIGURG - signal_stop[SIGURG] = 0; - signal_print[SIGURG] = 0; -#endif /* SIGURG */ -} - -@ - - -1.2 -log -@Avoid accessing inferior process if it just exited or terminated with -a signal. Clean up stack frame stuff in that case too, so that the -various stack commands ("i frame", "up", "frame", "where") don't get -confused. -@ -text -@d137 5 -@ - - -1.1 -log -@Initial revision -@ -text -@d472 4 -d485 35 -a524 2 - pc_changed = 0; - flush_cached_frames (); -d569 1 -a569 30 - if (WIFEXITED (w)) - { - terminal_ours_for_output (); - if (WRETCODE (w)) - printf ("\nProgram exited with code 0%o.\n", WRETCODE (w)); - else - printf ("\nProgram exited normally.\n"); - fflush (stdout); - inferior_died (); - stop_print_frame = 0; - break; - } - else if (!WIFSTOPPED (w)) - { - kill_inferior (); - stop_print_frame = 0; - stop_signal = WTERMSIG (w); - terminal_ours_for_output (); - printf ("\nProgram terminated with signal %d, %s\n", - stop_signal, - stop_signal < NSIG - ? sys_siglist[stop_signal] - : "(undocumented)"); - printf ("The inferior process no longer exists.\n"); - fflush (stdout); - break; - } - else - { - stop_signal = WSTOPSIG (w); -d571 6 -a576 6 - /* First, distinguish signals caused by the debugger from signals - that have to do with the program's own actions. - Note that breakpoint insns may cause SIGTRAP or SIGILL - or SIGEMT, depending on the operating system version. - Here we detect when a SIGILL or SIGEMT is really a breakpoint - and change it to SIGTRAP. */ -d578 1 -a578 1 - if (stop_signal == SIGTRAP -d580 3 -a582 3 - || (breakpoints_inserted && - (stop_signal == SIGILL - || stop_signal == SIGEMT)) -d584 15 -a598 1 - || stop_after_attach) -d600 1 -a600 15 - if (stop_signal == SIGTRAP && stop_after_trap) - { - stop_print_frame = 0; - break; - } - if (stop_after_attach) - break; - /* Don't even think about breakpoints - if still running the shell that will exec the program - or if just proceeded over a breakpoint. */ - if (stop_signal == SIGTRAP && trap_expected) - stop_breakpoint = 0; - else - { - /* See if there is a breakpoint at the current PC. */ -d602 8 -a609 8 - /* Notice the case of stepping through a jump - that leads just after a breakpoint. - Don't confuse that with hitting the breakpoint. - What we check for is that 1) stepping is going on - and 2) the pc before the last insn does not match - the address of the breakpoint before the current pc. */ - if (!(prev_pc != stop_pc - DECR_PC_AFTER_BREAK - && step_range_end && !step_resume_break_address)) -d611 9 -d621 2 -a622 11 - /* For condition exprs. */ - select_frame (get_current_frame (), 0); - stop_breakpoint = - breakpoint_stop_status (stop_pc, stop_frame_address); - /* Following in case break condition called a - function. */ - stop_print_frame = 1; - if (stop_breakpoint && DECR_PC_AFTER_BREAK) - { - stop_pc -= DECR_PC_AFTER_BREAK; - write_register (PC_REGNUM, stop_pc); -d624 1 -a624 1 - write_register (NPC_REGNUM, stop_pc + 4); -d626 1 -a626 2 - pc_changed = 0; - } -d628 12 -a639 12 - /* See if we stopped at the special breakpoint for - stepping over a subroutine call. */ - if (stop_pc - DECR_PC_AFTER_BREAK - == step_resume_break_address) - { - stop_step_resume_break = 1; - if (DECR_PC_AFTER_BREAK) - { - stop_pc -= DECR_PC_AFTER_BREAK; - write_register (PC_REGNUM, stop_pc); - pc_changed = 0; - } -d642 1 -d644 4 -a647 4 - if (stop_signal == SIGTRAP) - random_signal - = !(stop_breakpoint || trap_expected - || stop_step_resume_break -d649 2 -a650 2 - || (stop_sp INNER_THAN stop_pc - && stop_pc INNER_THAN stop_frame_address) -d652 1 -a652 1 - || stop_pc == text_end - 2 -d654 6 -a659 6 - || (step_range_end && !step_resume_break_address)); - else - { - random_signal - = !(stop_breakpoint - || stop_step_resume_break -d661 2 -a662 2 - || (stop_sp INNER_THAN stop_pc - && stop_pc INNER_THAN stop_frame_address) -d665 3 -a667 4 - ); - if (!random_signal) - stop_signal = SIGTRAP; - } -d669 3 -a671 2 - else - random_signal = 1; -d673 2 -a674 2 - /* For the program's own signals, act according to - the signal handling tables. */ -d676 50 -a725 19 - if (random_signal - && !(running_in_shell && stop_signal == SIGSEGV)) - { - /* Signal not for debugging purposes. */ - int printed = 0; - - stopped_by_random_signal = 1; - - if (stop_signal >= NSIG - || signal_print[stop_signal]) - { - printed = 1; - terminal_ours_for_output (); - printf ("\nProgram received signal %d, %s\n", - stop_signal, - stop_signal < NSIG - ? sys_siglist[stop_signal] - : "(undocumented)"); - fflush (stdout); -d727 1 -a727 7 - if (stop_signal >= NSIG - || signal_stop[stop_signal]) - break; - /* If not going to stop, give terminal back - if we took it away. */ - else if (printed) - terminal_inferior (); -d729 20 -a748 45 - - /* Handle cases caused by hitting a breakpoint. */ - - if (!random_signal - && (stop_breakpoint || stop_step_resume_break)) - { - /* Does a breakpoint want us to stop? */ - if (stop_breakpoint && stop_breakpoint != -1 - && stop_breakpoint != -0x1000001) - { - /* 0x1000000 is set in stop_breakpoint as returned by - breakpoint_stop_status to indicate a silent - breakpoint. */ - if ((stop_breakpoint > 0 ? stop_breakpoint : - -stop_breakpoint) - & 0x1000000) - { - stop_print_frame = 0; - if (stop_breakpoint > 0) - stop_breakpoint -= 0x1000000; - else - stop_breakpoint += 0x1000000; - } - break; - } - /* But if we have hit the step-resumption breakpoint, - remove it. It has done its job getting us here. - The sp test is to make sure that we don't get hung - up in recursive calls in functions without frame - pointers. If the stack pointer isn't outside of - where the breakpoint was set (within a routine to be - stepped over), we're in the middle of a recursive - call. Not true for reg window machines (sparc) - because the must change frames to call things and - the stack pointer doesn't have to change if it - the bp was set in a routine without a frame (pc can - be stored in some other window). - - The removal of the sp test is to allow calls to - alloca. Nasty things were happening. Oh, well, - gdb can only handle one level deep of lack of - frame pointer. */ - if (stop_step_resume_break - && (step_frame_address == 0 - || (stop_frame_address == step_frame_address -d751 1 -a751 1 - && step_resume_break_sp INNER_THAN stop_sp -d754 13 -a766 20 - ))) - { - remove_step_breakpoint (); - step_resume_break_address = 0; - } - /* Otherwise, must remove breakpoints and single-step - to get us past the one we hit. */ - else - { - remove_breakpoints (); - remove_step_breakpoint (); - breakpoints_inserted = 0; - another_trap = 1; - } - - /* We come here if we hit a breakpoint but should not - stop for it. Possibly we also were stepping - and should stop for that. So fall through and - test for stepping. But, if not stepping, - do not stop. */ -d769 9 -a777 2 - /* If this is the breakpoint at the end of a stack dummy, - just stop silently. */ -d779 2 -a780 2 - if (stop_sp INNER_THAN stop_pc - && stop_pc INNER_THAN stop_frame_address) -d782 2 -a783 2 - /* "stack" dummy must be in text segment for Convex Unix */ - if (stop_pc == text_end - 2) -d785 3 -a787 3 - { - stop_print_frame = 0; - stop_stack_dummy = 1; -d789 1 -a789 1 - trap_expected_after_continue = 1; -d791 2 -a792 2 - break; - } -d794 22 -a815 18 - if (step_resume_break_address) - /* Having a step-resume breakpoint overrides anything - else having to do with stepping commands until - that breakpoint is reached. */ - ; - /* If stepping through a line, keep going if still within it. */ - else if (!random_signal - && step_range_end - && stop_pc >= step_range_start - && stop_pc < step_range_end - /* The step range might include the start of the - function, so if we are at the start of the - step range and either the stack or frame pointers - just changed, we've stepped outside */ - && !(stop_pc == step_range_start - && stop_frame_address - && (stop_sp != prev_sp - || stop_frame_address != step_frame_address))) -d817 2 -a818 7 - /* Don't step through the return from a function - unless that is the first instruction stepped through. */ - if (ABOUT_TO_RETURN (stop_pc)) - { - stop_step = 1; - break; - } -d820 1 -d822 43 -a864 43 - /* We stepped out of the stepping range. See if that was due - to a subroutine call that we should proceed to the end of. */ - else if (!random_signal && step_range_end) - { - if (stop_func_start) - { - prologue_pc = stop_func_start; - SKIP_PROLOGUE (prologue_pc); - } - - /* ==> See comments at top of file on this algorithm. <==*/ - - if (stop_pc == stop_func_start - && (stop_func_start != prev_func_start - || prologue_pc != stop_func_start - || stop_sp != prev_sp)) - { - newfun = find_pc_function (stop_pc); - /* It's a subroutine call */ - if (step_over_calls > 0 || (step_over_calls && newfun == 0)) - { - /* A subroutine call has happened. */ - /* Set a special breakpoint after the return */ - step_resume_break_address = - SAVED_PC_AFTER_CALL (get_current_frame ()); - step_resume_break_duplicate - = breakpoint_here_p (step_resume_break_address); - step_resume_break_sp = stop_sp; - if (breakpoints_inserted) - insert_step_breakpoint (); - } - /* Subroutine call with source code we should not step over. - Do step to the first line of code in it. */ - else if (step_over_calls) - { - SKIP_PROLOGUE (stop_func_start); - sal = find_pc_line (stop_func_start, 0); - /* Use the step_resume_break to step until - the end of the prologue, even if that involves jumps - (as it seems to on the vax under 4.2). */ - /* If the prologue ends in the middle of a source line, - continue to the end of that source line. - Otherwise, just go to end of prologue. */ -d866 2 -a867 2 - /* no, don't either. It skips any code that's - legitimately on the first line. */ -d869 2 -a870 2 - if (sal.end && sal.pc != stop_func_start) - stop_func_start = sal.end; -d872 6 -a877 24 - - if (stop_func_start == stop_pc) - { - /* We are already there: stop now. */ - stop_step = 1; - break; - } - else - /* Put the step-breakpoint there and go until there. */ - { - step_resume_break_address = stop_func_start; - step_resume_break_sp = stop_sp; - - step_resume_break_duplicate - = breakpoint_here_p (step_resume_break_address); - if (breakpoints_inserted) - insert_step_breakpoint (); - /* Do not specify what the fp should be when we stop - since on some machines the prologue - is where the new fp value is established. */ - step_frame_address = 0; - /* And make sure stepping stops right away then. */ - step_range_end = step_range_start; - } -d880 1 -d882 13 -a894 7 - /* We get here only if step_over_calls is 0 and we - just stepped into a subroutine. I presume - that step_over_calls is only 0 when we're - supposed to be stepping at the assembly - language level.*/ - stop_step = 1; - break; -a896 1 - /* No subroutince call; stop now. */ -d899 5 -d908 6 -d983 4 -d993 2 -a994 1 - (get_current_frame ())->pc = read_pc (); -@ diff --git a/gdb/RCS/m-aux.h,v b/gdb/RCS/m-aux.h,v deleted file mode 100644 index 2bf07029eb..0000000000 --- a/gdb/RCS/m-aux.h,v +++ /dev/null @@ -1,591 +0,0 @@ -head 1.4; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.4 -date 89.04.26.00.51.42; author gnu; state Exp; -branches ; -next 1.3; - -1.3 -date 89.03.27.20.16.05; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.03.26.20.13.28; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.13.19.16.52; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.4 -log -@(1) Defined the big-endianness of the target machine. -(2) Define float to be IEEE compatible. -(3) Define invalid floats to be NaNs. -@ -text -@/* Parameters for execution on A/UX, for GDB, the GNU debugger. - Copyright (C) 1989 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! -*/ - -#ifndef aux -#define aux -#endif - -/* It's a USG system */ -#define USG - -/* Assembler instructions in USG "SGS" (sw generation system) format */ -#define USG_SGS_ASM - -/* Debugger information will be in COFF format. */ -#define COFF_FORMAT -#define COFF_NO_LONG_FILE_NAMES - -/* Terminal interface via termio */ -#define HAVE_TERMIO - -/* Unisoft fucked up the include files */ -#define UNISOFT_ASSHOLES - -/* Big or Little-Endian target machine - BITS: defined if bit #0 is the high-order bit of a byte. - BYTES:defined if byte#0 is the high-order byte of an int. - WORDS:defined if word#0 is the high-order word of a double. */ -#define BITS_BIG_ENDIAN -#define BYTES_BIG_ENDIAN -#define WORDS_BIG_ENDIAN - -/* Floating point is IEEE compatible */ -#define IEEE_FLOAT - -/* 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(pc) \ -{ register int op = read_memory_integer (pc, 2); \ - if (op == 0047126) \ - pc += 4; /* Skip link #word */ \ - else if (op == 0044016) \ - pc += 6; /* Skip link #long */ \ -} - -/* Immediately after a function call, return the saved pc. - Can't 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) - -/* Address of end of stack space. */ - -#define STACK_END_ADDR 0x20000000 - -/* Stack grows downward. */ - -#define INNER_THAN < - -/* Sequence of bytes for breakpoint instruction. */ -/* A/UX uses "trap &1" */ - -#define BREAKPOINT {0x4e, 0x41} - -/* 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 0 - -/* Nonzero if instruction at PC is a return instruction. */ - -#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e75) - -/* Return 1 if P points to an invalid floating point value. */ -/* FIXME, it's not clear what "invalid" means here. I take it to mean - "something that coredumps gdb if gdb tries to manipulate it" */ - -#define INVALID_FLOAT(p, len) is_nan(p, len) - -/* 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 29 - -/* Initializer for an array of names of registers. - There should be NUM_REGS strings in this initializer. */ - -#define REGISTER_NAMES \ - {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \ - "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \ - "ps", "pc", \ - "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \ - "fpcontrol", "fpstatus", "fpiaddr" } - -/* 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 14 /* Contains address of executing stack frame */ -#define SP_REGNUM 15 /* Contains address of top of stack */ -#define PS_REGNUM 16 /* Contains processor status */ -#define PC_REGNUM 17 /* Contains program counter */ -#define FP0_REGNUM 18 /* Floating point register 0 */ -#define FPC_REGNUM 26 /* 68881 control register */ - -/* This is a piece of magic that is given a register number REGNO - and as BLOCKEND the address in the system of the end of the user structure - and stores in ADDR the address in the kernel or core dump - of that register. */ - -#define REGISTER_U_ADDR(addr, blockend, regno) { \ - struct user u; \ - if (regno <= SP_REGNUM) \ - addr = blockend + regno * 4; \ - else if (regno == PS_REGNUM) \ - addr = blockend + RPS * 4; /* From reg.h */ \ - else if (regno == PC_REGNUM) \ - addr = blockend + PC * 4; /* From reg.h */ \ - else if (regno < FPC_REGNUM) \ - addr = (char *) u.u_fpdreg [regno-FP0_REGNUM] - (char *)&u; \ - else \ - addr = (char *)&u.u_fpsysreg[regno-FPC_REGNUM] - (char *)&u; \ -} - -/* Describe the pointer in each stack frame to the previous stack frame - (its caller). */ -/* Total amount of space needed to store our copies of the machine's - register state, the array `registers'. */ -#define REGISTER_BYTES (16*4+8*12+8+20) - -/* Index within `registers' of the first byte of the space for - register N. */ - -#define REGISTER_BYTE(N) \ - ((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 168 \ - : (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 12) + 72 \ - : (N) * 4) - -/* Number of bytes of storage in the actual machine representation - for register N. On the 68000, all regs are 4 bytes - except the floating point regs which are 12 bytes. */ -/* Note that the unsigned cast here forces the result of the - subtractiion to very high positive values if N < FP0_REGNUM */ - -#define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4) - -/* Number of bytes of storage in the program's representation - for register N. On the 68000, all regs are 4 bytes - except the floating point regs which are 8-byte doubles. */ - -#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 8 : 4) - -/* Largest value REGISTER_RAW_SIZE can have. */ - -#define MAX_REGISTER_RAW_SIZE 12 - -/* Largest value REGISTER_VIRTUAL_SIZE can have. */ - -#define MAX_REGISTER_VIRTUAL_SIZE 8 - -/* Nonzero if register N requires conversion - from raw format to virtual format. */ - -#define REGISTER_CONVERTIBLE(N) (((unsigned)(N) - FP0_REGNUM) < 8) - -/* Convert data from raw format for register REGNUM - to virtual format for register REGNUM. */ - -#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \ -{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \ - convert_from_68881 ((FROM), (TO)); \ - else \ - 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) \ -{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \ - convert_to_68881 ((FROM), (TO)); \ - else \ - bcopy ((FROM), (TO), 4); } - -/* Return the GDB type object for the "standard" data type - of data in register N. */ - -#define REGISTER_VIRTUAL_TYPE(N) \ - (((unsigned)(N) - FP0_REGNUM) < 8 ? builtin_type_double : 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) \ - { write_register (9, (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. */ - -/* In the case of the 68k, the frame's nominal address - is the address of a 4-byte word containing the calling frame's address. */ - -#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4)) - -#define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) - -#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain) - -/* Define other aspects of the stack frame. */ - -#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) - -/* Set VAL to the number of args passed to frame described by FI. - Can set VAL to -1, meaning no way to tell. */ - -/* We can't tell how many args there are - now that the C compiler delays popping them. */ -#define FRAME_NUM_ARGS(val,fi) (val = -1) - -#if 0 -#define FRAME_NUM_ARGS(val, fi) \ -{ register CORE_ADDR pc = FRAME_SAVED_PC (fi); \ - register int insn = 0177777 & read_memory_integer (pc, 2); \ - val = 0; \ - if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \ - val = read_memory_integer (pc + 2, 2); \ - else if ((insn & 0170777) == 0050217 /* addql #N, sp */ \ - || (insn & 0170777) == 0050117) /* addqw */ \ - { val = (insn >> 9) & 7; if (val == 0) val = 8; } \ - else if (insn == 0157774) /* addal #WW, sp */ \ - val = read_memory_integer (pc + 2, 4); \ - val >>= 2; } -#endif - -/* 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) \ -{ register int regnum; \ - register int regmask; \ - register CORE_ADDR next_addr; \ - register CORE_ADDR pc; \ - int nextinsn; \ - bzero (&frame_saved_regs, sizeof frame_saved_regs); \ - if ((frame_info)->pc >= (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \ - && (frame_info)->pc <= (frame_info)->frame) \ - { next_addr = (frame_info)->frame; \ - pc = (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\ - else \ - { pc = get_pc_function_start ((frame_info)->pc); \ - /* Verify we have a link a6 instruction next; \ - if not we lose. If we win, find the address above the saved \ - regs using the amount of storage from the link instruction. */\ - if (044016 == read_memory_integer (pc, 2)) \ - next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 4), pc+=4; \ - else if (047126 == read_memory_integer (pc, 2)) \ - next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 2), pc+=2; \ - else goto lose; \ - /* If have an addal #-n, sp next, adjust next_addr. */ \ - if ((0177777 & read_memory_integer (pc, 2)) == 0157774) \ - next_addr += read_memory_integer (pc += 2, 4), pc += 4; \ - } \ - /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ \ - regmask = read_memory_integer (pc + 2, 2); \ - /* But before that can come an fmovem. Check for it. */ \ - nextinsn = 0xffff & read_memory_integer (pc, 2); \ - if (0xf227 == nextinsn \ - && (regmask & 0xff00) == 0xe000) \ - { pc += 4; /* Regmask's low bit is for register fp7, the first pushed */ \ - for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \ - if (regmask & 1) \ - (frame_saved_regs).regs[regnum] = (next_addr -= 12); \ - regmask = read_memory_integer (pc + 2, 2); } \ - if (0044327 == read_memory_integer (pc, 2)) \ - { pc += 4; /* Regmask's low bit is for register 0, the first written */ \ - for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \ - if (regmask & 1) \ - (frame_saved_regs).regs[regnum] = (next_addr += 4) - 4; } \ - else if (0044347 == read_memory_integer (pc, 2)) \ - { pc += 4; /* Regmask's low bit is for register 15, the first pushed */ \ - for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \ - if (regmask & 1) \ - (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \ - else if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2))) \ - { regnum = 0xf & read_memory_integer (pc, 2); pc += 2; \ - (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \ - /* fmovemx to index of sp may follow. */ \ - regmask = read_memory_integer (pc + 2, 2); \ - nextinsn = 0xffff & read_memory_integer (pc, 2); \ - if (0xf236 == nextinsn \ - && (regmask & 0xff00) == 0xf000) \ - { pc += 10; /* Regmask's low bit is for register fp0, the first written */ \ - for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \ - if (regmask & 1) \ - (frame_saved_regs).regs[regnum] = (next_addr += 12) - 12; \ - regmask = read_memory_integer (pc + 2, 2); } \ - /* clrw -(sp); movw ccr,-(sp) may follow. */ \ - if (0x426742e7 == read_memory_integer (pc, 4)) \ - (frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4); \ - lose: ; \ - (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 8; \ - (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame; \ - (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4; \ -} - -/* Things needed for making the inferior call functions. */ - -/* Push an empty stack frame, to record the current PC, etc. */ - -#define PUSH_DUMMY_FRAME \ -{ register CORE_ADDR sp = read_register (SP_REGNUM); \ - register int regnum; \ - char raw_buffer[12]; \ - sp = push_word (sp, read_register (PC_REGNUM)); \ - sp = push_word (sp, read_register (FP_REGNUM)); \ - write_register (FP_REGNUM, sp); \ - for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \ - { read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \ - sp = push_bytes (sp, raw_buffer, 12); } \ - for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \ - sp = push_word (sp, read_register (regnum)); \ - sp = push_word (sp, read_register (PS_REGNUM)); \ - write_register (SP_REGNUM, sp); } - -/* Discard from the stack the innermost frame, - restoring all saved registers. */ - -#define POP_FRAME \ -{ register FRAME frame = get_current_frame (); \ - register CORE_ADDR fp; \ - register int regnum; \ - struct frame_saved_regs fsr; \ - struct frame_info *fi; \ - char raw_buffer[12]; \ - fi = get_frame_info (frame); \ - fp = fi->frame; \ - get_frame_saved_regs (fi, &fsr); \ - for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \ - if (fsr.regs[regnum]) \ - { read_memory (fsr.regs[regnum], raw_buffer, 12); \ - write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\ - for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \ - if (fsr.regs[regnum]) \ - write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \ - if (fsr.regs[PS_REGNUM]) \ - write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \ - write_register (FP_REGNUM, read_memory_integer (fp, 4)); \ - write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \ - write_register (SP_REGNUM, fp + 8); \ - flush_cached_frames (); \ - set_current_frame (create_new_frame (read_register (FP_REGNUM),\ - read_pc ())); } - -/* This sequence of words is the instructions - fmovem 0xff,-(sp) - moveml 0xfffc,-(sp) - clrw -(sp) - movew ccr,-(sp) - /..* The arguments are pushed at this point by GDB; - no code is needed in the dummy for this. - The CALL_DUMMY_START_OFFSET gives the position of - the following jsr instruction. *../ - jsr @@#32323232 - addl #69696969,sp - trap #15 - nop -Note this is 28 bytes. -We actually start executing at the jsr, since the pushing of the -registers is done by PUSH_DUMMY_FRAME. If this were real code, -the arguments for the function called by the jsr would be pushed -between the moveml and the jsr, and we could allow it to execute through. -But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done, -and we cannot allow the moveml to push the registers again lest they be -taken for the arguments. */ - -#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71} - -#define CALL_DUMMY_LENGTH 28 - -#define CALL_DUMMY_START_OFFSET 12 - -/* 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 *)((char *) dummyname + 20) = nargs * 4; \ - *(int *)((char *) dummyname + 14) = fun; } - -/* 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, SIGTRAP, 0, 0, 0, \ - 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - SIGILL } - -/* 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) \ -{ asm (".globl end"); \ - asm ("movel #end, sp"); \ - asm ("movel #0,a6"); } - -/* Push the frame pointer register on the stack. */ -#define PUSH_FRAME_PTR \ - asm ("movel a6,sp@@-"); - -/* Copy the top-of-stack to the frame pointer register. */ -#define POP_FRAME_PTR \ - asm ("movl sp@@,a6"); - -/* 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 \ -{ asm ("clrw -(sp)"); \ - asm ("pea sp@@(10)"); \ - asm ("movem #0xfffe,sp@@-"); } - -/* 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 \ -{ asm ("subil #8,sp@@(28)"); \ - asm ("movem sp@@,#0xffff"); \ - asm ("rte"); } -@ - - -1.3 -log -@Fix DECR_PC_AFTER_BREAK; A/UX reports breaks at the breakpoint addr, -not there+2. -@ -text -@d41 11 -d100 2 -d103 1 -a103 1 -#define INVALID_FLOAT(p, len) 1 /* FIXME! Just a first guess; not checked */ -@ - - -1.2 -log -@Mostly works! -@ -text -@d82 1 -a82 1 -#define DECR_PC_AFTER_BREAK 2 -@ - - -1.1 -log -@Initial revision -@ -text -@d1 504 -@ diff --git a/gdb/RCS/m-sparc.h,v b/gdb/RCS/m-sparc.h,v deleted file mode 100644 index 1720dfe65a..0000000000 --- a/gdb/RCS/m-sparc.h,v +++ /dev/null @@ -1,747 +0,0 @@ -head 1.3; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.3 -date 89.04.26.00.52.29; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.03.16.21.10.29; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.14.15.28.32; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.3 -log -@(1) Define big-endianness of SPARC. -(2) Define IEEE compatible float. -@ -text -@/* Parameters for execution on a Sun 4, for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. - Contributed by Michael Tiemann (tiemann@@mcc.com) - -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! -*/ - -#ifndef sun4 -#define sun4 -#endif - -/* 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 - -/* Debugger information will be in DBX format. */ - -#define READ_DBX_FORMAT - -/* Big or Little-Endian target machine - BITS: defined if bit #0 is the high-order bit of a byte. - BYTES:defined if byte#0 is the high-order byte of an int. - WORDS:defined if word#0 is the high-order word of a double. */ -#define BITS_BIG_ENDIAN -#define BYTES_BIG_ENDIAN -#define WORDS_BIG_ENDIAN - -/* Floating point is IEEE compatible. */ -#define IEEE_FLOAT - -/* 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(pc) \ - { pc = skip_prologue (pc); } - -/* Immediately after a function call, return the saved pc. - Can't go through the frames for this because on some machines - the new frame is not set up until the new function executes - some instructions. */ - -/* On the Sun 4 under SunOS, the compile will leave a fake insn which - encodes the structure size being returned. If we detect such - a fake insn, step past it. */ - -#define PC_ADJUST(pc) ((read_memory_integer (pc + 8, 4) & 0xfffffe00) == 0 ? \ - pc+12 : pc+8) - -#define SAVED_PC_AFTER_CALL(frame) PC_ADJUST (read_register (RP_REGNUM)) - -/* Address of end of stack space. */ - -#define STACK_END_ADDR 0xf8000000 - -/* Stack grows downward. */ - -#define INNER_THAN < - -/* Stack has strict alignment. */ - -#define STACK_ALIGN(ADDR) (((ADDR)+7)&-8) - -/* Sequence of bytes for breakpoint instruction. */ - -#define BREAKPOINT {0x91, 0xd0, 0x20, 0x01} - -/* 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 0 - -/* Nonzero if instruction at PC is a return instruction. */ -/* For SPARC, this is either a "jmpl %o7+8,%g0" or "jmpl %i7+8,%g0". - - Note: this does not work for functions returning structures under SunOS. */ -#define ABOUT_TO_RETURN(pc) \ - ((read_memory_integer (pc, 4)|0x00040000) == 0x81c7e008) - -/* Return 1 if P points to an invalid floating point value. */ - -#define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */ - -/* 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 72 - -/* Initializer for an array of names of registers. - There should be NUM_REGS strings in this initializer. */ - -#define REGISTER_NAMES \ -{ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", \ - "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7", \ - "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", \ - "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7", \ - \ - "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \ - "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \ - "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", \ - "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", \ - \ - "y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr" }; - -/* 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 30 /* Contains address of executing stack frame */ -#define RP_REGNUM 15 /* Contains return address value, *before* \ - any windows get switched. */ -#define SP_REGNUM 14 /* Contains address of top of stack, \ - which is also the bottom of the frame. */ -#define Y_REGNUM 64 /* Temp register for multiplication, etc. */ -#define PS_REGNUM 65 /* Contains processor status */ -#define PC_REGNUM 68 /* Contains program counter */ -#define NPC_REGNUM 69 /* Contains next PC */ -#define FP0_REGNUM 32 /* Floating point register 0 */ -#define FPS_REGNUM 70 /* Floating point status register */ -#define CPS_REGNUM 71 /* Coprocessor status register */ - -/* Total amount of space needed to store our copies of the machine's - register state, the array `registers'. */ -#define REGISTER_BYTES (32*4+32*4+8*4) - -/* Index within `registers' of the first byte of the space for - register N. */ -/* ?? */ -#define REGISTER_BYTE(N) ((N)*4) - -/* The SPARC processor has register windows. */ - -#define HAVE_REGISTER_WINDOWS - -/* Is this register part of the register window system? A yes answer - implies that 1) The name of this register will not be the same in - other frames, and 2) This register is automatically "saved" (out - registers shifting into ins counts) upon subroutine calls and thus - there is no need to search more than one stack frame for it. */ - -#define REGISTER_IN_WINDOW_P(regnum) \ - ((regnum) >= 8 && (regnum) < 32) - -/* Number of bytes of storage in the actual machine representation - for register N. */ - -/* On the SPARC, all regs are 4 bytes. */ - -#define REGISTER_RAW_SIZE(N) (4) - -/* Number of bytes of storage in the program's representation - for register N. */ - -/* On the SPARC, all regs are 4 bytes. */ - -#define REGISTER_VIRTUAL_SIZE(N) (4) - -/* Largest value REGISTER_RAW_SIZE can have. */ - -#define MAX_REGISTER_RAW_SIZE 8 - -/* Largest value REGISTER_VIRTUAL_SIZE can have. */ - -#define MAX_REGISTER_VIRTUAL_SIZE 8 - -/* 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) \ - ((N) < 32 ? builtin_type_int : (N) < 64 ? builtin_type_float : \ - 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) \ - { write_memory ((SP)+(16*4), &(ADDR), 4); } - -/* 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 (((int *)(REGBUF))+8, (VALBUF), TYPE_LENGTH (TYPE)) - -/* Write into appropriate registers a function return value - of type TYPE, given in virtual format. */ -/* On sparc, values are returned in register %o0. */ -#define STORE_RETURN_VALUE(TYPE,VALBUF) \ - write_register_bytes (REGISTER_BYTE (8), 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) \ - (read_memory_integer (((int *)(REGBUF))[SP_REGNUM]+(16*4), 4)) - -/* Enable use of alternate code to read and write registers. */ - -#define NEW_SUN_PTRACE - -/* Enable use of alternate code for Sun's format of core dump file. */ - -#define NEW_SUN_CORE - -/* Do implement the attach and detach commands. */ - -#define ATTACH_DETACH - -/* It is safe to look for symsegs on a Sun, because Sun's ld - does not screw up with random garbage at end of file. */ - -#define READ_GDB_SYMSEGS - - -/* Describe the pointer in each stack frame to the previous stack frame - (its caller). */ -#include - -#define GET_RWINDOW_REG(FRAME, REG) \ - (read_memory_integer (&((struct rwindow *)FRAME)->REG, 4)) - -/* 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. */ - -/* In the case of the Sun 4, the frame-chain's nominal address - is held in the frame pointer register. - - On the Sun4, the frame (in %fp) is %sp for the previous frame. - From the previous frame's %sp, we can find the previous frame's - %fp: it is in the save area just above the previous frame's %sp. - - If we are setting up an arbitrary frame, we'll need to know where - it ends. Hence the following. This part of the frame cache - structure should be checked before it is assumed that this frame's - bottom is in the stack pointer. - - If there isn't a frame below this one, the bottom of this frame is - in the stack pointer. - - If there is a frame below this one, and the frame pointers are - identical, it's a leaf frame and the bottoms are the same also. - - Otherwise the bottom of this frame is the top of the next frame. */ - -#define EXTRA_FRAME_INFO FRAME_ADDR bottom; -#define INIT_EXTRA_FRAME_INFO(fci) \ - (fci)->bottom = \ - ((fci)->next ? \ - ((fci)->frame == (fci)->next_frame ? \ - (fci)->next->bottom : (fci)->next->frame) : \ - read_register (SP_REGNUM)); - -#define FRAME_CHAIN(thisframe) \ - GET_RWINDOW_REG ((thisframe)->frame, rw_in[6]) - -/* Avoid checking FRAME_SAVED_PC since that screws us due to - improperly set up saved PC on a signal trampoline call */ -#if 0 -#define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) -#else -#define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0) -#endif - -#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain) - -/* Define other aspects of the stack frame. */ - -/* Where is the PC for a specific frame */ - -#define FRAME_SAVED_PC(FRAME) frame_saved_pc (FRAME) - -/* If the argument is on the stack, it will be here. */ -#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame) - -#define FRAME_STRUCT_ARGS_ADDRESS(fi) ((fi)->frame) - -#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame) - -/* Set VAL to the number of args passed to frame described by FI. - Can set VAL to -1, meaning no way to tell. */ - -/* We can't tell how many args there are - now that the C compiler delays popping them. */ -#define FRAME_NUM_ARGS(val,fi) (val = -1) - -/* Return number of bytes at start of arglist that are not really args. */ - -#define FRAME_ARGS_SKIP 68 - -/* 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. - - Note that on register window machines, we are currently making the - assumption that window registers are being saved somewhere in the - frame in which they are being used. If they are stored in an - inferior frame, find_saved_register will break. - - On the Sun 4, the only time all registers are saved is when - a dummy frame is involved. Otherwise, the only saved registers - are the LOCAL and IN registers which are saved as a result - of the "save/restore" opcodes. This condition is determined - by address rather than by value. */ - -#define FRAME_FIND_SAVED_REGS(fi, frame_saved_regs) \ -{ register int regnum; \ - register CORE_ADDR pc; \ - FRAME_ADDR frame = read_register (FP_REGNUM); \ - FRAME fid = FRAME_INFO_ID (fi); \ - if (!fid) fatal ("Bad frame info struct in FRAME_FIND_SAVED_REGS"); \ - bzero (&(frame_saved_regs), sizeof (frame_saved_regs)); \ - if ((fi)->pc >= frame - CALL_DUMMY_LENGTH - 0x140 \ - && (fi)->pc <= frame) \ - { \ - for (regnum = 1; regnum < 8; regnum++) \ - (frame_saved_regs).regs[regnum] = \ - frame + regnum * 4 - 0xa0; \ - for (regnum = 24; regnum < 32; regnum++) \ - (frame_saved_regs).regs[regnum] = \ - frame + (regnum - 24) * 4 - 0xc0; \ - for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 32; regnum++) \ - (frame_saved_regs).regs[regnum] = \ - frame + (regnum - FP0_REGNUM) * 4 - 0x80; \ - for (regnum = 64; regnum < NUM_REGS; regnum++) \ - (frame_saved_regs).regs[regnum] = \ - frame + (regnum - 64) * 4 - 0xe0; \ - frame = (fi)->bottom ? \ - (fi)->bottom : read_register (SP_REGNUM); \ - } \ - else \ - { \ - frame = (fi)->bottom ? \ - (fi)->bottom : read_register (SP_REGNUM); \ - for (regnum = 16; regnum < 32; regnum++) \ - (frame_saved_regs).regs[regnum] = frame + (regnum-16) * 4; \ - } \ - if ((fi)->next) \ - { \ - /* Pull off either the next frame pointer or \ - the stack pointer */ \ - FRAME_ADDR next_next_frame = \ - ((fi)->next->bottom ? \ - (fi)->next->bottom : \ - read_register (SP_REGNUM)); \ - for (regnum = 8; regnum < 16; regnum++) \ - (frame_saved_regs).regs[regnum] = next_next_frame + regnum * 4; \ - } \ - /* Otherwise, whatever we would get from ptrace(GETREGS) */ \ - /* is accurate */ \ - for (regnum = 30; regnum < 32; regnum++) \ - (frame_saved_regs).regs[regnum] = frame + (regnum-16) * 4; \ - (frame_saved_regs).regs[SP_REGNUM] = frame; \ - (frame_saved_regs).regs[PC_REGNUM] = frame + 15*4; \ -} - -/* Things needed for making the inferior call functions. */ -/* - * First of all, let me give my opinion of what the DUMMY_FRAME - * actually looks like. - * - * | | - * | | - * + - - - - - - - - - - - - - - - - +<-- fp (level 0) - * | | - * | | - * | | - * | | - * | Frame of innermost program | - * | function | - * | | - * | | - * | | - * | | - * | | - * |---------------------------------|<-- sp (level 0), fp (c) - * | | - * DUMMY | fp0-31 | - * | | - * | ------ |<-- fp - 0x80 - * FRAME | g0-7 |<-- fp - 0xa0 - * | i0-7 |<-- fp - 0xc0 - * | other |<-- fp - 0xe0 - * | ? | - * | ? | - * |---------------------------------|<-- sp' = fp - 0x140 - * | | - * xcution start | | - * sp' + 0x94 -->| CALL_DUMMY (x code) | - * | | - * | | - * |---------------------------------|<-- sp'' = fp - 0x200 - * | align sp to 8 byte boundary | - * | ==> args to fn <== | - * Room for | | - * i & l's + agg | CALL_DUMMY_STACK_ADJUST = 0x0x44| - * |---------------------------------|<-- final sp (variable) - * | | - * | Where function called will | - * | build frame. | - * | | - * | | - * - * I understand everything in this picture except what the space - * between fp - 0xe0 and fp - 0x140 is used for. Oh, and I don't - * understand why there's a large chunk of CALL_DUMMY that never gets - * executed (its function is superceeded by PUSH_DUMMY_FRAME; they - * are designed to do the same thing). - * - * PUSH_DUMMY_FRAME saves the registers above sp' and pushes the - * register file stack down one. - * - * call_function then writes CALL_DUMMY, pushes the args onto the - * stack, and adjusts the stack pointer. - * - * run_stack_dummy then starts execution (in the middle of - * CALL_DUMMY, as directed by call_function). - */ - -/* Push an empty stack frame, to record the current PC, etc. */ - -/* Note: to be perfectly correct, we have to restore the - IN registers (which were the OUT registers of the calling frame). */ -/* Note that the write's are of registers in the context of the newly - pushed frame. Thus the the fp*'s, the g*'s, the i*'s, and - the others, of the new frame, are being saved. - The locals are new; they don't need to be saved. The i's and l's of - the last frame were saved by the do_save_insn in the register - file (ie. on the stack, since a context switch happended imm after) */ -/* We note that the return pointer register does not *need* to have - the pc saved into it (return from this frame will be accomplished - by a POP_FRAME), however, just in case it might be needed, we will - leave it. However, we will write the original value of RP into the - location on the stack for saving i7 (what rp turns into upon call); - this way we don't loose the value with our function call. */ -/* Note that the pc saved must be 8 less than the actual pc, since - both POP_FRAME and the normal return sequence on the sparc return - to 8 more than the value of RP_REGNUM */ - -#define PUSH_DUMMY_FRAME \ -{ extern char registers[]; \ - register int regnum; \ - CORE_ADDR fp = read_register (FP_REGNUM); \ - CORE_ADDR pc = read_register (PC_REGNUM) - 8; \ - CORE_ADDR rp = read_register (RP_REGNUM); \ - void do_save_insn (); \ - supply_register (RP_REGNUM, &pc); \ - do_save_insn (0x140); \ - fp = read_register (FP_REGNUM); \ - write_memory (fp - 0x80, ®isters[REGISTER_BYTE (FP0_REGNUM)], 32 * 4);\ - write_memory (fp - 0xa0, ®isters[REGISTER_BYTE (0)], 8 * 4); \ - write_memory (fp - 0xc0, ®isters[REGISTER_BYTE (24)], 7 * 4); \ - write_memory (fp - 0xa4, &rp, 4); \ - write_memory (fp - 0xe0, ®isters[REGISTER_BYTE (64)], 8 * 4); \ -} - -/* Discard from the stack the innermost frame, - restoring all saved registers. - Note that the values stored in fsr by get_frame_saved_regs are *in - the context of the inferior frame*. What this means is that the i - regs of fsr must be restored into the o regs of the frame popped - into. We don't care about the output regs of the inferior frame. - - This is true for dummy frames. Is it true for normal frames? It - really does appear so. */ - -#define POP_FRAME \ -{ register FRAME frame = get_current_frame (); \ - register CORE_ADDR fp; \ - register CORE_ADDR pc; \ - register int regnum; \ - struct frame_saved_regs fsr; \ - struct frame_info *fi; \ - char raw_buffer[REGISTER_BYTES]; \ - void do_restore_insn (); \ - fi = get_frame_info (frame); \ - fp = fi->frame; \ - get_frame_saved_regs (fi, &fsr); \ - pc = read_memory_integer (fsr.regs[PC_REGNUM], 4); \ - do_restore_insn (PC_ADJUST (pc)); \ - if (fsr.regs[FP0_REGNUM]) \ - { \ - read_memory (fsr.regs[FP0_REGNUM], raw_buffer, 32 * 4); \ - write_register_bytes (REGISTER_BYTE (FP0_REGNUM), raw_buffer, 32 * 4); \ - } \ - if (fsr.regs[1]) \ - { \ - read_memory (fsr.regs[1], raw_buffer, 7 * 4); \ - write_register_bytes (REGISTER_BYTE (1), raw_buffer, 7 * 4); \ - } \ - if (fsr.regs[24]) \ - { \ - read_memory (fsr.regs[24], raw_buffer, 8 * 4); \ - write_register_bytes (REGISTER_BYTE (8), raw_buffer, 8 * 4); \ - } \ - if (fsr.regs[PS_REGNUM]) \ - write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \ - if (fsr.regs[Y_REGNUM]) \ - write_register (Y_REGNUM, read_memory_integer (fsr.regs[Y_REGNUM], 4)); \ - if (fsr.regs[NPC_REGNUM]) \ - write_register (NPC_REGNUM, read_memory_integer (fsr.regs[NPC_REGNUM], 4)); \ - flush_cached_frames (); \ - set_current_frame ( create_new_frame (read_register (FP_REGNUM), \ - read_pc ())); } - -/* This sequence of words is the instructions - - save %sp,-0x140,%sp - std %f30,[%fp-0x08] - std %f28,[%fp-0x10] - std %f26,[%fp-0x18] - std %f24,[%fp-0x20] - std %f22,[%fp-0x28] - std %f20,[%fp-0x30] - std %f18,[%fp-0x38] - std %f16,[%fp-0x40] - std %f14,[%fp-0x48] - std %f12,[%fp-0x50] - std %f10,[%fp-0x58] - std %f8,[%fp-0x60] - std %f6,[%fp-0x68] - std %f4,[%fp-0x70] - std %f2,[%fp-0x78] - std %f0,[%fp-0x80] - std %g6,[%fp-0x88] - std %g4,[%fp-0x90] - std %g2,[%fp-0x98] - std %g0,[%fp-0xa0] - std %i6,[%fp-0xa8] - std %i4,[%fp-0xb0] - std %i2,[%fp-0xb8] - std %i0,[%fp-0xc0] - nop ! stcsr [%fp-0xc4] - nop ! stfsr [%fp-0xc8] - nop ! wr %npc,[%fp-0xcc] - nop ! wr %pc,[%fp-0xd0] - rd %tbr,%o0 - st %o0,[%fp-0xd4] - rd %wim,%o1 - st %o0,[%fp-0xd8] - rd %psr,%o0 - st %o0,[%fp-0xdc] - rd %y,%o0 - st %o0,[%fp-0xe0] - - /..* The arguments are pushed at this point by GDB; - no code is needed in the dummy for this. - The CALL_DUMMY_START_OFFSET gives the position of - the following ld instruction. *../ - - ld [%sp+0x58],%o5 - ld [%sp+0x54],%o4 - ld [%sp+0x50],%o3 - ld [%sp+0x4c],%o2 - ld [%sp+0x48],%o1 - call 0x00000000 - ld [%sp+0x44],%o0 - nop - ta 1 - nop - - note that this is 192 bytes, which is a multiple of 8 (not only 4) bytes. - note that the `call' insn is a relative, not an absolute call. - note that the `nop' at the end is needed to keep the trap from - clobbering things (if NPC pointed to garbage instead). - -We actually start executing at the `sethi', since the pushing of the -registers (as arguments) is done by PUSH_DUMMY_FRAME. If this were -real code, the arguments for the function called by the CALL would be -pushed between the list of ST insns and the CALL, and we could allow -it to execute through. But the arguments have to be pushed by GDB -after the PUSH_DUMMY_FRAME is done, and we cannot allow these ST -insns to be performed again, lest the registers saved be taken for -arguments. */ - -#define CALL_DUMMY { 0x9de3bee0, 0xfd3fbff8, 0xf93fbff0, 0xf53fbfe8, \ - 0xf13fbfe0, 0xed3fbfd8, 0xe93fbfd0, 0xe53fbfc8, \ - 0xe13fbfc0, 0xdd3fbfb8, 0xd93fbfb0, 0xd53fbfa8, \ - 0xd13fbfa0, 0xcd3fbf98, 0xc93fbf90, 0xc53fbf88, \ - 0xc13fbf80, 0xcc3fbf78, 0xc83fbf70, 0xc43fbf68, \ - 0xc03fbf60, 0xfc3fbf58, 0xf83fbf50, 0xf43fbf48, \ - 0xf03fbf40, 0x01000000, 0x01000000, 0x01000000, \ - 0x01000000, 0x91580000, 0xd027bf50, 0x93500000, \ - 0xd027bf4c, 0x91480000, 0xd027bf48, 0x91400000, \ - 0xd027bf44, 0xda03a058, 0xd803a054, 0xd603a050, \ - 0xd403a04c, 0xd203a048, 0x40000000, 0xd003a044, \ - 0x01000000, 0x91d02001, 0x01000000, 0x01000000} - -#define CALL_DUMMY_LENGTH 192 - -#define CALL_DUMMY_START_OFFSET 148 - -#define CALL_DUMMY_STACK_ADJUST 68 - -/* 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 *)((char *) dummyname+168) = (0x40000000|((fun-(pc+168))>>2)); \ - if (TYPE_CODE (type) == TYPE_CODE_STRUCT \ - || TYPE_CODE (type) == TYPE_CODE_UNION) \ - *(int *)((char *) dummyname+176) = (TYPE_LENGTH (type) & 0x1fff); \ -} - - -/* Sparc has no reliable single step ptrace call */ - -#define NO_SINGLE_STEP 1 - -/* It does have a wait structure, and it might help things out . . . */ - -#define HAVE_WAIT_STRUCT - -/* Handle a feature in the sun4 compiler ("call .stret4" at the end of - functions returning structures). */ - -#define SUN4_COMPILER_FEATURE - -/* We need two arguments (in general) to the "info frame" command. - Note that the definition of this macro implies that there exists a - function "setup_arbitrary_frame" in mach-dep.c */ - -#define FRAME_SPECIFICATION_DYADIC - -/* KDB stuff flushed for now. */ -@ - - -1.2 -log -@Don't stop the stack trace until the "next frame pointer" is zero. -@ -text -@d39 11 -@ - - -1.1 -log -@Initial revision -@ -text -@d66 1 -a66 1 -#define STACK_END_ADDR 0xff000000 -d307 3 -d312 4 -@ diff --git a/gdb/RCS/m68k-pinsn.c,v b/gdb/RCS/m68k-pinsn.c,v deleted file mode 100644 index d8c7f84e03..0000000000 --- a/gdb/RCS/m68k-pinsn.c,v +++ /dev/null @@ -1,824 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.03.27.20.19.34; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.20.19.29.33; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Change HPUX_ASM to USG_SGS_ASM since it's really the Sys V -"Software Generation System" that we are fighting here. -@ -text -@/* Print m68k instructions for GDB, the GNU debugger. - Copyright (C) 1986, 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! -*/ - -#include - -#include "defs.h" -#include "param.h" -#include "symtab.h" -#include "opcode.h" - -/* 68k instructions are never longer than this many bytes. */ -#define MAXLEN 22 - -/* Number of elements in the opcode table. */ -#define NOPCODES (sizeof m68k_opcodes / sizeof m68k_opcodes[0]) - -extern char *reg_names[]; -char *fpcr_names[] = { "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr", - "fpiar/fpcr", "fpsr/fpcr", "fpiar-fpcr"}; - -static unsigned char *print_insn_arg (); -static unsigned char *print_indexed (); -static void print_base (); -static int fetch_arg (); - -#define NEXTBYTE(p) (p += 2, ((char *)p)[-1]) - -#define NEXTWORD(p) \ - (p += 2, ((((char *)p)[-2]) << 8) + p[-1]) - -#define NEXTLONG(p) \ - (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1]) - -#define NEXTSINGLE(p) \ - (p += 4, *((float *)(p - 4))) - -#define NEXTDOUBLE(p) \ - (p += 8, *((double *)(p - 8))) - -#define NEXTEXTEND(p) \ - (p += 12, 0.0) /* Need a function to convert from extended to double - precision... */ - -#define NEXTPACKED(p) \ - (p += 12, 0.0) /* Need a function to convert from packed to double - precision. Actually, it's easier to print a - packed number than a double anyway, so maybe - there should be a special case to handle this... */ - -/* Print the m68k instruction at address MEMADDR in debugged memory, - on STREAM. Returns length of the instruction, in bytes. */ - -int -print_insn (memaddr, stream) - CORE_ADDR memaddr; - FILE *stream; -{ - unsigned char buffer[MAXLEN]; - register int i; - register unsigned char *p; - register char *d; - register int bestmask; - int best; - - read_memory (memaddr, buffer, MAXLEN); - - bestmask = 0; - best = -1; - for (i = 0; i < NOPCODES; i++) - { - register unsigned int opcode = m68k_opcodes[i].opcode; - register unsigned int match = m68k_opcodes[i].match; - if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24))) - && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16))) - && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8))) - && ((0xff & buffer[3] & match) == (0xff & opcode))) - { - /* Don't use for printout the variants of divul and divsl - that have the same register number in two places. - The more general variants will match instead. */ - for (d = m68k_opcodes[i].args; *d; d += 2) - if (d[1] == 'D') - break; - - /* Don't use for printout the variants of most floating - point coprocessor instructions which use the same - register number in two places, as above. */ - if (*d == 0) - for (d = m68k_opcodes[i].args; *d; d += 2) - if (d[1] == 't') - break; - - if (*d == 0 && match > bestmask) - { - best = i; - bestmask = match; - } - } - } - - /* Handle undefined instructions. */ - if (best < 0) - { - fprintf (stream, "0%o", (buffer[0] << 8) + buffer[1]); - return 2; - } - - fprintf (stream, "%s", m68k_opcodes[best].name); - - /* Point at first word of argument data, - and at descriptor for first argument. */ - p = buffer + 2; - - /* Why do this this way? -MelloN */ - for (d = m68k_opcodes[best].args; *d; d += 2) - { - if (d[0] == '#') - { - if (d[1] == 'l' && p - buffer < 6) - p = buffer + 6; - else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8' ) - p = buffer + 4; - } - if (d[1] >= '1' && d[1] <= '3' && p - buffer < 4) - p = buffer + 4; - if (d[1] >= '4' && d[1] <= '6' && p - buffer < 6) - p = buffer + 6; - } - - d = m68k_opcodes[best].args; - - if (*d) - fputc (' ', stream); - - while (*d) - { - p = print_insn_arg (d, buffer, p, memaddr + p - buffer, stream); - d += 2; - if (*d && *(d - 2) != 'I' && *d != 'k') - fprintf (stream, ","); - } - return p - buffer; -} - -static unsigned char * -print_insn_arg (d, buffer, p, addr, stream) - char *d; - unsigned char *buffer; - register unsigned char *p; - CORE_ADDR addr; /* PC for this arg to be relative to */ - FILE *stream; -{ - register int val; - register int place = d[1]; - int regno; - register char *regname; - register unsigned char *p1; - register double flval; - int flt_p; - - switch (*d) - { - case 'C': - fprintf (stream, "ccr"); - break; - - case 'S': - fprintf (stream, "sr"); - break; - - case 'U': - fprintf (stream, "usp"); - break; - - case 'J': - { - static struct { char *name; int value; } names[] - = {{"sfc", 0x000}, {"dfc", 0x001}, {"cacr", 0x002}, - {"usp", 0x800}, {"vbr", 0x801}, {"caar", 0x802}, - {"msp", 0x803}, {"isp", 0x804}}; - - val = fetch_arg (buffer, place, 12); - for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--) - if (names[regno].value == val) - { - fprintf (stream, names[regno].name); - break; - } - if (regno < 0) - fprintf (stream, "%d", val); - } - break; - - case 'Q': - val = fetch_arg (buffer, place, 3); - if (val == 0) val = 8; - fprintf (stream, "#%d", val); - break; - - case 'M': - val = fetch_arg (buffer, place, 8); - if (val & 0x80) - val = val - 0x100; - fprintf (stream, "#%d", val); - break; - - case 'T': - val = fetch_arg (buffer, place, 4); - fprintf (stream, "#%d", val); - break; - - case 'D': - fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 3)]); - break; - - case 'A': - fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 3) + 010]); - break; - - case 'R': - fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 4)]); - break; - - case 'F': - fprintf (stream, "fp%d", fetch_arg (buffer, place, 3)); - break; - - case 'O': - val = fetch_arg (buffer, place, 6); - if (val & 0x20) - fprintf (stream, "%s", reg_names [val & 7]); - else - fprintf (stream, "%d", val); - break; - - case '+': - fprintf (stream, "(%s)+", reg_names[fetch_arg (buffer, place, 3) + 8]); - break; - - case '-': - fprintf (stream, "-(%s)", reg_names[fetch_arg (buffer, place, 3) + 8]); - break; - - case 'k': - if (place == 'k') - fprintf (stream, "{%s}", reg_names[fetch_arg (buffer, place, 3)]); - else if (place == 'C') - { - val = fetch_arg (buffer, place, 7); - if ( val > 63 ) /* This is a signed constant. */ - val -= 128; - fprintf (stream, "{#%d}", val); - } - else - error ("Invalid arg format in opcode table: \"%c%c\".", - *d, place); - break; - - case '#': - p1 = buffer + 2; - if (place == 's') - val = fetch_arg (buffer, place, 4); - else if (place == 'C') - val = fetch_arg (buffer, place, 7); - else if (place == '8') - val = fetch_arg (buffer, place, 3); - else if (place == '3') - val = fetch_arg (buffer, place, 8); - else if (place == 'b') - val = NEXTBYTE (p1); - else if (place == 'w') - val = NEXTWORD (p1); - else if (place == 'l') - val = NEXTLONG (p1); - else - error ("Invalid arg format in opcode table: \"%c%c\".", - *d, place); - fprintf (stream, "#%d", val); - break; - - case '^': - if (place == 's') - val = fetch_arg (buffer, place, 4); - else if (place == 'C') - val = fetch_arg (buffer, place, 7); - else if (place == '8') - val = fetch_arg (buffer, place, 3); - else if (place == 'b') - val = NEXTBYTE (p); - else if (place == 'w') - val = NEXTWORD (p); - else if (place == 'l') - val = NEXTLONG (p); - else - error ("Invalid arg format in opcode table: \"%c%c\".", - *d, place); - fprintf (stream, "#%d", val); - break; - - case 'B': - if (place == 'b') - val = NEXTBYTE (p); - else if (place == 'w') - val = NEXTWORD (p); - else if (place == 'l') - val = NEXTLONG (p); - else if (place == 'g') - { - val = ((char *)buffer)[1]; - if (val == 0) - val = NEXTWORD (p); - else if (val == -1) - val = NEXTLONG (p); - } - else if (place == 'c') - { - if (buffer[1] & 0x40) /* If bit six is one, long offset */ - val = NEXTLONG (p); - else - val = NEXTWORD (p); - } - else - error ("Invalid arg format in opcode table: \"%c%c\".", - *d, place); - - print_address (addr + val, stream); - break; - - case 'd': - val = NEXTWORD (p); - fprintf (stream, "%d(%s)", val, reg_names[fetch_arg (buffer, place, 3)]); - break; - - case 's': - fprintf (stream, "%s", fpcr_names[fetch_arg (buffer, place, 3)]); - break; - - case 'I': - val = fetch_arg (buffer, 'd', 3); /* Get coprocessor ID... */ - if (val != 1) /* Unusual coprocessor ID? */ - fprintf (stream, "(cpid=%d) ", val); - if (place == 'i') - p += 2; /* Skip coprocessor extended operands */ - break; - - case '*': - case '~': - case '%': - case ';': - case '@@': - case '!': - case '$': - case '?': - case '/': - case '&': - - if (place == 'd') - { - val = fetch_arg (buffer, 'x', 6); - val = ((val & 7) << 3) + ((val >> 3) & 7); - } - else - val = fetch_arg (buffer, 's', 6); - - /* Get register number assuming address register. */ - regno = (val & 7) + 8; - regname = reg_names[regno]; - switch (val >> 3) - { - case 0: - fprintf (stream, "%s", reg_names[val]); - break; - - case 1: - fprintf (stream, "%s", regname); - break; - - case 2: - fprintf (stream, "(%s)", regname); - break; - - case 3: - fprintf (stream, "(%s)+", regname); - break; - - case 4: - fprintf (stream, "-(%s)", regname); - break; - - case 5: - val = NEXTWORD (p); - fprintf (stream, "%d(%s)", val, regname); - break; - - case 6: - p = print_indexed (regno, p, addr, stream); - break; - - case 7: - switch (val & 7) - { - case 0: - val = NEXTWORD (p); - fprintf (stream, "@@#"); - print_address (val, stream); - break; - - case 1: - val = NEXTLONG (p); - fprintf (stream, "@@#"); - print_address (val, stream); - break; - - case 2: - val = NEXTWORD (p); - print_address (addr + val, stream); - break; - - case 3: - p = print_indexed (-1, p, addr, stream); - break; - - case 4: - flt_p = 1; /* Assume it's a float... */ - switch( place ) - { - case 'b': - val = NEXTBYTE (p); - flt_p = 0; - break; - - case 'w': - val = NEXTWORD (p); - flt_p = 0; - break; - - case 'l': - val = NEXTLONG (p); - flt_p = 0; - break; - - case 'f': - flval = NEXTSINGLE(p); - break; - - case 'F': - flval = NEXTDOUBLE(p); - break; - - case 'x': - flval = NEXTEXTEND(p); - break; - - case 'p': - flval = NEXTPACKED(p); - break; - - default: - error ("Invalid arg format in opcode table: \"%c%c\".", - *d, place); - } - if ( flt_p ) /* Print a float? */ - fprintf (stream, "#%g", flval); - else - fprintf (stream, "#%d", val); - break; - - default: - fprintf (stream, "", val); - } - } - break; - - default: - error ("Invalid arg format in opcode table: \"%c\".", *d); - } - - return (unsigned char *) p; -} - -/* Fetch BITS bits from a position in the instruction specified by CODE. - CODE is a "place to put an argument", or 'x' for a destination - that is a general address (mode and register). - BUFFER contains the instruction. */ - -static int -fetch_arg (buffer, code, bits) - unsigned char *buffer; - char code; - int bits; -{ - register int val; - switch (code) - { - case 's': - val = buffer[1]; - break; - - case 'd': /* Destination, for register or quick. */ - val = (buffer[0] << 8) + buffer[1]; - val >>= 9; - break; - - case 'x': /* Destination, for general arg */ - val = (buffer[0] << 8) + buffer[1]; - val >>= 6; - break; - - case 'k': - val = (buffer[3] >> 4); - break; - - case 'C': - val = buffer[3]; - break; - - case '1': - val = (buffer[2] << 8) + buffer[3]; - val >>= 12; - break; - - case '2': - val = (buffer[2] << 8) + buffer[3]; - val >>= 6; - break; - - case '3': - case 'j': - val = (buffer[2] << 8) + buffer[3]; - break; - - case '4': - val = (buffer[4] << 8) + buffer[5]; - val >>= 12; - break; - - case '5': - val = (buffer[4] << 8) + buffer[5]; - val >>= 6; - break; - - case '6': - val = (buffer[4] << 8) + buffer[5]; - break; - - case '7': - val = (buffer[2] << 8) + buffer[3]; - val >>= 7; - break; - - case '8': - val = (buffer[2] << 8) + buffer[3]; - val >>= 10; - break; - - default: - abort (); - } - - switch (bits) - { - case 3: - return val & 7; - case 4: - return val & 017; - case 5: - return val & 037; - case 6: - return val & 077; - case 7: - return val & 0177; - case 8: - return val & 0377; - case 12: - return val & 07777; - default: - abort (); - } -} - -/* Print an indexed argument. The base register is BASEREG (-1 for pc). - P points to extension word, in buffer. - ADDR is the nominal core address of that extension word. */ - -static unsigned char * -print_indexed (basereg, p, addr, stream) - int basereg; - unsigned char *p; - FILE *stream; - CORE_ADDR addr; -{ - register int word; - static char *scales[] = {"", "*2", "*4", "*8"}; - register int base_disp; - register int outer_disp; - char buf[40]; - - word = NEXTWORD (p); - - /* Generate the text for the index register. - Where this will be output is not yet determined. */ - sprintf (buf, "[%s.%c%s]", - reg_names[(word >> 12) & 0xf], - (word & 0x800) ? 'l' : 'w', - scales[(word >> 9) & 3]); - - /* Handle the 68000 style of indexing. */ - - if ((word & 0x100) == 0) - { - print_base (basereg, - ((word & 0x80) ? word | 0xff00 : word & 0xff) - + ((basereg == -1) ? addr : 0), - stream); - fprintf (stream, "%s", buf); - return p; - } - - /* Handle the generalized kind. */ - /* First, compute the displacement to add to the base register. */ - - if (word & 0200) - basereg = -2; - if (word & 0100) - buf[0] = 0; - base_disp = 0; - switch ((word >> 4) & 3) - { - case 2: - base_disp = NEXTWORD (p); - break; - case 3: - base_disp = NEXTLONG (p); - } - if (basereg == -1) - base_disp += addr; - - /* Handle single-level case (not indirect) */ - - if ((word & 7) == 0) - { - print_base (basereg, base_disp, stream); - fprintf (stream, "%s", buf); - return p; - } - - /* Two level. Compute displacement to add after indirection. */ - - outer_disp = 0; - switch (word & 3) - { - case 2: - outer_disp = NEXTWORD (p); - break; - case 3: - outer_disp = NEXTLONG (p); - } - - fprintf (stream, "%d(", outer_disp); - print_base (basereg, base_disp, stream); - - /* If postindexed, print the closeparen before the index. */ - if (word & 4) - fprintf (stream, ")%s", buf); - /* If preindexed, print the closeparen after the index. */ - else - fprintf (stream, "%s)", buf); - - return p; -} - -/* Print a base register REGNO and displacement DISP, on STREAM. - REGNO = -1 for pc, -2 for none (suppressed). */ - -static void -print_base (regno, disp, stream) - int regno; - int disp; - FILE *stream; -{ - if (regno == -2) - fprintf (stream, "%d", disp); - else if (regno == -1) - fprintf (stream, "0x%x", disp); - else - fprintf (stream, "%d(%s)", disp, reg_names[regno]); -} - -/* This is not part of insn printing, but it is machine-specific, - so this is a convenient place to put it. - - Convert a 68881 extended float to a double. - FROM is the address of the extended float. - Store the double in *TO. */ - -convert_from_68881 (from, to) - char *from; - double *to; -{ -#ifdef USG_SGS_ASM - asm ("mov.l 8(%a6),%a0"); - asm ("mov.l 12(%a6),%a1"); - asm ("fmove.x (%a0),%fp0"); - asm ("fmove.d %fp0,(%a1)"); -#else /* not USG_SGS_ASM */ -#if 0 - asm ("movl a6@@(8),a0"); - asm ("movl a6@@(12),a1"); - asm ("fmovex a0@@,fp0"); - asm ("fmoved fp0,a1@@"); -#else - /* Hand-assemble those insns since some assemblers lose - and some have different syntax. */ - asm (".word 020156"); - asm (".word 8"); - asm (".word 021156"); - asm (".word 12"); - asm (".long 0xf2104800"); - asm (".long 0xf2117400"); -#endif -#endif /* not USG_SGS_ASM */ -} - -/* The converse: convert the double *FROM to an extended float - and store where TO points. */ - -convert_to_68881 (from, to) - double *from; - char *to; -{ -#ifdef USG_SGS_ASM - asm ("mov.l 8(%a6),%a0"); - asm ("mov.l 12(%a6),%a1"); - asm ("fmove.d (%a0),%fp0"); - asm ("fmove.x %fp0,(%a1)"); -#else /* not USG_SGS_ASM */ -#if 0 - asm ("movl a6@@(8),a0"); - asm ("movl a6@@(12),a1"); - asm ("fmoved a0@@,fp0"); - asm ("fmovex fp0,a1@@"); -#else - /* Hand-assemble those insns since some assemblers lose. */ - asm (".word 020156"); - asm (".word 8"); - asm (".word 021156"); - asm (".word 12"); - asm (".long 0xf2105400"); - asm (".long 0xf2116800"); -#endif -#endif /* not USG_SGS_ASM */ -} -@ - - -1.1 -log -@Initial revision -@ -text -@d717 1 -a717 1 -#ifdef HPUX_ASM -d722 1 -a722 1 -#else /* not HPUX_ASM */ -d738 1 -a738 1 -#endif /* not HPUX_ASM */ -d748 1 -a748 1 -#ifdef HPUX_ASM -d753 1 -a753 1 -#else /* not HPUX_ASM */ -d768 1 -a768 1 -#endif /* not HPUX_ASM */ -@ diff --git a/gdb/RCS/main.c,v b/gdb/RCS/main.c,v deleted file mode 100644 index 1e6fafa602..0000000000 --- a/gdb/RCS/main.c,v +++ /dev/null @@ -1,1348 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.03.27.21.15.02; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.27.21.11.51; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Fix up "munch" so it generates a name that doesn't match its own -"grep" conventions. Change main so that it calls the new name, -and also doesn't use the conventions for functions that should NOT -be called by init.c. -@ -text -@/* Top level for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1988 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! -*/ -#include "defs.h" -#include "command.h" -#include "param.h" - -#ifdef USG -#include -#include -#endif - -#include -#include -#include -#include -#include - -#ifdef SET_STACK_LIMIT_HUGE -#include -#include - -int original_stack_limit; -#endif - -/* Version number of GDB, as a string. */ - -extern char *version; - -/* - * Declare all cmd_list_element's - */ - -/* Chain containing all defined commands. */ - -struct cmd_list_element *cmdlist; - -/* Chain containing all defined info subcommands. */ - -struct cmd_list_element *infolist; - -/* Chain containing all defined enable subcommands. */ - -struct cmd_list_element *enablelist; - -/* Chain containing all defined disable subcommands. */ - -struct cmd_list_element *disablelist; - -/* Chain containing all defined delete subcommands. */ - -struct cmd_list_element *deletelist; - -/* Chain containing all defined "enable breakpoint" subcommands. */ - -struct cmd_list_element *enablebreaklist; - -/* Chain containing all defined set subcommands */ - -struct cmd_list_element *setlist; - -/* stdio stream that command input is being read from. */ - -FILE *instream; - -/* Current working directory. */ - -char *current_directory; - -/* The directory name is actually stored here (usually). */ -static char dirbuf[MAXPATHLEN]; - -/* Nonzero if we should refrain from using an X window. */ - -int inhibit_windows = 0; - -/* Function to call before reading a command, if nonzero. - The function receives two args: an input stream, - and a prompt string. */ - -void (*window_hook) (); - -extern int frame_file_full_name; - -void free_command_lines (); -char *gdb_read_line (); -static void init_main (); -static void init_cmd_lists (); -void command_loop (); -static void source_command (); -static void print_gdb_version (); - -/* gdb prints this when reading a command interactively */ -static char *prompt; - -/* Buffer used for reading command lines, and the size - allocated for it so far. */ - -char *line; -int linesize; - -/* This is how `error' returns to command level. */ - -jmp_buf to_top_level; - -void -return_to_top_level () -{ - quit_flag = 0; - immediate_quit = 0; - clear_breakpoint_commands (); - clear_momentary_breakpoints (); - delete_current_display (); - do_cleanups (0); - longjmp (to_top_level, 1); -} - -/* Call FUNC with arg ARG, catching any errors. - If there is no error, return the value returned by FUNC. - If there is an error, return zero after printing ERRSTRING - (which is in addition to the specific error message already printed). */ - -int -catch_errors (func, arg, errstring) - int (*func) (); - int arg; - char *errstring; -{ - jmp_buf saved; - int val; - struct cleanup *saved_cleanup_chain; - - saved_cleanup_chain = save_cleanups (); - - bcopy (to_top_level, saved, sizeof (jmp_buf)); - - if (setjmp (to_top_level) == 0) - val = (*func) (arg); - else - { - fprintf (stderr, "%s\n", errstring); - val = 0; - } - - restore_cleanups (saved_cleanup_chain); - - bcopy (saved, to_top_level, sizeof (jmp_buf)); - return val; -} - -/* Handler for SIGHUP. */ - -static void -disconnect () -{ - kill_inferior_fast (); - signal (SIGHUP, SIG_DFL); - kill (getpid (), SIGHUP); -} - -/* Clean up on error during a "source" command (or execution of a - user-defined command). - Close the file opened by the command - and restore the previous input stream. */ - -static void -source_cleanup (stream) - FILE *stream; -{ - /* Instream may be 0; set to it when executing user-defined command. */ - if (instream) - fclose (instream); - instream = stream; -} - - -int -main (argc, argv, envp) - int argc; - char **argv; - char **envp; -{ - extern void request_quit (); - int count; - int inhibit_gdbinit = 0; - int quiet = 0; - int batch = 0; - register int i; - - quit_flag = 0; - linesize = 100; - line = (char *) xmalloc (linesize); - instream = stdin; - - getwd (dirbuf); - current_directory = dirbuf; - -#ifdef SET_STACK_LIMIT_HUGE - { - struct rlimit rlim; - - /* Set the stack limit huge so that alloca (particularly stringtab - * in dbxread.c) does not fail. */ - getrlimit (RLIMIT_STACK, &rlim); - original_stack_limit = rlim.rlim_cur; - rlim.rlim_cur = rlim.rlim_max; - setrlimit (RLIMIT_STACK, &rlim); - } -#endif /* SET_STACK_LIMIT_HUGE */ - - /* Look for flag arguments. */ - - for (i = 1; i < argc; i++) - { - if (!strcmp (argv[i], "-q") || !strcmp (argv[i], "-quiet")) - quiet = 1; - else if (!strcmp (argv[i], "-nx")) - inhibit_gdbinit = 1; - else if (!strcmp (argv[i], "-nw")) - inhibit_windows = 1; - else if (!strcmp (argv[i], "-batch")) - batch = 1, quiet = 1; - else if (!strcmp (argv[i], "-fullname")) - frame_file_full_name = 1; - else if (argv[i][0] == '-') - i++; - } - - /* Run the init function of each source file */ - - init_cmd_lists (); /* This needs to be done first */ - init_all_files (); - init_main (); /* But that omits this file! Do it now */ - - signal (SIGINT, request_quit); - signal (SIGQUIT, SIG_IGN); - if (signal (SIGHUP, SIG_IGN) != SIG_IGN) - signal (SIGHUP, disconnect); - - if (!quiet) - print_gdb_version (); - - /* Process the command line arguments. */ - - count = 0; - for (i = 1; i < argc; i++) - { - register char *arg = argv[i]; - /* Args starting with - say what to do with the following arg - as a filename. */ - if (arg[0] == '-') - { - extern void exec_file_command (), symbol_file_command (); - extern void core_file_command (), directory_command (); - extern void tty_command (); - - if (!strcmp (arg, "-q") || !strcmp (arg, "-nx") - || !strcmp (arg, "-quiet") || !strcmp (arg, "-batch") - || !strcmp (arg, "-fullname")) - /* Already processed above */ - continue; - - if (++i == argc) - fprintf (stderr, "No argument follows \"%s\".\n", arg); - if (!setjmp (to_top_level)) - { - /* -s foo: get syms from foo. -e foo: execute foo. - -se foo: do both with foo. -c foo: use foo as core dump. */ - if (!strcmp (arg, "-se")) - { - exec_file_command (argv[i], !batch); - symbol_file_command (argv[i], !batch); - } - else if (!strcmp (arg, "-s") || !strcmp (arg, "-symbols")) - symbol_file_command (argv[i], !batch); - else if (!strcmp (arg, "-e") || !strcmp (arg, "-exec")) - exec_file_command (argv[i], !batch); - else if (!strcmp (arg, "-c") || !strcmp (arg, "-core")) - core_file_command (argv[i], !batch); - /* -x foo: execute commands from foo. */ - else if (!strcmp (arg, "-x") || !strcmp (arg, "-command") - || !strcmp (arg, "-commands")) - source_command (argv[i]); - /* -d foo: add directory `foo' to source-file directory - search-list */ - else if (!strcmp (arg, "-d") || !strcmp (arg, "-dir") - || !strcmp (arg, "-directory")) - directory_command (argv[i], 0); - /* -cd FOO: specify current directory as FOO. - GDB remembers the precise string FOO as the dirname. */ - else if (!strcmp (arg, "-cd")) - { - int len = strlen (argv[i]); - current_directory = argv[i]; - if (len > 1 && current_directory[len - 1] == '/') - current_directory = savestring (current_directory, len-1); - chdir (current_directory); - init_source_path (); - } - /* -t /def/ttyp1: use /dev/ttyp1 for inferior I/O. */ - else if (!strcmp (arg, "-t") || !strcmp (arg, "-tty")) - tty_command (argv[i], 0); - else - error ("Unknown command-line switch: \"%s\"\n", arg); - } - } - else - { - /* Args not thus accounted for - are treated as, first, the symbol/executable file - and, second, the core dump file. */ - count++; - if (!setjmp (to_top_level)) - switch (count) - { - case 1: - exec_file_command (arg, !batch); - symbol_file_command (arg, !batch); - break; - - case 2: - core_file_command (arg, !batch); - break; - - case 3: - fprintf (stderr, "Excess command line args ignored. (%s%s)\n", - arg, (i == argc - 1) ? "" : " ..."); - } - } - } - - /* Read init file, if it exists in home directory */ - if (getenv ("HOME")) - { - char *s; - s = (char *) xmalloc (strlen (getenv ("HOME")) + 10); - strcpy (s, getenv ("HOME")); - strcat (s, "/.gdbinit"); - if (!inhibit_gdbinit && access (s, R_OK) == 0) - if (!setjmp (to_top_level)) - source_command (s); - } - - /* Read init file, if it exists in current directory. */ - if (!inhibit_gdbinit && access (".gdbinit", R_OK) == 0) - if (!setjmp (to_top_level)) - source_command (".gdbinit"); - - if (batch) - fatal ("Attempt to read commands from stdin in batch mode."); - - if (!quiet) - printf ("Type \"help\" for a list of commands.\n"); - - /* The command loop. */ - - while (1) - { - if (!setjmp (to_top_level)) - command_loop (); - clearerr (stdin); /* Don't get hung if C-d is typed. */ - } -} - -/* Execute the line P as a command. - Pass FROM_TTY as second argument to the defining function. */ - -void -execute_command (p, from_tty) - char *p; - int from_tty; -{ - register struct cmd_list_element *c; - register struct command_line *cmdlines; - - free_all_values (); - while (*p == ' ' || *p == '\t') p++; - if (*p) - { - c = lookup_cmd (&p, cmdlist, "", 0); - if (c->function == 0) - error ("That is not a command, just a help topic."); - else if (c->class == (int) class_user) - { - struct cleanup *old_chain; - - if (*p) - error ("User-defined commands cannot take arguments."); - cmdlines = (struct command_line *) c->function; - if (cmdlines == (struct command_line *) 0) - /* Null command */ - return; - - /* Set the instream to 0, indicating execution of a - user-defined function. */ - old_chain = make_cleanup (source_cleanup, instream); - instream = (FILE *) 0; - while (cmdlines) - { - execute_command (cmdlines->line, 0); - cmdlines = cmdlines->next; - } - do_cleanups (old_chain); - } - else - /* Pass null arg rather than an empty one. */ - (*c->function) (*p ? p : 0, from_tty); - } -} - -static void -do_nothing () -{ -} - -/* Read commands from `instream' and execute them - until end of file. */ -void -command_loop () -{ - struct cleanup *old_chain; - while (!feof (instream)) - { - if (window_hook && instream == stdin) - (*window_hook) (instream, prompt); - - quit_flag = 0; - old_chain = make_cleanup (do_nothing, 0); - execute_command (gdb_read_line (instream == stdin ? prompt : 0, - instream == stdin), - instream == stdin); - /* Do any commands attached to breakpoint we stopped at. */ - do_breakpoint_commands (); - do_cleanups (old_chain); - } -} - -#ifdef SIGTSTP -static void -stop_sig () -{ - signal (SIGTSTP, SIG_DFL); - sigsetmask (0); - kill (getpid (), SIGTSTP); - signal (SIGTSTP, stop_sig); - printf ("%s", prompt); - fflush (stdout); - - /* Forget about any previous command -- null line now will do nothing. */ - *line = 0; -} -#endif /* SIGTSTP */ - -/* Commands call this if they do not want to be repeated by null lines. */ - -void -dont_repeat () -{ - *line = 0; -} - -/* Read one line from the command input stream `instream' - into the buffer `line' (whose current length is `linesize'). - The buffer is made bigger as necessary. - Returns the address of the start of the line. */ - -char * -gdb_read_line (prompt, repeat) - char *prompt; - int repeat; -{ - register char *p = line; - register char *p1; - register int c; - char *nline; - - /* Control-C quits instantly if typed while in this loop - since it should not wait until the user types a newline. */ - immediate_quit++; -#ifdef SIGTSTP - signal (SIGTSTP, stop_sig); -#endif - - if (prompt) - { - printf (prompt); - fflush (stdout); - } - - while (1) - { - c = fgetc (instream); - if (c == -1 || c == '\n') - break; - /* Ignore backslash-newline; keep adding to the same line. */ - else if (c == '\\') - { - int c1 = fgetc (instream); - if (c1 == '\n') - continue; - else - ungetc (c1, instream); - } - - if (p - line == linesize - 1) - { - linesize *= 2; - nline = (char *) xrealloc (line, linesize); - p += nline - line; - line = nline; - } - *p++ = c; - } - -#ifdef SIGTSTP - signal (SIGTSTP, SIG_DFL); -#endif - immediate_quit--; - - /* If we just got an empty line, and that is supposed - to repeat the previous command, leave the last input unchanged. */ - if (p == line && repeat) - return line; - - /* If line is a comment, clear it out. */ - p1 = line; - while ((c = *p1) == ' ' || c == '\t') p1++; - if (c == '#') - p = line; - - *p = 0; - - return line; -} - -/* Read lines from the input stream - and accumulate them in a chain of struct command_line's - which is then returned. */ - -struct command_line * -read_command_lines () -{ - struct command_line *first = 0; - register struct command_line *next, *tail = 0; - register char *p, *p1; - struct cleanup *old_chain = 0; - - while (1) - { - dont_repeat (); - p = gdb_read_line (0, 1); - /* Remove leading and trailing blanks. */ - while (*p == ' ' || *p == '\t') p++; - p1 = p + strlen (p); - while (p1 != p && (p1[-1] == ' ' || p1[-1] == '\t')) p1--; - - /* Is this "end"? */ - if (p1 - p == 3 && !strncmp (p, "end", 3)) - break; - - /* No => add this line to the chain of command lines. */ - next = (struct command_line *) xmalloc (sizeof (struct command_line)); - next->line = savestring (p, p1 - p); - next->next = 0; - if (tail) - { - tail->next = next; - } - else - { - /* We just read the first line. - From now on, arrange to throw away the lines we have - if we quit or get an error while inside this function. */ - first = next; - old_chain = make_cleanup (free_command_lines, &first); - } - tail = next; - } - - dont_repeat (); - - /* Now we are about to return the chain to our caller, - so freeing it becomes his responsibility. */ - if (first) - discard_cleanups (old_chain); - return first; -} - -/* Free a chain of struct command_line's. */ - -void -free_command_lines (lptr) - struct command_line **lptr; -{ - register struct command_line *l = *lptr; - register struct command_line *next; - - while (l) - { - next = l->next; - free (l->line); - free (l); - l = next; - } -} - -/* Add an element to the list of info subcommands. */ - -void -add_info (name, fun, doc) - char *name; - void (*fun) (); - char *doc; -{ - add_cmd (name, no_class, fun, doc, &infolist); -} - -/* Add an alias to the list of info subcommands. */ - -void -add_info_alias (name, oldname, abbrev_flag) - char *name; - char *oldname; - int abbrev_flag; -{ - add_alias_cmd (name, oldname, 0, abbrev_flag, &infolist); -} - -/* The "info" command is defined as a prefix, with allow_unknown = 0. - Therefore, its own definition is called only for "info" with no args. */ - -static void -info_command () -{ - printf ("\"info\" must be followed by the name of an info command.\n"); - help_list (infolist, "info ", -1, stdout); -} - -/* Add an element to the list of commands. */ - -void -add_com (name, class, fun, doc) - char *name; - int class; - void (*fun) (); - char *doc; -{ - add_cmd (name, class, fun, doc, &cmdlist); -} - -/* Add an alias or abbreviation command to the list of commands. */ - -void -add_com_alias (name, oldname, class, abbrev_flag) - char *name; - char *oldname; - int class; - int abbrev_flag; -{ - add_alias_cmd (name, oldname, class, abbrev_flag, &cmdlist); -} - -void -error_no_arg (why) - char *why; -{ - error ("Argument required (%s).", why); -} - -static void -help_command (command, from_tty) - char *command; - int from_tty; /* Ignored */ -{ - help_cmd (command, stdout); -} - -static void -validate_comname (comname) - char *comname; -{ - register char *p; - - if (comname == 0) - error_no_arg ("name of command to define"); - - p = comname; - while (*p) - { - if (!(*p >= 'A' && *p <= 'Z') - && !(*p >= 'a' && *p <= 'z') - && !(*p >= '0' && *p <= '9') - && *p != '-') - error ("Junk in argument list: \"%s\"", p); - p++; - } -} - -static void -define_command (comname, from_tty) - char *comname; - int from_tty; -{ - register struct command_line *cmds; - register struct cmd_list_element *c; - char *tem = comname; - - validate_comname (comname); - - c = lookup_cmd (&tem, cmdlist, "", -1); - if (c) - { - if (c->class == (int) class_user || c->class == (int) class_alias) - tem = "Redefine command \"%s\"? "; - else - tem = "Really redefine built-in command \"%s\"? "; - if (!query (tem, comname)) - error ("Command \"%s\" not redefined.", comname); - } - - if (from_tty) - { - printf ("Type commands for definition of \"%s\".\n\ -End with a line saying just \"end\".\n", comname); - fflush (stdout); - } - comname = savestring (comname, strlen (comname)); - - cmds = read_command_lines (); - - if (c && c->class == (int) class_user) - free_command_lines (&c->function); - - add_com (comname, class_user, cmds, - (c && c->class == (int) class_user) - ? c->doc : savestring ("User-defined.", 13)); -} - -static void -document_command (comname, from_tty) - char *comname; - int from_tty; -{ - struct command_line *doclines; - register struct cmd_list_element *c; - char *tem = comname; - - validate_comname (comname); - - c = lookup_cmd (&tem, cmdlist, "", 0); - - if (c->class != (int) class_user) - error ("Command \"%s\" is built-in.", comname); - - if (from_tty) - printf ("Type documentation for \"%s\".\n\ -End with a line saying just \"end\".\n", comname); - - doclines = read_command_lines (); - - if (c->doc) free (c->doc); - - { - register struct command_line *cl1; - register int len = 0; - - for (cl1 = doclines; cl1; cl1 = cl1->next) - len += strlen (cl1->line) + 1; - - c->doc = (char *) xmalloc (len + 1); - *c->doc = 0; - - for (cl1 = doclines; cl1; cl1 = cl1->next) - { - strcat (c->doc, cl1->line); - if (cl1->next) - strcat (c->doc, "\n"); - } - } - - free_command_lines (&doclines); -} - -static void -copying_info () -{ - immediate_quit++; - printf (" GDB GENERAL PUBLIC LICENSE\n\ - (Clarified 11 Feb 1988)\n\ -\n\ - Copyright (C) 1988 Richard M. Stallman\n\ - Everyone is permitted to copy and distribute verbatim copies\n\ - of this license, but changing it is not allowed.\n\ - You can also use this wording to make the terms for other programs.\n\ -\n\ - The license agreements of most software companies keep you at the\n\ -mercy of those companies. By contrast, our general public license is\n\ -intended to give everyone the right to share GDB. To make sure that\n\ -you get the rights we want you to have, we need to make restrictions\n\ -that forbid anyone to deny you these rights or to ask you to surrender\n\ -the rights. Hence this license agreement.\n\ -\n\ - Specifically, we want to make sure that you have the right to give\n\ -away copies of GDB, that you receive source code or else can get it\n\ -if you want it, that you can change GDB or use pieces of it in new\n\ -free programs, and that you know you can do these things.\n\ ---Type Return to print more--"); - fflush (stdout); - gdb_read_line (0, 0); - - printf ("\ - To make sure that everyone has such rights, we have to forbid you to\n\ -deprive anyone else of these rights. For example, if you distribute\n\ -copies of GDB, you must give the recipients all the rights that you\n\ -have. You must make sure that they, too, receive or can get the\n\ -source code. And you must tell them their rights.\n\ -\n\ - Also, for our own protection, we must make certain that everyone\n\ -finds out that there is no warranty for GDB. If GDB is modified by\n\ -someone else and passed on, we want its recipients to know that what\n\ -they have is not what we distributed, so that any problems introduced\n\ -by others will not reflect on our reputation.\n\ -\n\ - Therefore we (Richard Stallman and the Free Software Foundation,\n\ -Inc.) make the following terms which say what you must do to be\n\ -allowed to distribute or change GDB.\n\ ---Type Return to print more--"); - fflush (stdout); - gdb_read_line (0, 0); - - printf ("\ - COPYING POLICIES\n\ -\n\ - 1. You may copy and distribute verbatim copies of GDB source code as\n\ -you receive it, in any medium, provided that you conspicuously and\n\ -appropriately publish on each copy a valid copyright notice \"Copyright\n\ -\(C) 1988 Free Software Foundation, Inc.\" (or with whatever year is\n\ -appropriate); keep intact the notices on all files that refer\n\ -to this License Agreement and to the absence of any warranty; and give\n\ -any other recipients of the GDB program a copy of this License\n\ -Agreement along with the program. You may charge a distribution fee\n\ -for the physical act of transferring a copy.\n\ -\n\ - 2. You may modify your copy or copies of GDB or any portion of it,\n\ -and copy and distribute such modifications under the terms of\n\ -Paragraph 1 above, provided that you also do the following:\n\ -\n\ - a) cause the modified files to carry prominent notices stating\n\ - that you changed the files and the date of any change; and\n\ ---Type Return to print more--"); - fflush (stdout); - gdb_read_line (0, 0); - - printf ("\ - b) cause the whole of any work that you distribute or publish,\n\ - that in whole or in part contains or is a derivative of GDB\n\ - or any part thereof, to be licensed to all third parties on terms\n\ - identical to those contained in this License Agreement (except that\n\ - you may choose to grant more extensive warranty protection to some\n\ - or all third parties, at your option).\n\ -\n"); - printf ("\ - c) if the modified program serves as a debugger, cause it\n\ - when started running in the simplest and usual way, to print\n\ - an announcement including a valid copyright notice\n\ - \"Copyright (C) 1988 Free Software Foundation, Inc.\" (or with\n\ - the year that is appropriate), saying that there is no warranty\n\ - (or else, saying that you provide a warranty) and that users may\n\ - redistribute the program under these conditions, and telling the user\n\ - how to view a copy of this License Agreement.\n\ -\n\ - d) You may charge a distribution fee for the physical act of\n\ - transferring a copy, and you may at your option offer warranty\n\ - protection in exchange for a fee.\n\ -\n\ -Mere aggregation of another unrelated program with this program (or its\n\ -derivative) on a volume of a storage or distribution medium does not bring\n\ -the other program under the scope of these terms.\n\ ---Type Return to print more--"); - fflush (stdout); - gdb_read_line (0, 0); - - printf ("\ - 3. You may copy and distribute GDB (or a portion or derivative of it,\n\ -under Paragraph 2) in object code or executable form under the terms of\n\ -Paragraphs 1 and 2 above provided that you also do one of the following:\n\ -\n\ - a) accompany it with the complete corresponding machine-readable\n\ - source code, which must be distributed under the terms of\n\ - Paragraphs 1 and 2 above; or,\n\ -\n\ - b) accompany it with a written offer, valid for at least three\n\ - years, to give any third party free (except for a nominal\n\ - shipping charge) a complete machine-readable copy of the\n\ - corresponding source code, to be distributed under the terms of\n\ - Paragraphs 1 and 2 above; or,\n\n"); - - printf ("\ - c) accompany it with the information you received as to where the\n\ - corresponding source code may be obtained. (This alternative is\n\ - allowed only for noncommercial distribution and only if you\n\ - received the program in object code or executable form alone.)\n\ -\n\ -For an executable file, complete source code means all the source code for\n\ -all modules it contains; but, as a special exception, it need not include\n\ -source code for modules which are standard libraries that accompany the\n\ -operating system on which the executable file runs.\n\ ---Type Return to print more--"); - fflush (stdout); - gdb_read_line (0, 0); - - printf ("\ - 4. You may not copy, sublicense, distribute or transfer GDB\n\ -except as expressly provided under this License Agreement. Any attempt\n\ -otherwise to copy, sublicense, distribute or transfer GDB is void and\n\ -your rights to use the program under this License agreement shall be\n\ -automatically terminated. However, parties who have received computer\n\ -software programs from you with this License Agreement will not have\n\ -their licenses terminated so long as such parties remain in full compliance.\n\ -\n\ -"); - printf ("\ - 5. If you wish to incorporate parts of GDB into other free\n\ -programs whose distribution conditions are different, write to the Free\n\ -Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet\n\ -worked out a simple rule that can be stated here, but we will often permit\n\ -this. We will be guided by the two goals of preserving the free status of\n\ -all derivatives of our free software and of promoting the sharing and reuse\n\ -of software.\n\ -\n\ -In other words, go ahead and share GDB, but don't try to stop\n\ -anyone else from sharing it farther. Help stamp out software hoarding!\n\ -"); - immediate_quit--; -} - -static void -warranty_info () -{ - immediate_quit++; - printf (" NO WARRANTY\n\ -\n\ - BECAUSE GDB IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO\n\ -WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT\n\ -WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,\n\ -RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE GDB \"AS IS\" WITHOUT\n\ -WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT\n\ -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n\ -A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND\n\ -PERFORMANCE OF GDB IS WITH YOU. SHOULD GDB PROVE DEFECTIVE, YOU\n\ -ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n"); - - printf ("\ - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.\n\ -STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY\n\ -WHO MAY MODIFY AND REDISTRIBUTE GDB, BE LIABLE TO\n\ -YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER\n\ -SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR\n\ -INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA\n\ -BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A\n\ -FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GDB, EVEN\n\ -IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR\n\ -ANY CLAIM BY ANY OTHER PARTY.\n"); - immediate_quit--; -} - -static void -print_gdb_version () -{ - printf ("GDB %s, Copyright (C) 1988 Free Software Foundation, Inc.\n\ -There is ABSOLUTELY NO WARRANTY for GDB; type \"info warranty\" for details.\n\ -GDB is free software and you are welcome to distribute copies of it\n\ - under certain conditions; type \"info copying\" to see the conditions.\n", - version); -} - -static void -version_info () -{ - immediate_quit++; - print_gdb_version (); - immediate_quit--; -} - -/* xgdb calls this to reprint the usual GDB prompt. */ - -void -print_prompt () -{ - printf ("%s", prompt); - fflush (stdout); -} - -/* Command to specify a prompt string instead of "(gdb) ". */ - -static void -set_prompt_command (text) - char *text; -{ - char *p, *q; - register int c; - char *new; - - if (text == 0) - error_no_arg ("string to which to set prompt"); - - new = (char *) xmalloc (strlen (text) + 2); - p = text; q = new; - while (c = *p++) - { - if (c == '\\') - { - /* \ at end of argument is used after spaces - so they won't be lost. */ - if (*p == 0) - break; - c = parse_escape (&p); - if (c == 0) - break; /* C loses */ - else if (c > 0) - *q++ = c; - } - else - *q++ = c; - } - if (*(p - 1) != '\\') - *q++ = ' '; - *q++ = '\0'; - new = (char *) xrealloc (new, q - new); - free (prompt); - prompt = new; -} - -static void -quit_command () -{ - if (have_inferior_p ()) - { - if (query ("The program is running. Quit anyway? ")) - { - /* Prevent any warning message from reopen_exec_file, in case - we have a core file that's inconsistent with the exec file. */ - exec_file_command (0, 0); - kill_inferior (); - } - else - error ("Not confirmed."); - } - exit (0); -} - -int -input_from_terminal_p () -{ - return instream == stdin; -} - -static void -pwd_command (arg, from_tty) - char *arg; - int from_tty; -{ - if (arg) error ("The \"pwd\" command does not take an argument: %s", arg); - getwd (dirbuf); - - if (strcmp (dirbuf, current_directory)) - printf ("Working directory %s\n (canonically %s).\n", - current_directory, dirbuf); - else - printf ("Working directory %s.\n", current_directory); -} - -static void -cd_command (dir, from_tty) - char *dir; - int from_tty; -{ - int len; - int change; - - if (dir == 0) - error_no_arg ("new working directory"); - - len = strlen (dir); - dir = savestring (dir, len - (len > 1 && dir[len-1] == '/')); - if (dir[0] == '/') - current_directory = dir; - else - { - current_directory = concat (current_directory, "/", dir); - free (dir); - } - - /* Now simplify any occurrences of `.' and `..' in the pathname. */ - - change = 1; - while (change) - { - char *p; - change = 0; - - for (p = current_directory; *p;) - { - if (!strncmp (p, "/./", 2) - && (p[2] == 0 || p[2] == '/')) - strcpy (p, p + 2); - else if (!strncmp (p, "/..", 3) - && (p[3] == 0 || p[3] == '/') - && p != current_directory) - { - char *q = p; - while (q != current_directory && q[-1] != '/') q--; - if (q != current_directory) - { - strcpy (q-1, p+3); - p = q-1; - } - } - else p++; - } - } - - if (chdir (dir) < 0) - perror_with_name (dir); - - if (from_tty) - pwd_command ((char *) 0, 1); -} - -static void -source_command (file) - char *file; -{ - FILE *stream; - struct cleanup *cleanups; - - if (file == 0) - error_no_arg ("file to read commands from"); - - stream = fopen (file, "r"); - if (stream == 0) - perror_with_name (file); - - cleanups = make_cleanup (source_cleanup, instream); - - instream = stream; - - command_loop (); - - do_cleanups (cleanups); -} - -static void -echo_command (text) - char *text; -{ - char *p = text; - register int c; - - if (text) - while (c = *p++) - { - if (c == '\\') - { - /* \ at end of argument is used after spaces - so they won't be lost. */ - if (*p == 0) - return; - - c = parse_escape (&p); - if (c >= 0) - fputc (c, stdout); - } - else - fputc (c, stdout); - } -} - -static void -dump_me_command () -{ - if (query ("Should GDB dump core? ")) - { - signal (SIGQUIT, SIG_DFL); - kill (getpid (), SIGQUIT); - } -} - -static void -init_cmd_lists () -{ - cmdlist = (struct cmd_list_element *) 0; - infolist = (struct cmd_list_element *) 0; - enablelist = (struct cmd_list_element *) 0; - disablelist = (struct cmd_list_element *) 0; - deletelist = (struct cmd_list_element *) 0; - enablebreaklist = (struct cmd_list_element *) 0; - setlist = (struct cmd_list_element *) 0; -} - -static void -init_main () -{ - prompt = savestring ("(gdb) ", 6); - - /* Define the classes of commands. - They will appear in the help list in the reverse of this order. */ - - add_cmd ("obscure", class_obscure, 0, "Obscure features.", &cmdlist); - add_cmd ("alias", class_alias, 0, "Aliases of other commands.", &cmdlist); - add_cmd ("user", class_user, 0, "User-defined commands.\n\ -The commands in this class are those defined by the user.\n\ -Use the \"define\" command to define a command.", &cmdlist); - add_cmd ("support", class_support, 0, "Support facilities.", &cmdlist); - add_cmd ("status", class_info, 0, "Status inquiries.", &cmdlist); - add_cmd ("files", class_files, 0, "Specifying and examining files.", &cmdlist); - add_cmd ("breakpoints", class_breakpoint, 0, "Making program stop at certain points.", &cmdlist); - add_cmd ("data", class_vars, 0, "Examining data.", &cmdlist); - add_cmd ("stack", class_stack, 0, "Examining the stack.\n\ -The stack is made up of stack frames. Gdb assigns numbers to stack frames\n\ -counting from zero for the innermost (currently executing) frame.\n\n\ -At any time gdb identifies one frame as the \"selected\" frame.\n\ -Variable lookups are done with respect to the selected frame.\n\ -When the program being debugged stops, gdb selects the innermost frame.\n\ -The commands below can be used to select other frames by number or address.", - &cmdlist); - add_cmd ("running", class_run, 0, "Running the program.", &cmdlist); - - add_com ("pwd", class_files, pwd_command, - "Print working directory. This is used for your program as well."); - add_com ("cd", class_files, cd_command, - "Set working directory to DIR for debugger and program being debugged.\n\ -The change does not take effect for the program being debugged\n\ -until the next time it is started."); - - add_cmd ("prompt", class_support, set_prompt_command, - "Change gdb's prompt from the default of \"(gdb)\"", - &setlist); - add_com ("echo", class_support, echo_command, - "Print a constant string. Give string as argument.\n\ -C escape sequences may be used in the argument.\n\ -No newline is added at the end of the argument;\n\ -use \"\\n\" if you want a newline to be printed.\n\ -Since leading and trailing whitespace are ignored in command arguments,\n\ -if you want to print some you must use \"\\\" before leading whitespace\n\ -to be printed or after trailing whitespace."); - add_com ("document", class_support, document_command, - "Document a user-defined command.\n\ -Give command name as argument. Give documentation on following lines.\n\ -End with a line of just \"end\"."); - add_com ("define", class_support, define_command, - "Define a new command name. Command name is argument.\n\ -Definition appears on following lines, one command per line.\n\ -End with a line of just \"end\".\n\ -Use the \"document\" command to give documentation for the new command.\n\ -Commands defined in this way do not take arguments."); - - add_com ("source", class_support, source_command, - "Read commands from a file named FILE.\n\ -Note that the file \".gdbinit\" is read automatically in this way\n\ -when gdb is started."); - add_com ("quit", class_support, quit_command, "Exit gdb."); - add_com ("help", class_support, help_command, "Print list of commands."); - add_com_alias ("q", "quit", class_support, 1); - add_com_alias ("h", "help", class_support, 1); - - add_com ("dump-me", class_obscure, dump_me_command, - "Get fatal error; make debugger dump its core."); - - add_prefix_cmd ("info", class_info, info_command, - "Generic command for printing status.", - &infolist, "info ", 0, &cmdlist); - add_com_alias ("i", "info", class_info, 1); - - add_info ("copying", copying_info, "Conditions for redistributing copies of GDB."); - add_info ("warranty", warranty_info, "Various kinds of warranty you do not have."); - add_info ("version", version_info, "Report what version of GDB this is."); -} -@ - - -1.1 -log -@Initial revision -@ -text -@d103 2 -a104 2 -static void initialize_main (); -static void initialize_cmd_lists (); -d247 3 -a249 3 - initialize_cmd_lists (); /* This needs to be done first */ - initialize_all_files (); - initialize_main (); /* But that omits this file! Do it now */ -d1206 1 -a1206 1 -initialize_cmd_lists () -d1218 1 -a1218 1 -initialize_main () -@ diff --git a/gdb/RCS/munch,v b/gdb/RCS/munch,v deleted file mode 100755 index bac6946458..0000000000 --- a/gdb/RCS/munch,v +++ /dev/null @@ -1,75 +0,0 @@ -head 1.3; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.3 -date 89.03.27.21.15.45; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.03.27.20.18.28; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.20.18.58.17; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.3 -log -@Fix up "munch" so it generates a name that doesn't match its own -"grep" conventions. Change main so that it calls the new name, -and also doesn't use the conventions for functions that should NOT -be called by init.c. -@ -text -@#! /bin/sh - -# create an initialization procedure from a list of .o files -# Look in object files, find symbols including the string _initialize_, -# and call each one as a function. - -echo '/* Do not modify this file. It is created automatically by "munch". */' -echo 'void init_all_files () {' - -nm $* | egrep '_initialize_' | \ - sed -e 's/^.*\(initialize_[a-zA-Z_0-9]*\).*$/ _\1 ();/' | \ - sort -u - -echo '}' -@ - - -1.2 -log -@Generic change: make it not care much about the output format of "nm". -Now as long as _initialize_foo is not touching any other -symbol or alphanumeric, we'll find it and use it. -@ -text -@d8 1 -a8 1 -echo 'void initialize_all_files () {' -@ - - -1.1 -log -@Initial revision -@ -text -@d4 2 -d10 3 -a12 1 -nm -p $* | egrep 'T *__?initialize_' | sed -e 's/^.*T *_*\(.*\)/ _\1 ();/' -@ diff --git a/gdb/RCS/printcmd.c,v b/gdb/RCS/printcmd.c,v deleted file mode 100644 index 2ab3acc8d7..0000000000 --- a/gdb/RCS/printcmd.c,v +++ /dev/null @@ -1,1707 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.04.26.00.54.22; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.04.25.15.38.49; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@(1) Depend on XXX_BIG_ENDIAN rather than testing gdb's object code. -(2) Print to the STREAM parameter, not to stdout. -(3) Use is_nan with new arguments. -(4) Use unpack_double with new args, and deal with invalid results. -(5) Don't print history numbers in the "print" command for things -that weren't recorded in history (because they were invalid values). -@ -text -@/* Print values for GNU debugger GDB. - Copyright (C) 1986, 1987, 1988 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! -*/ - -#include -#include "defs.h" -#include "param.h" -#include "frame.h" -#include "symtab.h" -#include "value.h" -#include "expression.h" - -struct format_data -{ - int count; - char format; - char size; -}; - -/* Last specified output format. */ - -static char last_format = 'x'; - -/* Last specified examination size. 'b', 'h', 'w' or `q'. */ - -static char last_size = 'w'; - -/* Default address to examine next. */ - -static CORE_ADDR next_address; - -/* Last address examined. */ - -static CORE_ADDR last_examine_address; - -/* Contents of last address examined. - This is not valid past the end of the `x' command! */ - -static value last_examine_value; - -/* Number of auto-display expression currently being displayed. - So that we can deleted it if we get an error or a signal within it. - -1 when not doing one. */ - -int current_display_number; - -static void do_one_display (); - -void do_displays (); -void print_address (); -void print_scalar_formatted (); - - -/* Decode a format specification. *STRING_PTR should point to it. - OFORMAT and OSIZE are used as defaults for the format and size - if none are given in the format specification. - The structure returned describes all the data - found in the specification. In addition, *STRING_PTR is advanced - past the specification and past all whitespace following it. */ - -struct format_data -decode_format (string_ptr, oformat, osize) - char **string_ptr; - char oformat; - char osize; -{ - struct format_data val; - register char *p = *string_ptr; - - val.format = oformat; - val.size = osize; - val.count = 1; - - if (*p >= '0' && *p <= '9') - val.count = atoi (p); - while (*p >= '0' && *p <= '9') p++; - - /* Now process size or format letters that follow. */ - - while (1) - { - if (*p == 'b' || *p == 'h' || *p == 'w' || *p == 'g') - val.size = *p++; -#ifdef LONG_LONG - else if (*p == 'l') - { - val.size = 'g'; - p++; - } -#endif - else if (*p >= 'a' && *p <= 'z') - val.format = *p++; - else - break; - } - -#ifndef LONG_LONG - /* Make sure 'g' size is not used on integer types. - Well, actually, we can handle hex. */ - if (val.size == 'g' && val.format != 'f' && val.format != 'x') - val.size = 'w'; -#endif - - while (*p == ' ' || *p == '\t') p++; - *string_ptr = p; - - return val; -} - -/* Print value VAL on stdout according to FORMAT, a letter or 0. - Do not end with a newline. - 0 means print VAL according to its own type. - SIZE is the letter for the size of datum being printed. - This is used to pad hex numbers so they line up. */ - -static void -print_formatted (val, format, size) - register value val; - register char format; - char size; -{ - int len = TYPE_LENGTH (VALUE_TYPE (val)); - - if (VALUE_LVAL (val) == lval_memory) - next_address = VALUE_ADDRESS (val) + len; - - switch (format) - { - case 's': - next_address = VALUE_ADDRESS (val) - + value_print (value_addr (val), stdout, 0); - break; - - case 'i': - next_address = VALUE_ADDRESS (val) - + print_insn (VALUE_ADDRESS (val), stdout); - break; - - default: - if (format == 0 - || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_ARRAY - || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_STRUCT - || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_UNION - || VALUE_REPEATED (val)) - value_print (val, stdout, format); - else - print_scalar_formatted (VALUE_CONTENTS (val), VALUE_TYPE (val), - format, size, stdout); - } -} - -/* Print a scalar of data of type TYPE, pointed to in GDB by VALADDR, - according to letters FORMAT and SIZE on STREAM. - FORMAT may not be zero. Formats s and i are not supported at this level. - - This is how the elements of an array or structure are printed - with a format. */ - -void -print_scalar_formatted (valaddr, type, format, size, stream) - char *valaddr; - struct type *type; - char format; - int size; - FILE *stream; -{ - LONGEST val_long; - int len = TYPE_LENGTH (type); - - if (size == 'g' && sizeof (LONGEST) < 8 - && format == 'x') - { - /* ok, we're going to have to get fancy here. Assumption: a - long is four bytes. */ - unsigned long v1, v2, tmp; - - v1 = unpack_long (builtin_type_long, valaddr); - v2 = unpack_long (builtin_type_long, valaddr + 4); - -#ifdef BYTES_BIG_ENDIAN -#else - /* Little endian -- swap the two for printing */ - tmp = v1; - v1 = v2; - v2 = tmp; -#endif - - switch (format) - { - case 'x': - fprintf (stream, "0x%08x%08x", v1, v2); - break; - default: - error ("Output size \"g\" unimplemented for format \"%c\".", - format); - } - return; - } - - val_long = unpack_long (type, valaddr); - - /* If value is unsigned, truncate it in case negative. */ - if (format != 'd') - { - if (len == sizeof (char)) - val_long &= (1 << 8 * sizeof(char)) - 1; - else if (len == sizeof (short)) - val_long &= (1 << 8 * sizeof(short)) - 1; - else if (len == sizeof (long)) - val_long &= (unsigned long) - 1; - } - - switch (format) - { - case 'x': -#ifdef LONG_LONG - if (!size) - size = (len < sizeof (long long) ? 'w' : 'g'); - switch (size) - { - case 'b': - fprintf (stream, "0x%02llx", val_long); - break; - case 'h': - fprintf (stream, "0x%04llx", val_long); - break; - case 0: /* no size specified, like in print */ - case 'w': - fprintf (stream, "0x%08llx", val_long); - break; - case 'g': - fprintf (stream, "0x%16llx", val_long); - break; - default: - error ("Undefined output size \"%c\".", size); - } -#else - switch (size) - { - case 'b': - fprintf (stream, "0x%02x", val_long); - break; - case 'h': - fprintf (stream, "0x%04x", val_long); - break; - case 0: /* no size specified, like in print */ - case 'w': - fprintf (stream, "0x%08x", val_long); - break; - case 'g': - fprintf (stream, "0x%16x", val_long); - break; - default: - error ("Undefined output size \"%c\".", size); - } -#endif /* not LONG_LONG */ - break; - - case 'd': -#ifdef LONG_LONG - fprintf (stream, "%lld", val_long); -#else - fprintf (stream, "%d", val_long); -#endif - break; - - case 'u': -#ifdef LONG_LONG - fprintf (stream, "%llu", val_long); -#else - fprintf (stream, "%u", val_long); -#endif - break; - - case 'o': - if (val_long) -#ifdef LONG_LONG - fprintf (stream, "0%llo", val_long); -#else - fprintf (stream, "0%o", val_long); -#endif - else - fprintf (stream, "0"); - break; - - case 'a': - print_address ((CORE_ADDR) val_long, stream); - break; - - case 'c': - value_print (value_from_long (builtin_type_char, val_long), stream, 0); - break; - - case 'f': - if (len == sizeof (float)) - type = builtin_type_float; - else if (len == sizeof (double)) - type = builtin_type_double; - else abort(); - -#ifdef IEEE_FLOAT - if (is_nan (valaddr, len)) - { - fprintf (stream, "NaN"); - break; - } -#endif - { - double doub; - int inv; - - doub = unpack_double (type, valaddr, &inv); - if (inv) - fprintf (stream, "Invalid float value"); - else - fprintf (stream, len > 4? "%.16g": "%.6g", doub); - } - break; - - case 0: - abort (); - - default: - error ("Undefined output format \"%c\".", format); - } -} - -/* Specify default address for `x' command. - `info lines' uses this. */ - -void -set_next_address (addr) - CORE_ADDR addr; -{ - next_address = addr; - - /* Make address available to the user as $_. */ - set_internalvar (lookup_internalvar ("_"), - value_from_long (builtin_type_int, (LONGEST) addr)); -} - -/* Print address ADDR symbolically on STREAM. - First print it as a number. Then perhaps print - after the number. */ - -void -print_address (addr, stream) - CORE_ADDR addr; - FILE *stream; -{ - register int i; - struct symbol *fs; - char *name; - int name_location; - - fprintf (stream, "0x%x", addr); - - fs = find_pc_function (addr); - - if (!fs) - { - i = find_pc_misc_function (addr); - - if (i < 0) return; /* If nothing comes through, don't - print anything symbolic */ - - name = misc_function_vector[i].name; - name_location = misc_function_vector[i].address; - } - else - { - name = fs->name; - name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (fs)); - } - - if (addr - name_location) - fprintf (stream, " <%s+%d>", - name, - addr - name_location); - else - fprintf (stream, " <%s>", name); -} - -/* Examine data at address ADDR in format FMT. - Fetch it from memory and print on stdout. */ - -static void -do_examine (fmt, addr) - struct format_data fmt; - CORE_ADDR addr; -{ - register char format = 0; - register char size; - register int count = 1; - struct type *val_type; - register int i; - register int maxelts; - - format = fmt.format; - size = fmt.size; - count = fmt.count; - next_address = addr; - - /* String or instruction format implies fetch single bytes - regardless of the specified size. */ - if (format == 's' || format == 'i') - size = 'b'; - - if (size == 'b') - val_type = builtin_type_char; - else if (size == 'h') - val_type = builtin_type_short; - else if (size == 'w') - val_type = builtin_type_long; - else if (size == 'g') -#ifndef LONG_LONG - val_type = builtin_type_double; -#else - val_type = builtin_type_long_long; -#endif - - maxelts = 8; - if (size == 'w') - maxelts = 4; - if (size == 'g') - maxelts = 2; - if (format == 's' || format == 'i') - maxelts = 1; - - /* Print as many objects as specified in COUNT, at most maxelts per line, - with the address of the next one at the start of each line. */ - - while (count > 0) - { - print_address (next_address, stdout); - fputc (':', stdout); - for (i = maxelts; - i > 0 && count > 0; - i--, count--) - { - fputc ('\t', stdout); - /* Note that print_formatted sets next_address for the next - object. */ - last_examine_address = next_address; - last_examine_value = value_at (val_type, next_address); - print_formatted (last_examine_value, format, size); - } - fputc ('\n', stdout); - fflush (stdout); - } -} - -static void -validate_format (fmt, cmdname) - struct format_data fmt; - char *cmdname; -{ - if (fmt.size != 0) - error ("Size letters are meaningless in \"%s\" command.", cmdname); - if (fmt.count != 1) - error ("Item count other than 1 is meaningless in \"%s\" command.", - cmdname); - if (fmt.format == 'i' || fmt.format == 's') - error ("Format letter \"%c\" is meaningless in \"%s\" command.", - fmt.format, cmdname); -} - -static void -print_command (exp) - char *exp; -{ - struct expression *expr; - register struct cleanup *old_chain = 0; - register char format = 0; - register value val; - struct format_data fmt; - int histindex; - int cleanup = 0; - - if (exp && *exp == '/') - { - exp++; - fmt = decode_format (&exp, last_format, 0); - validate_format (fmt, "print"); - last_format = format = fmt.format; - } - - if (exp && *exp) - { - expr = parse_c_expression (exp); - old_chain = make_cleanup (free_current_contents, &expr); - cleanup = 1; - val = evaluate_expression (expr); - } - else - val = access_value_history (0); - - histindex = record_latest_value (val); - if (histindex >= 0) printf ("$%d = ", histindex); - - print_formatted (val, format, fmt.size); - printf ("\n"); - - if (cleanup) - do_cleanups (old_chain); -} - -static void -output_command (exp) - char *exp; -{ - struct expression *expr; - register struct cleanup *old_chain; - register char format = 0; - register value val; - struct format_data fmt; - - if (exp && *exp == '/') - { - exp++; - fmt = decode_format (&exp, 0, 0); - validate_format (fmt, "print"); - format = fmt.format; - } - - expr = parse_c_expression (exp); - old_chain = make_cleanup (free_current_contents, &expr); - - val = evaluate_expression (expr); - - print_formatted (val, format, fmt.size); - - do_cleanups (old_chain); -} - -static void -set_command (exp) - char *exp; -{ - struct expression *expr = parse_c_expression (exp); - register struct cleanup *old_chain - = make_cleanup (free_current_contents, &expr); - evaluate_expression (expr); - do_cleanups (old_chain); -} - -static void -address_info (exp) - char *exp; -{ - register struct symbol *sym; - register CORE_ADDR val; - int is_a_field_of_this; /* C++: lookup_symbol sets this to nonzero - if exp is a field of `this'. */ - - if (exp == 0) - error ("Argument required."); - - sym = lookup_symbol (exp, get_selected_block (), VAR_NAMESPACE, - &is_a_field_of_this); - if (sym == 0) - { - register int i; - - if (is_a_field_of_this) - { - printf("Symbol \"%s\" is a field of the local class variable `this'\n", exp); - return; - } - - for (i = 0; i < misc_function_count; i++) - if (!strcmp (misc_function_vector[i].name, exp)) - break; - - if (i < misc_function_count) - printf ("Symbol \"%s\" is at 0x%x in a file compiled without -g.\n", - exp, misc_function_vector[i].address); - else - error ("No symbol \"%s\" in current context.", exp); - return; - } - - printf ("Symbol \"%s\" is ", SYMBOL_NAME (sym)); - val = SYMBOL_VALUE (sym); - - switch (SYMBOL_CLASS (sym)) - { - case LOC_CONST: - case LOC_CONST_BYTES: - printf ("constant"); - break; - - case LOC_LABEL: - printf ("a label at address 0x%x", val); - break; - - case LOC_REGISTER: - printf ("a variable in register %s", reg_names[val]); - break; - - case LOC_STATIC: - printf ("static at address 0x%x", val); - break; - - case LOC_REGPARM: - printf ("an argument in register %s", reg_names[val]); - break; - - case LOC_ARG: - printf ("an argument at offset %d", val); - break; - - case LOC_LOCAL: - printf ("a local variable at frame offset %d", val); - break; - - case LOC_TYPEDEF: - printf ("a typedef"); - break; - - case LOC_BLOCK: - printf ("a function at address 0x%x", - BLOCK_START (SYMBOL_BLOCK_VALUE (sym))); - break; - } - printf (".\n"); -} - -static void -x_command (exp, from_tty) - char *exp; - int from_tty; -{ - struct expression *expr; - struct format_data fmt; - struct cleanup *old_chain; - - fmt.format = last_format; - fmt.size = last_size; - fmt.count = 1; - - if (exp && *exp == '/') - { - exp++; - fmt = decode_format (&exp, last_format, last_size); - last_size = fmt.size; - last_format = fmt.format; - } - - /* If we have an expression, evaluate it and use it as the address. */ - - if (exp != 0 && *exp != 0) - { - expr = parse_c_expression (exp); - /* Cause expression not to be there any more - if this command is repeated with Newline. - But don't clobber a user-defined command's definition. */ - if (from_tty) - *exp = 0; - old_chain = make_cleanup (free_current_contents, &expr); - next_address = (CORE_ADDR) value_as_long (evaluate_expression (expr)); - do_cleanups (old_chain); - } - - do_examine (fmt, next_address); - - /* Set a couple of internal variables if appropriate. */ - if (last_examine_value) - { - /* Make last address examined available to the user as $_. */ - set_internalvar (lookup_internalvar ("_"), - value_from_long (builtin_type_int, - (LONGEST) last_examine_address)); - - /* Make contents of last address examined available to the user as $__.*/ - set_internalvar (lookup_internalvar ("__"), last_examine_value); - } -} - -/* Commands for printing types of things. */ - -static void -whatis_command (exp) - char *exp; -{ - struct expression *expr; - register value val; - register struct cleanup *old_chain; - - if (exp) - { - expr = parse_c_expression (exp); - old_chain = make_cleanup (free_current_contents, &expr); - val = evaluate_type (expr); - } - else - val = access_value_history (0); - - printf ("type = "); - type_print (VALUE_TYPE (val), "", stdout, 1); - printf ("\n"); - - if (exp) - do_cleanups (old_chain); -} - -static void -ptype_command (typename) - char *typename; -{ - register char *p = typename; - register int len; - extern struct block *get_current_block (); - register struct block *b - = (have_inferior_p () || have_core_file_p ()) ? get_current_block () : 0; - register struct type *type; - - if (typename == 0) - error_no_arg ("type name"); - - while (*p && *p != ' ' && *p != '\t') p++; - len = p - typename; - while (*p == ' ' || *p == '\t') p++; - - if (len == 6 && !strncmp (typename, "struct", 6)) - type = lookup_struct (p, b); - else if (len == 5 && !strncmp (typename, "union", 5)) - type = lookup_union (p, b); - else if (len == 4 && !strncmp (typename, "enum", 4)) - type = lookup_enum (p, b); - else - { - type = lookup_typename (typename, b, 1); - if (type == 0) - { - register struct symbol *sym - = lookup_symbol (typename, b, STRUCT_NAMESPACE, 0); - if (sym == 0) - error ("No type named %s.", typename); - printf ("No type named %s, but there is a ", - typename); - switch (TYPE_CODE (SYMBOL_TYPE (sym))) - { - case TYPE_CODE_STRUCT: - printf ("struct"); - break; - - case TYPE_CODE_UNION: - printf ("union"); - break; - - case TYPE_CODE_ENUM: - printf ("enum"); - } - printf (" %s. Type \"help ptype\".\n", typename); - type = SYMBOL_TYPE (sym); - } - } - - type_print (type, "", stdout, 1); - printf ("\n"); -} - -enum display_status {disabled, enabled}; - -struct display -{ - /* Chain link to next auto-display item. */ - struct display *next; - /* Expression to be evaluated and displayed. */ - struct expression *exp; - /* Item number of this auto-display item. */ - int number; - /* Display format specified. */ - struct format_data format; - /* Innermost block required by this expression when evaluated */ - struct block *block; - /* Status of this display (enabled or disabled) */ - enum display_status status; -}; - -/* Chain of expressions whose values should be displayed - automatically each time the program stops. */ - -static struct display *display_chain; - -static int display_number; - -/* Add an expression to the auto-display chain. - Specify the expression. */ - -static void -display_command (exp, from_tty) - char *exp; - int from_tty; -{ - struct format_data fmt; - register struct expression *expr; - register struct display *new; - extern struct block *innermost_block; - - if (exp == 0) - { - do_displays (); - return; - } - - if (*exp == '/') - { - exp++; - fmt = decode_format (&exp, 0, 0); - if (fmt.size && fmt.format == 0) - fmt.format = 'x'; - if (fmt.format == 'i' || fmt.format == 's') - fmt.size = 'b'; - } - else - { - fmt.format = 0; - fmt.size = 0; - fmt.count = 0; - } - - innermost_block = 0; - expr = parse_c_expression (exp); - - new = (struct display *) xmalloc (sizeof (struct display)); - - new->exp = expr; - new->block = innermost_block; - new->next = display_chain; - new->number = ++display_number; - new->format = fmt; - new->status = enabled; - display_chain = new; - - if (from_tty && have_inferior_p ()) - do_one_display (new); - - dont_repeat (); -} - -static void -free_display (d) - struct display *d; -{ - free (d->exp); - free (d); -} - -/* Clear out the display_chain. - Done when new symtabs are loaded, since this invalidates - the types stored in many expressions. */ - -void -clear_displays () -{ - register struct display *d; - - while (d = display_chain) - { - free (d->exp); - display_chain = d->next; - free (d); - } -} - -/* Delete the auto-display number NUM. */ - -void -delete_display (num) - int num; -{ - register struct display *d1, *d; - - if (!display_chain) - error ("No display number %d.", num); - - if (display_chain->number == num) - { - d1 = display_chain; - display_chain = d1->next; - free_display (d1); - } - else - for (d = display_chain; ; d = d->next) - { - if (d->next == 0) - error ("No display number %d.", num); - if (d->next->number == num) - { - d1 = d->next; - d->next = d1->next; - free_display (d1); - break; - } - } -} - -/* Delete some values from the auto-display chain. - Specify the element numbers. */ - -static void -undisplay_command (args) - char *args; -{ - register char *p = args; - register char *p1; - register int num; - register struct display *d, *d1; - - if (args == 0) - { - if (query ("Delete all auto-display expressions? ")) - clear_displays (); - dont_repeat (); - return; - } - - while (*p) - { - p1 = p; - while (*p1 >= '0' && *p1 <= '9') p1++; - if (*p1 && *p1 != ' ' && *p1 != '\t') - error ("Arguments must be display numbers."); - - num = atoi (p); - - delete_display (num); - - p = p1; - while (*p == ' ' || *p == '\t') p++; - } - dont_repeat (); -} - -/* Display a single auto-display. - Do nothing if the display cannot be printed in the current context, - or if the display is disabled. */ - -static void -do_one_display (d) - struct display *d; -{ - int within_current_scope; - - if (d->status == disabled) - return; - - if (d->block) - within_current_scope = contained_in (get_selected_block (), d->block); - else - within_current_scope = 1; - if (!within_current_scope) - return; - - current_display_number = d->number; - - printf ("%d: ", d->number); - if (d->format.size) - { - printf ("x/"); - if (d->format.count != 1) - printf ("%d", d->format.count); - printf ("%c", d->format.format); - if (d->format.format != 'i' && d->format.format != 's') - printf ("%c", d->format.size); - printf (" "); - print_expression (d->exp, stdout); - if (d->format.count != 1) - printf ("\n"); - else - printf (" "); - do_examine (d->format, - (CORE_ADDR) value_as_long (evaluate_expression (d->exp))); - - } - else - { - if (d->format.format) - printf ("/%c ", d->format.format); - print_expression (d->exp, stdout); - printf (" = "); - print_formatted (evaluate_expression (d->exp), - d->format.format, d->format.size); - printf ("\n"); - } - - fflush (stdout); - current_display_number = -1; -} - -/* Display all of the values on the auto-display chain which can be - evaluated in the current scope. */ - -void -do_displays () -{ - register struct display *d; - - for (d = display_chain; d; d = d->next) - do_one_display (d); -} - -/* Delete the auto-display which we were in the process of displaying. - This is done when there is an error or a signal. */ - -void -delete_current_display () -{ - if (current_display_number >= 0) - { - delete_display (current_display_number); - fprintf (stderr, "Deleting display %d to avoid infinite recursion.\n", - current_display_number); - } - current_display_number = -1; -} - -static void -display_info () -{ - register struct display *d; - - if (!display_chain) - printf ("There are no auto-display expressions now.\n"); - else - printf ("Auto-display expressions now in effect:\n\ -Num Enb Expression\n"); - - for (d = display_chain; d; d = d->next) - { - printf ("%d: %c ", d->number, "ny"[(int)d->status]); - if (d->format.size) - printf ("/%d%c%c ", d->format.count, d->format.size, - d->format.format); - else if (d->format.format) - printf ("/%c ", d->format.format); - print_expression (d->exp, stdout); - if (d->block && !contained_in (get_selected_block (), d->block)) - printf (" (cannot be evaluated in the current context)"); - printf ("\n"); - fflush (stdout); - } -} - -void -enable_display (args) - char *args; -{ - register char *p = args; - register char *p1; - register int num; - register struct display *d; - - if (p == 0) - { - for (d = display_chain; d; d->next) - d->status = enabled; - } - else - while (*p) - { - p1 = p; - while (*p1 >= '0' && *p1 <= '9') - p1++; - if (*p1 && *p1 != ' ' && *p1 != '\t') - error ("Arguments must be display numbers."); - - num = atoi (p); - - for (d = display_chain; d; d = d->next) - if (d->number == num) - { - d->status = enabled; - goto win; - } - printf ("No display number %d.\n", num); - win: - p = p1; - while (*p == ' ' || *p == '\t') - p++; - } -} - -void -disable_display (args) - char *args; -{ - register char *p = args; - register char *p1; - register int num; - register struct display *d; - - if (p == 0) - { - for (d = display_chain; d; d->next) - d->status = disabled; - } - else - while (*p) - { - p1 = p; - while (*p1 >= '0' && *p1 <= '9') - p1++; - if (*p1 && *p1 != ' ' && *p1 != '\t') - error ("Arguments must be display numbers."); - - num = atoi (p); - - for (d = display_chain; d; d = d->next) - if (d->number == num) - { - d->status = disabled; - goto win; - } - printf ("No display number %d.\n", num); - win: - p = p1; - while (*p == ' ' || *p == '\t') - p++; - } -} - - -/* Print the value in stack frame FRAME of a variable - specified by a struct symbol. */ - -void -print_variable_value (var, frame, stream) - struct symbol *var; - CORE_ADDR frame; - FILE *stream; -{ - value val = read_var_value (var, frame); - value_print (val, stream, 0); -} - -/* Print the arguments of a stack frame, given the function FUNC - running in that frame (as a symbol), the info on the frame, - and the number of args according to the stack frame (or -1 if unknown). */ - -static void print_frame_nameless_args (); - -void -print_frame_args (func, fi, num, stream) - struct symbol *func; - struct frame_info *fi; - int num; - FILE *stream; -{ - struct block *b; - int nsyms = 0; - int first = 1; - register int i; - register int last_offset = FRAME_ARGS_SKIP; - register int last_regparm = 0; - register struct symbol *lastsym, *sym, *nextsym; - register value val; - register CORE_ADDR addr = FRAME_ARGS_ADDRESS (fi); - - if (func) - { - b = SYMBOL_BLOCK_VALUE (func); - nsyms = BLOCK_NSYMS (b); - } - - lastsym = 0; - while (1) - { - /* Find first arg that is not before LAST_OFFSET. */ - nextsym = 0; - for (i = 0; i < nsyms; i++) - { - QUIT; - sym = BLOCK_SYM (b, i); - if (SYMBOL_CLASS (sym) == LOC_ARG) - { - if (SYMBOL_VALUE (sym) >= last_offset - && (nextsym == 0 - || SYMBOL_VALUE (sym) < SYMBOL_VALUE (nextsym))) - nextsym = sym; - } - else if (SYMBOL_CLASS (sym) == LOC_REGPARM) - { - /* This shouldn't be sorted by number. Since we can't - find nameless args with register parameters, print - this out in order by .stabs. */ - if (sym > lastsym && nextsym == 0) - nextsym = sym; - } - } - if (nextsym == 0) - break; - sym = nextsym; - /* Print any nameless args between the last arg printed - and the next arg. */ - if (SYMBOL_CLASS (sym) == LOC_ARG - && last_offset != (SYMBOL_VALUE (sym) / sizeof (int)) * sizeof (int)) - { - print_frame_nameless_args (addr, last_offset, SYMBOL_VALUE (sym), - stream); - first = 0; - } - /* Print the next arg. */ - if (SYMBOL_CLASS (sym) == LOC_REGPARM) - val = value_from_register (SYMBOL_TYPE (sym), - SYMBOL_VALUE (sym), - FRAME_INFO_ID (fi)); - else - val = value_at (SYMBOL_TYPE (sym), addr + SYMBOL_VALUE (sym)); - - if (! first) - fprintf (stream, ", "); - fprintf (stream, "%s=", SYMBOL_NAME (sym)); - value_print (val, stream, 0); - first = 0; - if (SYMBOL_CLASS (sym) == LOC_ARG) - last_offset = SYMBOL_VALUE (sym) + TYPE_LENGTH (SYMBOL_TYPE (sym)); - else - { - last_regparm = SYMBOL_VALUE (sym) + 1; - last_offset += TYPE_LENGTH (SYMBOL_TYPE (sym)); - } - - /* Round up address of next arg to multiple of size of int. */ - last_offset - = ((last_offset + sizeof (int) - 1) / sizeof (int)) * sizeof (int); - lastsym = sym; - } - if (num >= 0 && num * sizeof (int) + FRAME_ARGS_SKIP > last_offset) - print_frame_nameless_args (addr, last_offset, - num * sizeof (int) + FRAME_ARGS_SKIP, stream); -} - -static void -print_frame_nameless_args (argsaddr, start, end, stream) - CORE_ADDR argsaddr; - int start; - int end; - FILE *stream; -{ - while (start < end) - { - QUIT; - if (start != FRAME_ARGS_SKIP) - fprintf (stream, ", "); - fprintf (stream, "%d", - read_memory_integer (argsaddr + start, sizeof (int))); - start += sizeof (int); - } -} - -static void -printf_command (arg) - char *arg; -{ - register char *f; - register char *s = arg; - char *string; - value *val_args; - int nargs = 0; - int allocated_args = 20; - char *arg_bytes; - char *argclass; - int i; - int argindex; - int nargs_wanted; - - val_args = (value *) xmalloc (allocated_args * sizeof (value)); - - if (s == 0) - error_no_arg ("format-control string and values to print"); - - /* Skip white space before format string */ - while (*s == ' ' || *s == '\t') s++; - - /* A format string should follow, enveloped in double quotes */ - if (*s++ != '"') - error ("Bad format string, missing '\"'."); - - /* Parse the format-control string and copy it into the string STRING, - processing some kinds of escape sequence. */ - - f = string = (char *) alloca (strlen (s) + 1); - while (*s != '"') - { - int c = *s++; - switch (c) - { - case '\0': - error ("Bad format string, non-terminated '\"'."); - /* doesn't return */ - - case '\\': - switch (c = *s++) - { - case '\\': - *f++ = '\\'; - break; - case 'n': - *f++ = '\n'; - break; - case 't': - *f++ = '\t'; - break; - case 'r': - *f++ = '\r'; - break; - case '"': - *f++ = '"'; - break; - default: - /* ??? TODO: handle other escape sequences */ - error ("Unrecognized \\ escape character in format string."); - } - break; - - default: - *f++ = c; - } - } - - /* Skip over " and following space and comma. */ - s++; - *f++ = '\0'; - while (*s == ' ' || *s == '\t') s++; - - if (*s != ',' && *s != 0) - error ("Invalid argument syntax"); - - if (*s == ',') s++; - while (*s == ' ' || *s == '\t') s++; - - /* Now scan the string for %-specs and see what kinds of args they want. - argclass[I] is set to 1 if the Ith arg should be a string. - It's set to 2 if the Ith arg should be floating point. */ - - argclass = (char *) alloca (strlen (s)); - nargs_wanted = 0; - f = string; - while (*f) - if (*f++ == '%') - { - while (index ("0123456789.hlL-+ #", *f)) f++; - if (*f == 's') - argclass[nargs_wanted++] = 1; - else if (*f == 'e' || *f == 'f' || *f == 'g') - argclass[nargs_wanted++] = 2; - else if (*f != '%') - argclass[nargs_wanted++] = 0; - f++; - } - - /* Now, parse all arguments and evaluate them. - Store the VALUEs in VAL_ARGS. */ - - while (*s != '\0') - { - char *s1; - if (nargs == allocated_args) - val_args = (value *) xrealloc (val_args, - (allocated_args *= 2) - * sizeof (value)); - s1 = s; - val_args[nargs] = parse_to_comma_and_eval (&s1); - - /* If format string wants a float, unchecked-convert the value to - floating point of the same size */ - - if (argclass[nargs] == 2) - { - argclass[nargs] = 0; - if (TYPE_LENGTH (VALUE_TYPE (val_args[nargs])) == sizeof (float)) - VALUE_TYPE (val_args[nargs]) = builtin_type_float; - if (TYPE_LENGTH (VALUE_TYPE (val_args[nargs])) == sizeof (double)) - VALUE_TYPE (val_args[nargs]) = builtin_type_double; - } - nargs++; - s = s1; - if (*s == ',') - s++; - } - - if (nargs != nargs_wanted) - error ("Wrong number of arguments for specified format-string"); - - /* Now lay out an argument-list containing the arguments - as doubles, integers and C pointers. */ - - arg_bytes = (char *) alloca (sizeof (double) * nargs); - argindex = 0; - for (i = 0; i < nargs; i++) - { - if (argclass[i]) - { - char *str; - int tem, j; - tem = value_as_long (val_args[i]); - - /* This is a %s argument. Find the length of the string. */ - for (j = 0; ; j++) - { - char c; - QUIT; - read_memory (tem + j, &c, 1); - if (c == 0) - break; - } - - /* Copy the string contents into a string inside GDB. */ - str = (char *) alloca (j + 1); - read_memory (tem, str, j); - str[j] = 0; - - /* Pass address of internal copy as the arg to vprintf. */ - *((int *) &arg_bytes[argindex]) = (int) str; - argindex += sizeof (int); - } - else if (VALUE_TYPE (val_args[i])->code == TYPE_CODE_FLT) - { - *((double *) &arg_bytes[argindex]) = value_as_double (val_args[i]); - argindex += sizeof (double); - } - else -#ifdef LONG_LONG - if (TYPE_LENGTH (VALUE_TYPE (val_args[i])) == sizeof (long long)) - { - *(long long *) &arg_bytes[argindex] = value_as_long (val_args[i]); - argindex += sizeof (long long); - } - else -#endif - { - *((int *) &arg_bytes[argindex]) = value_as_long (val_args[i]); - argindex += sizeof (int); - } - } - - vprintf (string, arg_bytes); -} - -extern struct cmd_list_element *enablelist, *disablelist, *deletelist; -extern struct cmd_list_element *cmdlist, *setlist; - -void -_initialize_printcmd () -{ - current_display_number = -1; - - add_info ("address", address_info, - "Describe where variable VAR is stored."); - - add_com ("x", class_vars, x_command, - "Examine memory: x/FMT ADDRESS.\n\ -ADDRESS is an expression for the memory address to examine.\n\ -FMT is a repeat count followed by a format letter and a size letter.\n\ -Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),\n\ - f(float), a(address), i(instruction), c(char) and s(string).\n\ -Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).\n\ - g is meaningful only with f, for type double.\n\ -The specified number of objects of the specified size are printed\n\ -according to the format.\n\n\ -Defaults for format and size letters are those previously used.\n\ -Default count is 1. Default address is following last thing printed\n\ -with this command or \"print\"."); - - add_com ("ptype", class_vars, ptype_command, - "Print definition of type TYPE.\n\ -Argument may be a type name defined by typedef, or \"struct STRUCTNAME\"\n\ -or \"union UNIONNAME\" or \"enum ENUMNAME\".\n\ -The selected stack frame's lexical context is used to look up the name."); - - add_com ("whatis", class_vars, whatis_command, - "Print data type of expression EXP."); - - add_info ("display", display_info, - "Expressions to display when program stops, with code numbers."); - - add_abbrev_cmd ("undisplay", class_vars, undisplay_command, - "Cancel some expressions to be displayed when program stops.\n\ -Arguments are the code numbers of the expressions to stop displaying.\n\ -No argument means cancel all automatic-display expressions.\n\ -\"delete display\" has the same effect as this command.\n\ -Do \"info display\" to see current list of code numbers.", - &cmdlist); - - add_com ("display", class_vars, display_command, - "Print value of expression EXP each time the program stops.\n\ -/FMT may be used before EXP as in the \"print\" command.\n\ -/FMT \"i\" or \"s\" or including a size-letter is allowed,\n\ -as in the \"x\" command, and then EXP is used to get the address to examine\n\ -and examining is done as in the \"x\" command.\n\n\ -With no argument, display all currently requested auto-display expressions.\n\ -Use \"undisplay\" to cancel display requests previously made."); - - add_cmd ("display", class_vars, enable_display, - "Enable some expressions to be displayed when program stops.\n\ -Arguments are the code numbers of the expressions to resume displaying.\n\ -No argument means enable all automatic-display expressions.\n\ -Do \"info display\" to see current list of code numbers.", &enablelist); - - add_cmd ("display", class_vars, disable_display, - "Disable some expressions to be displayed when program stops.\n\ -Arguments are the code numbers of the expressions to stop displaying.\n\ -No argument means disable all automatic-display expressions.\n\ -Do \"info display\" to see current list of code numbers.", &disablelist); - - add_cmd ("display", class_vars, undisplay_command, - "Cancel some expressions to be displayed when program stops.\n\ -Arguments are the code numbers of the expressions to stop displaying.\n\ -No argument means cancel all automatic-display expressions.\n\ -Do \"info display\" to see current list of code numbers.", &deletelist); - - add_com ("printf", class_vars, printf_command, - "printf \"printf format string\", arg1, arg2, arg3, ..., argn\n\ -This is useful for formatted output in user-defined commands."); - add_com ("output", class_vars, output_command, - "Like \"print\" but don't put in value history and don't print newline.\n\ -This is useful in user-defined commands."); - - add_prefix_cmd ("set", class_vars, set_command, -"Perform an assignment VAR = EXP.\n\ -You must type the \"=\". VAR may be a debugger \"convenience\" variable\n\ -(names starting with $), a register (a few standard names starting with $),\n\ -or an actual variable in the program being debugged. EXP is any expression.\n\ -Use \"set variable\" for variables with names identical to set subcommands.\n\ -\nWith a subcommand, this command modifies parts of the gdb environment", - &setlist, "set ", 1, &cmdlist); - - add_cmd ("variable", class_vars, set_command, - "Perform an assignment VAR = EXP.\n\ -You must type the \"=\". VAR may be a debugger \"convenience\" variable\n\ -(names starting with $), a register (a few standard names starting with $),\n\ -or an actual variable in the program being debugged. EXP is any expression.\n\ -This may usually be abbreviated to simply \"set\".", - &setlist); - - add_com ("print", class_vars, print_command, - concat ("Print value of expression EXP.\n\ -Variables accessible are those of the lexical environment of the selected\n\ -stack frame, plus all those whose scope is global or an entire file.\n\ -\n\ -$NUM gets previous value number NUM. $ and $$ are the last two values.\n\ -$$NUM refers to NUM'th value back from the last one.\n\ -Names starting with $ refer to registers (with the values they would have\n\ -if the program were to return to the stack frame now selected, restoring\n\ -all registers saved by frames farther in) or else to debugger\n\ -\"convenience\" variables (any such name not a known register).\n\ -Use assignment expressions to give values to convenience variables.\n", - "\n\ -\{TYPE}ADREXP refers to a datum of data type TYPE, located at address ADREXP.\n\ -@@ is a binary operator for treating consecutive data objects\n\ -anywhere in memory as an array. FOO@@NUM gives an array whose first\n\ -element is FOO, whose second element is stored in the space following\n\ -where FOO is stored, etc. FOO must be an expression whose value\n\ -resides in memory.\n", - "\n\ -EXP may be preceded with /FMT, where FMT is a format letter\n\ -but no count or size letter (see \"x\" command).")); - add_com_alias ("p", "print", class_vars, 1); -} - -@ - - -1.1 -log -@Initial revision -@ -text -@a191 1 - int bigendian = 0; -d196 7 -a202 5 - { - union { - char a, b, c, d; - long i; - } x; -a203 10 - x.i = 1; - if (x.a) - { - /* Little endian */ - tmp = v1; - v1 = v2; - v2 = tmp; - } - } - -d207 1 -a207 1 - printf ("0x%08x%08x", v1, v2); -d238 1 -a238 1 - printf ("0x%02llx", val_long); -d241 1 -a241 1 - printf ("0x%04llx", val_long); -d245 1 -a245 1 - printf ("0x%08llx", val_long); -d248 1 -a248 1 - printf ("0x%16llx", val_long); -d257 1 -a257 1 - printf ("0x%02x", val_long); -d260 1 -a260 1 - printf ("0x%04x", val_long); -d264 1 -a264 1 - printf ("0x%08x", val_long); -d267 1 -a267 1 - printf ("0x%16x", val_long); -d277 1 -a277 1 - printf ("%lld", val_long); -d279 1 -a279 1 - printf ("%d", val_long); -d285 1 -a285 1 - printf ("%llu", val_long); -d287 1 -a287 1 - printf ("%u", val_long); -d294 1 -a294 1 - printf ("0%llo", val_long); -d296 1 -a296 1 - printf ("0%o", val_long); -d299 1 -a299 1 - printf ("0"); -d313 1 -a313 1 - if (len == sizeof (double)) -d315 2 -d318 1 -a318 1 - if (is_nan (unpack_double (type, valaddr))) -d320 1 -a320 1 - printf ("Nan"); -d324 10 -a333 4 - if (len > 4) - printf ("%.16g", unpack_double (type, valaddr)); - else - printf ("%.6g", unpack_double (type, valaddr)); -d515 1 -a515 1 - printf ("$%d = ", histindex); -@ diff --git a/gdb/RCS/remote.c,v b/gdb/RCS/remote.c,v deleted file mode 100644 index 213113dd4b..0000000000 --- a/gdb/RCS/remote.c,v +++ /dev/null @@ -1,662 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.03.27.20.21.22; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.20.18.45.46; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Avoid . -@ -text -@/* Memory-access and commands for inferior process, for GDB. - Copyright (C) 1988 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! -*/ - -/* Remote communication protocol. - All values are encoded in ascii hex digits. - - Request Packet - - read registers g - reply XX....X Each byte of register data - is described by two hex digits. - Registers are in the internal order - for GDB, and the bytes in a register - are in the same order the machine uses. - or ENN for an error. - - write regs GXX..XX Each byte of register data - is described by two hex digits. - reply OK for success - ENN for an error - - read mem mAA..AA,LLLL AA..AA is address, LLLL is length. - reply XX..XX XX..XX is mem contents - or ENN NN is errno - - write mem MAA..AA,LLLL:XX..XX - AA..AA is address, - LLLL is number of bytes, - XX..XX is data - reply OK for success - ENN for an error - - cont cAA..AA AA..AA is address to resume - If AA..AA is omitted, - resume at same address. - - step sAA..AA AA..AA is address to resume - If AA..AA is omitted, - resume at same address. - - There is no immediate reply to step or cont. - The reply comes when the machine stops. - It is SAA AA is the "signal number" - - kill req k -*/ - -#include "defs.h" -#include "param.h" -#include "frame.h" -#include "inferior.h" - -#include "wait.h" - -#ifdef USG -#include -#include -#endif - -#include -#include -#include -#include - -#ifdef HAVE_TERMIO -#include -#undef TIOCGETP -#define TIOCGETP TCGETA -#undef TIOCSETN -#define TIOCSETN TCSETA -#undef TIOCSETP -#define TIOCSETP TCSETAF -#define TERMINAL struct termio -#else -#include -#define TERMINAL struct sgttyb -#endif - -int kiodebug; - -int icache; - -/* Descriptor for I/O to remote machine. */ -int remote_desc; - -#define PBUFSIZ 400 - -static void remote_send (); -static void putpkt (); -static void getpkt (); -static void dcache_flush (); - - -/* 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; -{ - TERMINAL sg; - - remote_debugging = 0; - dcache_init (); - - remote_desc = open (name, O_RDWR); - if (remote_desc < 0) - perror_with_name (name); - - ioctl (remote_desc, TIOCGETP, &sg); -#ifdef HAVE_TERMIO - sg.c_lflag &= ~ICANON; -#else - sg.sg_flags = RAW; -#endif - ioctl (remote_desc, TIOCSETP, &sg); - - if (from_tty) - printf ("Remote debugging using %s\n", name); - remote_debugging = 1; -} - -/* Convert hex digit A to a number. */ - -static int -fromhex (a) - int a; -{ - if (a >= '0' && a <= '9') - return a - '0'; - else if (a >= 'a' && a <= 'f') - return a - 'a' + 10; - else - error ("Reply contains invalid hex digit"); -} - -/* Convert number NIB to a hex digit. */ - -static int -tohex (nib) - int nib; -{ - if (nib < 10) - return '0'+nib; - else - return 'a'+nib-10; -} - -/* Tell the remote machine to resume. */ - -int -remote_resume (step, signal) - int step, signal; -{ - char buf[PBUFSIZ]; - - dcache_flush (); - - strcpy (buf, step ? "s": "c"); - - putpkt (buf); -} - -/* Wait until the remote machine stops, then return, - storing status in STATUS just as `wait' would. */ - -int -remote_wait (status) - WAITTYPE *status; -{ - char buf[PBUFSIZ]; - - WSETEXIT ((*status), 0); - getpkt (buf); - if (buf[0] == 'E') - error ("Remote failure reply: %s", buf); - if (buf[0] != 'S') - error ("Invalid remote reply: %s", buf); - WSETSTOP ((*status), (((fromhex (buf[1])) << 4) + (fromhex (buf[2])))); -} - -/* Read the remote registers into the block REGS. */ - -void -remote_fetch_registers (regs) - char *regs; -{ - char buf[PBUFSIZ]; - int i; - char *p; - - sprintf (buf, "g"); - remote_send (buf); - - /* Reply describes registers byte by byte, - each byte encoded as two hex characters. */ - - p = buf; - for (i = 0; i < REGISTER_BYTES; i++) - { - if (p[0] == 0 || p[1] == 0) - error ("Remote reply is too short: %s", buf); - regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]); - p += 2; - } -} - -/* Store the remote registers from the contents of the block REGS. */ - -void -remote_store_registers (regs) - char *regs; -{ - char buf[PBUFSIZ]; - int i; - char *p; - - buf[0] = 'G'; - - /* Command describes registers byte by byte, - each byte encoded as two hex characters. */ - - p = buf + 1; - for (i = 0; i < REGISTER_BYTES; i++) - { - *p++ = tohex ((regs[i] >> 4) & 0xf); - *p++ = tohex (regs[i] & 0xf); - } - - remote_send (buf); -} - -/* Read a word from remote address ADDR and return it. - This goes through the data cache. */ - -int -remote_fetch_word (addr) - CORE_ADDR addr; -{ - if (icache) - { - extern CORE_ADDR text_start, text_end; - - if (addr >= text_start && addr < text_end) - { - int buffer; - xfer_core_file (addr, &buffer, sizeof (int)); - return buffer; - } - } - return dcache_fetch (addr); -} - -/* Write a word WORD into remote address ADDR. - This goes through the data cache. */ - -void -remote_store_word (addr, word) - CORE_ADDR addr; - int word; -{ - dcache_poke (addr, word); -} - -/* Write memory data directly to the remote machine. - This does not inform the data cache; the data cache uses this. - MEMADDR is the address in the remote memory space. - MYADDR is the address of the buffer in our space. - LEN is the number of bytes. */ - -void -remote_write_bytes (memaddr, myaddr, len) - CORE_ADDR memaddr; - char *myaddr; - int len; -{ - char buf[PBUFSIZ]; - int i; - char *p; - - if (len > PBUFSIZ / 2 - 20) - abort (); - - sprintf (buf, "M%x,%x:", memaddr, len); - - /* Command describes registers byte by byte, - each byte encoded as two hex characters. */ - - p = buf + strlen (buf); - for (i = 0; i < len; i++) - { - *p++ = tohex ((myaddr[i] >> 4) & 0xf); - *p++ = tohex (myaddr[i] & 0xf); - } - - remote_send (buf); -} - -/* Read memory data directly from the remote machine. - This does not use the data cache; the data cache uses this. - MEMADDR is the address in the remote memory space. - MYADDR is the address of the buffer in our space. - LEN is the number of bytes. */ - -void -remote_read_bytes (memaddr, myaddr, len) - CORE_ADDR memaddr; - char *myaddr; - int len; -{ - char buf[PBUFSIZ]; - int i; - char *p; - - if (len > PBUFSIZ / 2 - 1) - abort (); - - sprintf (buf, "m%x,%x", memaddr, len); - remote_send (buf); - - /* Reply describes registers byte by byte, - each byte encoded as two hex characters. */ - - p = buf; - for (i = 0; i < len; i++) - { - if (p[0] == 0 || p[1] == 0) - error ("Remote reply is too short: %s", buf); - myaddr[i] = fromhex (p[0]) * 16 + fromhex (p[1]); - p += 2; - } -} - -/* - -A debug packet whose contents are -is encapsulated for transmission in the form: - - $ # CSUM1 CSUM2 - - must be ASCII alphanumeric and cannot include characters - '$' or '#' - - CSUM1 and CSUM2 are ascii hex representation of an 8-bit - checksum of , the most significant nibble is sent first. - the hex digits 0-9,a-f are used. - -Receiver responds with: - - + - if CSUM is correct and ready for next packet - - - if CSUM is incorrect - -*/ - -/* Send the command in BUF to the remote machine, - and read the reply into BUF. - Report an error if we get an error reply. */ - -static void -remote_send (buf) - char *buf; -{ - int i; - putpkt (buf); - getpkt (buf); - - if (buf[0] == 'E') - error ("Remote failure reply: %s", buf); -} - -/* Send a packet to the remote machine, with error checking. - The data of the packet is in BUF. */ - -static void -putpkt (buf) - char *buf; -{ - int i; - char csum = 0; - char buf2[500]; - char buf3[1]; - int cnt = strlen (buf); - char *p; - - if (kiodebug) - fprintf (stderr, "Sending packet: %s\n", buf); - - /* Copy the packet into buffer BUF2, encapsulating it - and giving it a checksum. */ - - p = buf2; - *p++ = '$'; - - for (i = 0; i < cnt; i++) - { - csum += buf[i]; - *p++ = buf[i]; - } - *p++ = '#'; - *p++ = tohex ((csum >> 4) & 0xf); - *p++ = tohex (csum & 0xf); - - /* Send it over and over until we get a positive ack. */ - - do { - write (remote_desc, buf2, p - buf2); - read (remote_desc, buf3, 1); - } while (buf3[0] != '+'); -} - -static int -readchar () -{ - char buf[1]; - while (read (remote_desc, buf, 1) != 1) ; - return buf[0] & 0x7f; -} - -/* Read a packet from the remote machine, with error checking, - and store it in BUF. */ - -static void -getpkt (buf) - char *buf; -{ - char *bp; - unsigned char csum; - unsigned int c, c1, c2; - extern kiodebug; - - while (1) - { - /* Force csum to be zero here because of possible error retry. */ - csum = 0; - - while ((c = readchar()) != '$'); - - bp = buf; - while (1) - { - c = readchar (); - if (c == '#') - break; - *bp++ = c; - csum += c; - } - *bp = 0; - - c1 = fromhex (readchar ()); - c2 = fromhex (readchar ()); - if (csum == (c1 << 4) + c2) - break; - printf ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n", - (c1 << 4) + c2, csum, buf); - write (remote_desc, "-", 1); - } - - write (remote_desc, "+", 1); - - if (kiodebug) - fprintf (stderr,"Packet received :%s\n", buf); -} - -/* The data cache records all the data read from the remote machine - since the last time it stopped. - - Each cache block holds 16 bytes of data - starting at a multiple-of-16 address. */ - -#define DCACHE_SIZE 64 /* Number of cache blocks */ - -struct dcache_block { - struct dcache_block *next, *last; - unsigned int addr; /* Address for which data is recorded. */ - int data[4]; -}; - -struct dcache_block dcache_free, dcache_valid; - -/* Free all the data cache blocks, thus discarding all cached data. */ - -static void -dcache_flush () -{ - register struct dcache_block *db; - - while ((db = dcache_valid.next) != &dcache_valid) - { - remque (db); - insque (db, &dcache_free); - } -} - -/* - * If addr is present in the dcache, return the address of the block - * containing it. - */ - -struct dcache_block * -dcache_hit (addr) -{ - register struct dcache_block *db; - - if (addr & 3) - abort (); - - /* Search all cache blocks for one that is at this address. */ - db = dcache_valid.next; - while (db != &dcache_valid) - { - if ((addr & 0xfffffff0) == db->addr) - return db; - db = db->next; - } - return NULL; -} - -/* Return the int data at address ADDR in dcache block DC. */ - -int -dcache_value (db, addr) - struct dcache_block *db; - unsigned int addr; -{ - if (addr & 3) - abort (); - return (db->data[(addr>>2)&3]); -} - -/* Get a free cache block, put it on the valid list, - and return its address. The caller should store into the block - the address and data that it describes. */ - -struct dcache_block * -dcache_alloc () -{ - register struct dcache_block *db; - - if ((db = dcache_free.next) == &dcache_free) - /* If we can't get one from the free list, take last valid */ - db = dcache_valid.last; - - remque (db); - insque (db, &dcache_valid); - return (db); -} - -/* Return the contents of the word at address ADDR in the remote machine, - using the data cache. */ - -int -dcache_fetch (addr) - CORE_ADDR addr; -{ - register struct dcache_block *db; - - db = dcache_hit (addr); - if (db == 0) - { - db = dcache_alloc (); - remote_read_bytes (addr & ~0xf, db->data, 16); - db->addr = addr & ~0xf; - } - return (dcache_value (db, addr)); -} - -/* Write the word at ADDR both in the data cache and in the remote machine. */ - -dcache_poke (addr, data) - CORE_ADDR addr; - int data; -{ - register struct dcache_block *db; - - /* First make sure the word is IN the cache. DB is its cache block. */ - db = dcache_hit (addr); - if (db == 0) - { - db = dcache_alloc (); - remote_read_bytes (addr & ~0xf, db->data, 16); - db->addr = addr & ~0xf; - } - - /* Modify the word in the cache. */ - db->data[(addr>>2)&3] = data; - - /* Send the changed word. */ - remote_write_bytes (addr, &data, 4); -} - -/* Initialize the data cache. */ - -dcache_init () -{ - register i; - register struct dcache_block *db; - - db = (struct dcache_block *) xmalloc (sizeof (struct dcache_block) * - DCACHE_SIZE); - dcache_free.next = dcache_free.last = &dcache_free; - dcache_valid.next = dcache_valid.last = &dcache_valid; - for (i=0;i -@ diff --git a/gdb/RCS/source.c,v b/gdb/RCS/source.c,v deleted file mode 100644 index f19ff1da47..0000000000 --- a/gdb/RCS/source.c,v +++ /dev/null @@ -1,990 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.03.27.20.21.45; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.20.18.45.48; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Avoid . -@ -text -@/* List lines of source files for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1988 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! -*/ - -#include "defs.h" -#include "symtab.h" -#include "param.h" - -#ifdef USG -#include -#include -#endif - -#include -#include -#include -#include - -/* Path of directories to search for source files. - Same format as the PATH environment variable's value. */ - -static char *source_path; - -/* Symtab of default file for listing lines of. */ - -struct symtab *current_source_symtab; - -/* Default next line to list. */ - -int current_source_line; - -/* Line number of last line printed. Default for various commands. - current_source_line is usually, but not always, the same as this. */ - -static int last_line_listed; - -/* First line number listed by last listing command. */ - -static int first_line_listed; - - -struct symtab *psymtab_to_symtab (); - -/* Set the source file default for the "list" command, - specifying a symtab. */ - -void -select_source_symtab (s) - register struct symtab *s; -{ - struct symtabs_and_lines sals; - struct symtab_and_line sal; - struct partial_symtab *ps, *cs_pst; - - /* Make the default place to list be the function `main' - if one exists. */ - if (lookup_symbol ("main", 0, VAR_NAMESPACE, 0)) - { - sals = decode_line_spec ("main", 1); - sal = sals.sals[0]; - free (sals.sals); - current_source_symtab = sal.symtab; - current_source_line = sal.line - 9; - return; - } - - /* If there is no `main', use the last symtab in the list, - which is actually the first found in the file's symbol table. - But ignore .h files. */ - if (s) - { - do - { - char *name = s->filename; - int len = strlen (name); - if (! (len > 2 && !strcmp (&name[len - 2], ".h"))) - current_source_symtab = s; - s = s->next; - } - while (s); - current_source_line = 1; - } - else - { - ps = partial_symtab_list; - while (ps) - { - char *name = ps->filename; - int len = strlen (name); - if (! (len > 2 && !strcmp (&name[len - 2], ".h"))) - cs_pst = ps; - ps = ps->next; - } - if (cs_pst) - current_source_symtab = psymtab_to_symtab (cs_pst); - else - current_source_symtab = 0; - current_source_line = 1; - } -} - -static void -directories_info () -{ - printf ("Source directories searched: %s\n", source_path); -} - -void -init_source_path () -{ - register struct symtab *s; - - source_path = savestring (current_directory, strlen (current_directory)); - - /* Forget what we learned about line positions in source files; - must check again now since files may be found in - a different directory now. */ - for (s = symtab_list; s; s = s->next) - if (s->line_charpos != 0) - { - free (s->line_charpos); - s->line_charpos = 0; - } -} - -void -directory_command (dirname, from_tty) - char *dirname; - int from_tty; -{ - char *old = source_path; - - if (dirname == 0) - { - if (query ("Reinitialize source path to %s? ", current_directory)) - { - init_source_path (); - free (old); - } - } - else - { - struct stat st; - register int len = strlen (dirname); - register char *tem; - extern char *index (); - - if (index (dirname, ':')) - error ("Please add one directory at a time to the source path."); - if (dirname[len - 1] == '/') - /* Sigh. "foo/" => "foo" */ - dirname[--len] == '\0'; - - while (dirname[len - 1] == '.') - { - if (len == 1) - { - /* "." => getwd () */ - dirname = current_directory; - goto append; - } - else if (dirname[len - 2] == '/') - { - if (len == 2) - { - /* "/." => "/" */ - dirname[--len] = '\0'; - goto append; - } - else - { - /* "...foo/." => "...foo" */ - dirname[len -= 2] = '\0'; - continue; - } - } - break; - } - - if (dirname[0] != '/') - dirname = concat (current_directory, "/", dirname); - else - dirname = savestring (dirname, len); - make_cleanup (free, dirname); - - if (stat (dirname, &st) < 0) - perror_with_name (dirname); - if ((st.st_mode & S_IFMT) != S_IFDIR) - error ("%s is not a directory.", dirname); - - append: - len = strlen (dirname); - tem = source_path; - while (1) - { - if (!strncmp (tem, dirname, len) - && (tem[len] == '\0' || tem[len] == ':')) - { - printf ("\"%s\" is already in the source path.\n", - dirname); - break; - } - tem = index (tem, ':'); - if (tem) - tem++; - else - { - source_path = concat (old, ":", dirname); - free (old); - break; - } - } - if (from_tty) - directories_info (); - } -} - -/* Open a file named STRING, searching path PATH (dir names sep by colons) - using mode MODE and protection bits PROT in the calls to open. - If TRY_CWD_FIRST, try to open ./STRING before searching PATH. - (ie pretend the first element of PATH is ".") - If FILENAMED_OPENED is non-null, set it to a newly allocated string naming - the actual file opened (this string will always start with a "/" - - If a file is found, return the descriptor. - Otherwise, return -1, with errno set for the last name we tried to open. */ - -/* >>>> This should only allow files of certain types, - >>>> eg executable, non-directory */ -int -openp (path, try_cwd_first, string, mode, prot, filename_opened) - char *path; - int try_cwd_first; - char *string; - int mode; - int prot; - char **filename_opened; -{ - register int fd; - register char *filename; - register char *p, *p1; - register int len; - - /* ./foo => foo */ - while (string[0] == '.' && string[1] == '/') - string += 2; - - if (try_cwd_first || string[0] == '/') - { - filename = string; - fd = open (filename, mode, prot); - if (fd >= 0 || string[0] == '/') - goto done; - } - - filename = (char *) alloca (strlen (path) + strlen (string) + 2); - fd = -1; - for (p = path; p; p = p1 ? p1 + 1 : 0) - { - p1 = (char *) index (p, ':'); - if (p1) - len = p1 - p; - else - len = strlen (p); - - strncpy (filename, p, len); - filename[len] = 0; - strcat (filename, "/"); - strcat (filename, string); - - fd = open (filename, mode, prot); - if (fd >= 0) break; - } - - done: - if (filename_opened) - if (fd < 0) - *filename_opened = (char *) 0; - else if (filename[0] == '/') - *filename_opened = savestring (filename, strlen (filename)); - else - { - *filename_opened = concat (current_directory, "/", filename); - } - - return fd; -} - -/* Create and initialize the table S->line_charpos that records - the positions of the lines in the source file, which is assumed - to be open on descriptor DESC. - All set S->nlines to the number of such lines. */ - -static void -find_source_lines (s, desc) - struct symtab *s; - int desc; -{ - struct stat st; - register char *data, *p, *end; - int nlines = 0; - int lines_allocated = 1000; - int *line_charpos = (int *) xmalloc (lines_allocated * sizeof (int)); - extern int exec_mtime; - - fstat (desc, &st); - if (get_exec_file (0) != 0 && exec_mtime < st.st_mtime) - printf ("Source file is more recent than executable.\n"); - - data = (char *) alloca (st.st_size); - myread (desc, data, st.st_size); - end = data + st.st_size; - p = data; - line_charpos[0] = 0; - nlines = 1; - while (p != end) - { - if (*p++ == '\n' - /* A newline at the end does not start a new line. */ - && p != end) - { - if (nlines == lines_allocated) - { - lines_allocated *= 2; - line_charpos = (int *) xrealloc (line_charpos, - sizeof (int) * lines_allocated); - } - line_charpos[nlines++] = p - data; - } - } - s->nlines = nlines; - s->line_charpos = (int *) xrealloc (line_charpos, nlines * sizeof (int)); -} - -/* Return the character position of a line LINE in symtab S. - Return 0 if anything is invalid. */ - -int -source_line_charpos (s, line) - struct symtab *s; - int line; -{ - if (!s) return 0; - if (!s->line_charpos || line <= 0) return 0; - if (line > s->nlines) - line = s->nlines; - return s->line_charpos[line - 1]; -} - -/* Return the line number of character position POS in symtab S. */ - -int -source_charpos_line (s, chr) - register struct symtab *s; - register int chr; -{ - register int line = 0; - register int *lnp; - - if (s == 0 || s->line_charpos == 0) return 0; - lnp = s->line_charpos; - /* Files are usually short, so sequential search is Ok */ - while (line < s->nlines && *lnp <= chr) - { - line++; - lnp++; - } - if (line >= s->nlines) - line = s->nlines; - return line; -} - -/* Get full pathname and line number positions for a symtab. - Return nonzero if line numbers may have changed. - Set *FULLNAME to actual name of the file as found by `openp', - or to 0 if the file is not found. */ - -int -get_filename_and_charpos (s, line, fullname) - struct symtab *s; - int line; - char **fullname; -{ - register int desc, linenums_changed = 0; - - desc = openp (source_path, 0, s->filename, O_RDONLY, 0, &s->fullname); - if (desc < 0) - { - if (fullname) - *fullname = NULL; - return 0; - } - if (fullname) - *fullname = s->fullname; - if (s->line_charpos == 0) linenums_changed = 1; - if (linenums_changed) find_source_lines (s, desc); - close (desc); - return linenums_changed; -} - -/* Print text describing the full name of the source file S - and the line number LINE and its corresponding character position. - The text starts with two Ctrl-z so that the Emacs-GDB interface - can easily find it. - - MID_STATEMENT is nonzero if the PC is not at the beginning of that line. - - Return 1 if successful, 0 if could not find the file. */ - -int -identify_source_line (s, line, mid_statement) - struct symtab *s; - int line; - int mid_statement; -{ - if (s->line_charpos == 0) - get_filename_and_charpos (s, line, 0); - if (s->fullname == 0) - return 0; - printf ("\032\032%s:%d:%d:%s\n", s->fullname, - line, s->line_charpos[line - 1], - mid_statement ? "middle" : "beg"); - current_source_line = line; - first_line_listed = line; - last_line_listed = line; - current_source_symtab = s; - return 1; -} - -/* Print source lines from the file of symtab S, - starting with line number LINE and stopping before line number STOPLINE. */ - -void -print_source_lines (s, line, stopline, noerror) - struct symtab *s; - int line, stopline; - int noerror; -{ - register int c; - register int desc; - register FILE *stream; - int nlines = stopline - line; - - desc = openp (source_path, 0, s->filename, O_RDONLY, 0, &s->fullname); - if (desc < 0) - { - extern int errno; - if (! noerror) - perror_with_name (s->filename); - print_sys_errmsg (s->filename, errno); - return; - } - - if (s->line_charpos == 0) - find_source_lines (s, desc); - - if (line < 1 || line > s->nlines) - { - close (desc); - error ("Line number out of range; %s has %d lines.", - s->filename, s->nlines); - } - - if (lseek (desc, s->line_charpos[line - 1], 0) < 0) - { - close (desc); - perror_with_name (s->filename); - } - - current_source_symtab = s; - current_source_line = line; - first_line_listed = line; - - stream = fdopen (desc, "r"); - clearerr (stream); - - while (nlines-- > 0) - { - c = fgetc (stream); - if (c == EOF) break; - last_line_listed = current_source_line; - printf ("%d\t", current_source_line++); - do - { - if (c < 040 && c != '\t' && c != '\n') - { - fputc ('^', stdout); - fputc (c + 0100, stdout); - } - else if (c == 0177) - printf ("^?"); - else - fputc (c, stdout); - } while (c != '\n' && (c = fgetc (stream)) >= 0); - } - - fclose (stream); -} - - - -/* - C++ - Print a list of files and line numbers which a user may choose from - in order to list a function which was specified ambiguously - (as with `list classname::overloadedfuncname', for example). - The vector in SALS provides the filenames and line numbers. - */ -static void -ambiguous_line_spec (sals) - struct symtabs_and_lines *sals; -{ - int i; - - for (i = 0; i < sals->nelts; ++i) - printf("file: \"%s\", line number: %d\n", - sals->sals[i].symtab->filename, sals->sals[i].line); -} - - -static void -list_command (arg, from_tty) - char *arg; - int from_tty; -{ - struct symtabs_and_lines sals, sals_end; - struct symtab_and_line sal, sal_end; - struct symbol *sym; - char *arg1; - int no_end = 1; - int dummy_end = 0; - int dummy_beg = 0; - int linenum_beg = 0; - char *p; - - if (symtab_list == 0 && partial_symtab_list == 0) - error ("Listing source lines requires symbols."); - - /* Pull in a current source symtab if necessary */ - if (current_source_symtab == 0 && - (arg == 0 || arg[0] == '+' || arg[0] == '-')) - select_source_symtab (symtab_list); - - /* "l" or "l +" lists next ten lines. */ - - if (arg == 0 || !strcmp (arg, "+")) - { - if (current_source_symtab == 0) - error ("No default source file yet. Do \"help list\"."); - print_source_lines (current_source_symtab, current_source_line, - current_source_line + 10, 0); - return; - } - - /* "l -" lists previous ten lines, the ones before the ten just listed. */ - if (!strcmp (arg, "-")) - { - if (current_source_symtab == 0) - error ("No default source file yet. Do \"help list\"."); - print_source_lines (current_source_symtab, - max (first_line_listed - 10, 1), - first_line_listed, 0); - return; - } - - /* Now if there is only one argument, decode it in SAL - and set NO_END. - If there are two arguments, decode them in SAL and SAL_END - and clear NO_END; however, if one of the arguments is blank, - set DUMMY_BEG or DUMMY_END to record that fact. */ - - arg1 = arg; - if (*arg1 == ',') - dummy_beg = 1; - else - { - sals = decode_line_1 (&arg1, 0, 0, 0); - - if (! sals.nelts) return; /* C++ */ - if (sals.nelts > 1) - { - ambiguous_line_spec (&sals); - free (sals.sals); - return; - } - - sal = sals.sals[0]; - free (sals.sals); - } - - /* Record whether the BEG arg is all digits. */ - - for (p = arg; p != arg1 && *p >= '0' && *p <= '9'; p++); - linenum_beg = (p == arg1); - - while (*arg1 == ' ' || *arg1 == '\t') - arg1++; - if (*arg1 == ',') - { - no_end = 0; - arg1++; - while (*arg1 == ' ' || *arg1 == '\t') - arg1++; - if (*arg1 == 0) - dummy_end = 1; - else - { - if (dummy_beg) - sals_end = decode_line_1 (&arg1, 0, 0, 0); - else - sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line); - if (sals_end.nelts == 0) - return; - if (sals_end.nelts > 1) - { - ambiguous_line_spec (&sals_end); - free (sals_end.sals); - return; - } - sal_end = sals_end.sals[0]; - free (sals_end.sals); - } - } - - if (*arg1) - error ("Junk at end of line specification."); - - if (!no_end && !dummy_beg && !dummy_end - && sal.symtab != sal_end.symtab) - error ("Specified start and end are in different files."); - if (dummy_beg && dummy_end) - error ("Two empty args do not say what lines to list."); - - /* if line was specified by address, - first print exactly which line, and which file. - In this case, sal.symtab == 0 means address is outside - of all known source files, not that user failed to give a filename. */ - if (*arg == '*') - { - if (sal.symtab == 0) - error ("No source file for address 0x%x.", sal.pc); - sym = find_pc_function (sal.pc); - if (sym) - printf ("0x%x is in %s (%s, line %d).\n", - sal.pc, SYMBOL_NAME (sym), sal.symtab->filename, sal.line); - else - printf ("0x%x is in %s, line %d.\n", - sal.pc, sal.symtab->filename, sal.line); - } - - /* If line was not specified by just a line number, - and it does not imply a symtab, it must be an undebuggable symbol - which means no source code. */ - - if (! linenum_beg && sal.symtab == 0) - error ("No line number known for %s.", arg); - - /* If this command is repeated with RET, - turn it into the no-arg variant. */ - - if (from_tty) - *arg = 0; - - if (dummy_beg && sal_end.symtab == 0) - error ("No default source file yet. Do \"help list\"."); - if (dummy_beg) - print_source_lines (sal_end.symtab, max (sal_end.line - 9, 1), - sal_end.line + 1, 0); - else if (sal.symtab == 0) - error ("No default source file yet. Do \"help list\"."); - else if (no_end) - print_source_lines (sal.symtab, max (sal.line - 5, 1), sal.line + 5, 0); - else - print_source_lines (sal.symtab, sal.line, - dummy_end ? sal.line + 10 : sal_end.line + 1, - 0); -} - -/* Print info on range of pc's in a specified line. */ - -static void -line_info (arg, from_tty) - char *arg; - int from_tty; -{ - struct symtabs_and_lines sals; - struct symtab_and_line sal; - int start_pc, end_pc; - int i; - - if (arg == 0) - { - sal.symtab = current_source_symtab; - sal.line = last_line_listed; - sals.nelts = 1; - sals.sals = (struct symtab_and_line *) - xmalloc (sizeof (struct symtab_and_line)); - sals.sals[0] = sal; - } - else - { - sals = decode_line_spec_1 (arg, 0); - - /* If this command is repeated with RET, - turn it into the no-arg variant. */ - if (from_tty) - *arg = 0; - } - - /* C++ More than one line may have been specified, as when the user - specifies an overloaded function name. Print info on them all. */ - for (i = 0; i < sals.nelts; i++) - { - sal = sals.sals[i]; - - if (sal.symtab == 0) - error ("No source file specified."); - - if (sal.line > 0 - && find_line_pc_range (sal.symtab, sal.line, &start_pc, &end_pc)) - { - if (start_pc == end_pc) - printf ("Line %d of \"%s\" is at pc 0x%x but contains no code.\n", - sal.line, sal.symtab->filename, start_pc); - else - printf ("Line %d of \"%s\" starts at pc 0x%x and ends at 0x%x.\n", - sal.line, sal.symtab->filename, start_pc, end_pc); - /* x/i should display this line's code. */ - set_next_address (start_pc); - /* Repeating "info line" should do the following line. */ - last_line_listed = sal.line + 1; - } - else - printf ("Line number %d is out of range for \"%s\".\n", - sal.line, sal.symtab->filename); - } -} - -/* Commands to search the source file for a regexp. */ - -static void -forward_search_command (regex, from_tty) - char *regex; -{ - register int c; - register int desc; - register FILE *stream; - int line = last_line_listed + 1; - char *msg; - - msg = (char *) re_comp (regex); - if (msg) - error (msg); - - if (current_source_symtab == 0) - error ("No default source file yet. Do \"help list\"."); - - /* Search from last_line_listed+1 in current_source_symtab */ - - desc = openp (source_path, 0, current_source_symtab->filename, - O_RDONLY, 0, ¤t_source_symtab->fullname); - if (desc < 0) - perror_with_name (current_source_symtab->filename); - - if (current_source_symtab->line_charpos == 0) - find_source_lines (current_source_symtab, desc); - - if (line < 1 || line > current_source_symtab->nlines) - { - close (desc); - error ("Expression not found"); - } - - if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0) - { - close (desc); - perror_with_name (current_source_symtab->filename); - } - - stream = fdopen (desc, "r"); - clearerr (stream); - while (1) { - char buf[4096]; /* Should be reasonable??? */ - register char *p = buf; - - c = fgetc (stream); - if (c == EOF) - break; - do { - *p++ = c; - } while (c != '\n' && (c = fgetc (stream)) >= 0); - - /* we now have a source line in buf, null terminate and match */ - *p = 0; - if (re_exec (buf) > 0) - { - /* Match! */ - fclose (stream); - print_source_lines (current_source_symtab, - line, line+1, 0); - current_source_line = max (line - 5, 1); - return; - } - line++; - } - - printf ("Expression not found\n"); - fclose (stream); -} - -static void -reverse_search_command (regex, from_tty) - char *regex; -{ - register int c; - register int desc; - register FILE *stream; - int line = last_line_listed - 1; - char *msg; - - msg = (char *) re_comp (regex); - if (msg) - error (msg); - - if (current_source_symtab == 0) - error ("No default source file yet. Do \"help list\"."); - - /* Search from last_line_listed-1 in current_source_symtab */ - - desc = openp (source_path, 0, current_source_symtab->filename, - O_RDONLY, 0, ¤t_source_symtab->fullname); - if (desc < 0) - perror_with_name (current_source_symtab->filename); - - if (current_source_symtab->line_charpos == 0) - find_source_lines (current_source_symtab, desc); - - if (line < 1 || line > current_source_symtab->nlines) - { - close (desc); - error ("Expression not found"); - } - - if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0) - { - close (desc); - perror_with_name (current_source_symtab->filename); - } - - stream = fdopen (desc, "r"); - clearerr (stream); - while (1) - { - char buf[4096]; /* Should be reasonable??? */ - register char *p = buf; - - c = fgetc (stream); - if (c == EOF) - break; - do { - *p++ = c; - } while (c != '\n' && (c = fgetc (stream)) >= 0); - - /* We now have a source line in buf; null terminate and match. */ - *p = 0; - if (re_exec (buf) > 0) - { - /* Match! */ - fclose (stream); - print_source_lines (current_source_symtab, - line, line+1, 0); - current_source_line = max (line - 5, 1); - return; - } - line--; - if (fseek (stream, current_source_symtab->line_charpos[line - 1], 0) < 0) - { - fclose (stream); - perror_with_name (current_source_symtab->filename); - } - } - - printf ("Expression not found\n"); - fclose (stream); - return; -} - -void -_initialize_source () -{ - current_source_symtab = 0; - init_source_path (); - - add_com ("directory", class_files, directory_command, - "Add directory DIR to end of search path for source files.\n\ -With no argument, reset the search path to just the working directory\n\ -and forget cached info on line positions in source files."); - - add_info ("directories", directories_info, - "Current search path for finding source files."); - - add_info ("line", line_info, - "Core addresses of the code for a source line.\n\ -Line can be specified as\n\ - LINENUM, to list around that line in current file,\n\ - FILE:LINENUM, to list around that line in that file,\n\ - FUNCTION, to list around beginning of that function,\n\ - FILE:FUNCTION, to distinguish among like-named static functions.\n\ -Default is to describe the last source line that was listed.\n\n\ -This sets the default address for \"x\" to the line's first instruction\n\ -so that \"x/i\" suffices to start examining the machine code.\n\ -The address is also stored as the value of \"$_\"."); - - add_com ("forward-search", class_files, forward_search_command, - "Search for regular expression (see regex(3)) from last line listed."); - add_com_alias ("search", "forward-search", class_files, 0); - - add_com ("reverse-search", class_files, reverse_search_command, - "Search backward for regular expression (see regex(3)) from last line listed."); - - add_com ("list", class_files, list_command, - "List specified function or line.\n\ -With no argument, lists ten more lines after or around previous listing.\n\ -\"list -\" lists the ten lines before a previous ten-line listing.\n\ -One argument specifies a line, and ten lines are listed around that line.\n\ -Two arguments with comma between specify starting and ending lines to list.\n\ -Lines can be specified in these ways:\n\ - LINENUM, to list around that line in current file,\n\ - FILE:LINENUM, to list around that line in that file,\n\ - FUNCTION, to list around beginning of that function,\n\ - FILE:FUNCTION, to distinguish among like-named static functions.\n\ - *ADDRESS, to list around the line containing that address.\n\ -With two args if one is empty it stands for ten lines away from the other arg."); -} - -@ - - -1.1 -log -@Initial revision -@ -text -@d27 1 -a27 1 -#include -@ diff --git a/gdb/RCS/sparc-dep.c,v b/gdb/RCS/sparc-dep.c,v deleted file mode 100644 index 8178e0052d..0000000000 --- a/gdb/RCS/sparc-dep.c,v +++ /dev/null @@ -1,1091 +0,0 @@ -head 1.3; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.3 -date 89.04.04.21.31.02; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.02.10.01.47.27; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.10.01.46.36; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.3 -log -@Fix handling of annulled branches in single step. "b foo; bcc,a bar" -annuls the instruction at foo, not just after the bcc,a. Also, -handle CBcc (coprocessor) annulled branch, and improve doc. -@ -text -@/* Machine-dependent code which would otherwise be in inflow.c and core.c, - for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. - This code is for the sparc cpu. - -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! -*/ - -#include "defs.h" -#include "param.h" -#include "frame.h" -#include "inferior.h" -#include "obstack.h" -#include "sparc-opcode.h" -#include "gdbcore.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -extern int errno; -extern int attach_flag; - -/* 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); -} - -void -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.*/ - -void -kill_inferior_fast () -{ - if (remote_debugging) - return; - if (inferior_pid == 0) - return; - ptrace (8, inferior_pid, 0, 0); - wait (0); -} - -/* Simulate single-step ptrace call for sun4. Code written by Gary - Beihl (beihl@@mcc.com). */ - -/* - * Duplicated from breakpoint.c because (at least for now) this is a - * machine dependent routine. - */ -static char break_insn[] = BREAKPOINT; - -/* From infrun.c */ -extern int stop_after_trap, stop_after_attach; - -static CORE_ADDR next_pc, npc4, target; -static int brknpc4, brktrg; -typedef char binsn_quantum[sizeof break_insn]; -static binsn_quantum break_mem[3]; - -/* Non-zero if we just simulated a single-step ptrace call. This is - needed because we cannot remove the breakpoints in the inferior - process until after the `wait' in `wait_for_inferior'. Used for - sun4. */ - -int one_stepped; - -void -single_step (signal) - int signal; -{ - branch_type br, isannulled(); - CORE_ADDR pc; - - next_pc = read_register (NPC_REGNUM); - npc4 = next_pc + 4; /* branch not taken */ - - if (!one_stepped) - { - /* Always set breakpoint for NPC. */ - read_memory (next_pc, break_mem[0], sizeof break_insn); - write_memory (next_pc, break_insn, sizeof break_insn); - /* printf ("set break at %x\n",next_pc); */ - - pc = read_register (PC_REGNUM); - br = isannulled (pc, &target); - brknpc4 = brktrg = 0; - - if (br == bicca) - { - /* Conditional annulled branch will either end up at - npc (if taken) or at npc+4 (if not taken). Trap npc+4. */ - brknpc4 = 1; - read_memory (npc4, break_mem[1], sizeof break_insn); - write_memory (npc4, break_insn, sizeof break_insn); - } - else if (br == baa && target != next_pc) - { - /* Unconditional annulled branch will always end up at - the target. */ - brktrg = 1; - read_memory (target, break_mem[2], sizeof break_insn); - write_memory (target, break_insn, sizeof break_insn); - } - - /* Let it go */ - ptrace (7, inferior_pid, 1, signal); - one_stepped = 1; - return; - } - else - { - /* Remove breakpoints */ - write_memory (next_pc, break_mem[0], sizeof break_insn); - - if (brknpc4) - { - write_memory (npc4, break_mem[1], sizeof break_insn); - } - if (brktrg) - { - write_memory (target, break_mem[2], sizeof break_insn); - } - one_stepped = 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 - { - /* Sparc doesn't have single step on ptrace */ - if (step) - single_step (signal); - else - ptrace (7, inferior_pid, 1, signal); - if (errno) - perror_with_name ("ptrace"); - } -} - -#ifdef ATTACH_DETACH - -/* Start debugging the process whose number is PID. */ - -int -attach (pid) - int pid; -{ - errno = 0; - ptrace (PTRACE_ATTACH, pid, 0, 0); - if (errno) - perror_with_name ("ptrace"); - attach_flag = 1; - return pid; -} - -/* Stop debugging the process whose number is PID - and continue it with signal number SIGNAL. - SIGNAL = 0 means just continue it. */ - -void -detach (signal) - int signal; -{ - errno = 0; - ptrace (PTRACE_DETACH, inferior_pid, 1, signal); - if (errno) - perror_with_name ("ptrace"); - attach_flag = 0; -} -#endif /* ATTACH_DETACH */ - -void -fetch_inferior_registers () -{ - struct regs inferior_registers; - struct fp_status inferior_fp_registers; - extern char registers[]; - int cwp; - struct rwindow local_and_ins; - - if (remote_debugging) - remote_fetch_registers (registers); - else - { - ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers); - ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers); - - registers[REGISTER_BYTE (0)] = 0; - bcopy (&inferior_registers.r_g1, ®isters[REGISTER_BYTE (1)], 15 * 4); - bcopy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)], - sizeof inferior_fp_registers.fpu_fr); - *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps; - *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc; - *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = inferior_registers.r_npc; - *(int *)®isters[REGISTER_BYTE (Y_REGNUM)] = inferior_registers.r_y; -/* *(int *)®isters[REGISTER_BYTE (RP_REGNUM)] = - inferior_registers.r_o7 + 8; - bcopy (&inferior_fp_registers.Fpu_fsr, - ®isters[REGISTER_BYTE (FPS_REGNUM)], - sizeof (FPU_FSR_TYPE)); */ - - read_inferior_memory (inferior_registers.r_sp, - ®isters[REGISTER_BYTE (16)], - 16*4); - } -} - -/* 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). */ - -void -store_inferior_registers (regno) - int regno; -{ - struct regs inferior_registers; - struct fp_status inferior_fp_registers; - extern char registers[]; - - if (remote_debugging) - remote_store_registers (registers); - else - { - int in_regs = 1, in_fpregs = 1, in_fparegs, in_cpregs = 1; - - if (regno >= 0) - if (FP0_REGNUM <= regno && regno <= FP0_REGNUM + 32) - in_regs = 0; - else - in_fpregs = 0; - - if (in_regs) - { - bcopy (®isters[REGISTER_BYTE (1)], - &inferior_registers.r_g1, 15 * 4); - - inferior_registers.r_ps = - *(int *)®isters[REGISTER_BYTE (PS_REGNUM)]; - inferior_registers.r_pc = - *(int *)®isters[REGISTER_BYTE (PC_REGNUM)]; - inferior_registers.r_npc = - *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)]; - inferior_registers.r_y = - *(int *)®isters[REGISTER_BYTE (Y_REGNUM)]; - - write_inferior_memory (*(int *)®isters[REGISTER_BYTE (SP_REGNUM)], - ®isters[REGISTER_BYTE (16)], - 16*4); - } - if (in_fpregs) - { - bcopy (®isters[REGISTER_BYTE (FP0_REGNUM)], - &inferior_fp_registers, - sizeof inferior_fp_registers.fpu_fr); - - /* bcopy (®isters[REGISTER_BYTE (FPS_REGNUM)], - &inferior_fp_registers.Fpu_fsr, - sizeof (FPU_FSR_TYPE)); - ****/ - } - - if (in_regs) - ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers); - if (in_fpregs) - ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers); - } -} - -/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory - in the NEW_SUN_PTRACE case. - It ought to be straightforward. But it appears that writing did - not write the data that I specified. I cannot understand where - it got the data that it actually did write. */ - -/* 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 (remote_debugging) - buffer[i] = remote_fetch_word (addr); - else - 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) - buffer[0] = remote_fetch_word (addr); - else - buffer[0] = ptrace (1, inferior_pid, addr, 0); - - if (count > 1) - { - if (remote_debugging) - buffer[count - 1] - = remote_fetch_word (addr + (count - 1) * sizeof (int)); - else - 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; - if (remote_debugging) - remote_store_word (addr, buffer[i]); - else - ptrace (4, inferior_pid, addr, buffer[i]); - if (errno) - return errno; - } - - return 0; -} - - -/* Machine-dependent code which would otherwise be in core.c */ -/* Work with core dump and executable files, for GDB. */ - -/* Recognize COFF format systems because a.out.h defines AOUTHDR. */ -#ifdef AOUTHDR -#define COFF_FORMAT -#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 */ - -/* 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 -#define AOUTHDR struct exec -#endif - -extern char *sys_siglist[]; - -/* Hook for `exec_file_command' command to call. */ - -extern void (*exec_file_display_hook) (); - -#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 (); - -void -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) - { - 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); - - { - struct core corestr; - - val = myread (corechan, &corestr, sizeof corestr); - if (val < 0) - perror_with_name (filename); - if (corestr.c_magic != CORE_MAGIC) - error ("\"%s\" does not appear to be a core dump file (magic 0x%x, expected 0x%x)", - filename, corestr.c_magic, (int) CORE_MAGIC); - else if (sizeof (struct core) != corestr.c_len) - error ("\"%s\" has an invalid struct core length (%d, expected %d)", - filename, corestr.c_len, (int) sizeof (struct core)); - - /* Note that data_start and data_end don't depend on the exec file */ - data_start = N_DATADDR (corestr.c_aouthdr); - data_end = data_start + corestr.c_dsize; - stack_start = stack_end - corestr.c_ssize; - data_offset = sizeof corestr; - stack_offset = sizeof corestr + corestr.c_dsize; - - /* G0 *always* holds 0. */ - *(int *)®isters[REGISTER_BYTE (0)] = 0; - /* The globals and output registers. */ - - bcopy (&corestr.c_regs.r_g1, ((int *) registers) + 1, 15 * 4); - *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps; - *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc; - *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = corestr.c_regs.r_npc; - *(int *)®isters[REGISTER_BYTE (Y_REGNUM)] = corestr.c_regs.r_y; - - /* My best guess at where to get the locals and input - registers is exactly where they usually are, right above - the stack pointer. If the core dump was caused by a bus - writing off the stack pointer (as is possible) then this - won't work, but it's worth the try. */ - { - int sp; - - sp = *(int *)®isters[REGISTER_BYTE (SP_REGNUM)]; - lseek (corechan, sp - stack_start + stack_offset, L_SET); - if (16 * 4 != myread (corechan, - ®isters[REGISTER_BYTE (16)], - 16 * 4)) - /* fprintf so user can still use gdb */ - fprintf (stderr, "Couldn't read input and local registers from core file\n"); - } - - bcopy (corestr.c_fpu.fpu_regs, - ®isters[REGISTER_BYTE (FP0_REGNUM)], - sizeof corestr.c_fpu.fpu_regs); -#ifdef FPU - bcopy (&corestr.c_fpu.fpu_fsr, - ®isters[REGISTER_BYTE (FPS_REGNUM)], - sizeof (FPU_FSR_TYPE)); -#endif - - bcopy (&corestr.c_aouthdr, &core_aouthdr, sizeof (struct exec)); - - printf ("Core file is from \"%s\".\n", corestr.c_cmdname); - if (corestr.c_signo > 0) - printf ("Program terminated with signal %d, %s.\n", - corestr.c_signo, - corestr.c_signo < NSIG - ? sys_siglist[corestr.c_signo] - : "(undocumented)"); - } - 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"); -} - -void -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; - 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) - { - 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) < 0) - error ("\"%s\": can't read text section header", execfile); - - if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections) < 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; - exec_mtime = file_hdr.f_timdat; - } -#else /* not COFF_FORMAT */ - { - struct stat st_exec; - 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; - - fstat (execchan, &st_exec); - 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); -} - -/* - * Find the pc saved in frame FRAME. - */ -CORE_ADDR -frame_saved_pc (frame) - FRAME frame; -{ - CORE_ADDR prev_pc; - - /* If it's at the bottom, the return value's stored in i7/rp */ - if (get_current_frame () == frame) - prev_pc = GET_RWINDOW_REG (read_register (SP_REGNUM), rw_in[7]); - else - /* Wouldn't this always work? This would allow this routine to - be completely a macro. */ - prev_pc = GET_RWINDOW_REG (frame->bottom, rw_in[7]); - - return PC_ADJUST (prev_pc); -} - -/* - * Since an individual frame in the frame cache is defined by two - * arguments (a frame pointer and a stack pointer), we need two - * arguments to get info for an arbitrary stack frame. This routine - * takes two arguments and makes the cached frames look as if these - * two arguments defined a frame on the cache. This allows the rest - * of info frame to extract the important arguments without - * difficulty. - */ -FRAME -setup_arbitrary_frame (frame, stack) - FRAME_ADDR frame, stack; -{ - struct frame_info *fci; - FRAME fid = create_new_frame (frame, 0); - - if (!fid) - fatal ("internal: create_new_frame returned invalid frame id"); - - fid->bottom = stack; - - return fid; -} - -/* This code was written by Gary Beihl (beihl@@mcc.com). - It was modified by Michael Tiemann (tiemann@@corto.inria.fr). */ - -struct command_line *get_breakpoint_commands (); - -/* - * This routine appears to be passed a size by which to increase the - * stack. It then executes a save instruction in the inferior to - * increase the stack by this amount. Only the register window system - * should be affected by this; the program counter & etc. will not be. - * - * This instructions used for this purpose are: - * - * sethi %hi(0x0),g1 * - * add g1,0x1ee0,g1 * - * save sp,g1,sp - * sethi %hi(0x0),g1 * - * add g1,0x1ee0,g1 * - * t g0,0x1,o0 - * sethi %hi(0x0),g0 (nop) - * - * I presume that these set g1 to be the negative of the size, do a - * save (putting the stack pointer at sp - size) and restore the - * original contents of g1. A * indicates that the actual value of - * the instruction is modified below. - */ -static int save_insn_opcodes[] = { - 0x03000000, 0x82007ee0, 0x9de38001, 0x03000000, - 0x82007ee0, 0x91d02001, 0x01000000 }; - -/* Neither do_save_insn or do_restore_insn save stack configuration - (since the stack is in an indeterminate state through the call to - each of them); that responsibility of the routine which calls them. */ - -void -do_save_insn (size) - int size; -{ - int g1 = read_register (1); - CORE_ADDR sp = read_register (SP_REGNUM); - CORE_ADDR pc = read_register (PC_REGNUM); - CORE_ADDR npc = read_register (NPC_REGNUM); - CORE_ADDR fake_pc = sp - sizeof (save_insn_opcodes); - struct inferior_status inf_status; - - save_inferior_status (&inf_status, 0); /* Don't restore stack info */ - /* - * See above. - */ - save_insn_opcodes[0] = 0x03000000 | ((-size >> 10) & 0x3fffff); - save_insn_opcodes[1] = 0x82006000 | (-size & 0x3ff); - save_insn_opcodes[3] = 0x03000000 | ((g1 >> 10) & 0x3fffff); - save_insn_opcodes[4] = 0x82006000 | (g1 & 0x3ff); - write_memory (fake_pc, save_insn_opcodes, sizeof (save_insn_opcodes)); - - clear_proceed_status (); - stop_after_trap = 1; - proceed (fake_pc, 0, 0); - - write_register (PC_REGNUM, pc); - write_register (NPC_REGNUM, npc); - restore_inferior_status (&inf_status); -} - -/* - * This routine takes a program counter value. It restores the - * register window system to the frame above the current one, and sets - * the pc and npc to the correct values. - */ - -/* The following insns translate to: - - restore - t g0,0x1,o0 - sethi %hi(0x0), g0 */ - -static int restore_insn_opcodes[] = { 0x81e80000, 0x91d02001, 0x01000000 }; - -void -do_restore_insn (pc) - CORE_ADDR pc; -{ - CORE_ADDR sp = read_register (SP_REGNUM); - CORE_ADDR npc = pc + 4; - CORE_ADDR fake_pc = sp - sizeof (restore_insn_opcodes); - struct inferior_status inf_status; - - save_inferior_status (&inf_status, 0); /* Don't restore stack info */ - - if (!pc) - abort(); - - write_memory (fake_pc, restore_insn_opcodes, sizeof (restore_insn_opcodes)); - - clear_proceed_status (); - stop_after_trap = 1; - proceed (fake_pc, 0, 0); - - write_register (PC_REGNUM, pc); - write_register (NPC_REGNUM, npc); - restore_inferior_status (&inf_status); -} - -/* - * This routine should be more specific in it's actions; making sure - * that it uses the same register in the initial prologue section. - */ -CORE_ADDR -skip_prologue (pc) - CORE_ADDR pc; -{ - union - { - union insn_fmt insn; - int i; - } x; - int dest = -1; - - x.i = read_memory_integer (pc, 4); - - /* Recognize sethi insn. Record destination. */ - if (x.insn.sethi.op == 0 - && x.insn.sethi.op2 == 4) - { - dest = x.insn.sethi.rd; - pc += 4; - x.i = read_memory_integer (pc, 4); - } - - /* Recognizes an add immediate value to register to either %g1 or - the destination register recorded above. Actually, this might - well recognize several different arithmetic operations.*/ - if (x.insn.arith_imm.op == 2 - && x.insn.arith_imm.i == 1 - && (x.insn.arith_imm.rd == 1 - || x.insn.arith_imm.rd == dest)) - { - pc += 4; - x.i = read_memory_integer (pc, 4); - } - - /* This recognizes any SAVE insn. But why do the XOR and then - the compare? That's identical to comparing against 60 (as long - as there isn't any sign extension). */ - if (x.insn.arith.op == 2 - && (x.insn.arith.op3 ^ 32) == 28) - { - pc += 4; - x.i = read_memory_integer (pc, 4); - } - - /* Now we need to recognize stores into the frame from the input - registers. This recognizes all non alternate stores of input - register, into a location offset from the frame pointer. */ - while (x.insn.arith_imm.op == 3 - && (x.insn.arith_imm.op3 & 0x3c) == 4 /* Store, non-alt */ - && (x.insn.arith_imm.rd & 0x18) == 0x18 /* Input register */ - && x.insn.arith_imm.i == 1 /* Immediate mode */ - && x.insn.arith_imm.rs1 == 30 /* Off of frame pointer */ - && x.insn.arith_imm.simm >= 0x44 /* Into reserved */ - && x.insn.arith_imm.simm < 0x5b) /* stack space. */ - { - pc += 4; - x.i = read_memory_integer (pc, 4); - } - return pc; -} - -/* - * Check instruction at "addr" to see if it is an annulled branch. - * All other instructions will go to NPC or will trap. - * - * Set *target if we find a candidate branch; set to zero if not. - */ - -branch_type -isannulled (addr, target) - CORE_ADDR addr, *target; -{ - union insn_fmt instr; - branch_type val = not_branch; - long offset; /* Must be signed for sign-extend */ - - *target = 0; - instr.intval = read_memory_integer (addr, 4); - /* printf("intval = %x\n",instr.intval); */ - switch (instr.op1.op1) - { - case 0: /* Format 2 */ - switch(instr.op2.op2) - { - case 2: case 6: case 7: /* Bcc, FBcc, CBcc */ - if (instr.branch.cond == 8) - val = instr.branch.a ? baa : ba; - else - val = instr.branch.a ? bicca : bicc; - /* 22 bits, sign extended */ - offset = 4 * ((int) (instr.branch.disp << 10) >> 10); - *target = addr + offset; - break; - } - break; - } - /*printf("isannulled ret: %d\n",val); */ - return val; -} -@ - - -1.2 -log -@ * Use gdbcore.h rather than a bunch of externs. - * Avoid dependency on "exec file" when figuring out data_start and data_end -of core file. -@ -text -@d97 2 -a98 2 -static CORE_ADDR next_pc, pc8, target; -static int brkpc8, brktrg; -d113 2 -a114 1 - branch_type br, isabranch(); -d117 1 -a117 1 - pc8 = read_register (PC_REGNUM) + 8; /* branch not taken */ -d124 1 -d126 3 -a128 3 - /* printf ("set break at %x\n",next_pc); */ - br = isabranch (pc8 - 8, &target); - brkpc8 = brktrg = 0; -d130 7 -a136 6 - if (br == bicca && pc8 != next_pc) - { - /* Handle branches with care */ - brkpc8 = 1; - read_memory (pc8, break_mem[1], sizeof break_insn); - write_memory (pc8, break_insn, sizeof break_insn); -d140 2 -d157 1 -a157 1 - if (brkpc8) -d159 1 -a159 1 - write_memory (pc8, break_mem[1], sizeof break_insn); -d895 6 -a900 1 -/* Set *target if we find a branch. */ -d903 1 -a903 1 -isabranch (addr, target) -d918 1 -a918 1 - case 2: case 6: /* BICC & FBCC */ -d930 1 -a930 1 - /*printf("isabranch ret: %d\n",val); */ -@ - - -1.1 -log -@Initial revision -@ -text -@d29 1 -a453 49 -/* 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; - -d520 2 -a521 1 - data_start = exec_data_start; -a601 2 - data_start = 0; - data_end -= exec_data_start; -a644 2 - data_start = exec_data_start; - data_end += exec_data_start; -a661 2 - data_start = exec_data_start; - data_end += exec_data_start; -@ diff --git a/gdb/RCS/stack.c,v b/gdb/RCS/stack.c,v deleted file mode 100644 index fc755c2fbe..0000000000 --- a/gdb/RCS/stack.c,v +++ /dev/null @@ -1,882 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.02.09.23.53.05; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.09.15.03.51; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Avoid coredumps if stack commands are used when there is no stack. -@ -text -@/* Print and select stack frames for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1989 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! -*/ - -#include - -#include "defs.h" -#include "param.h" -#include "symtab.h" -#include "frame.h" -#include "inferior.h" -#include "gdbcore.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; - -/* Error message when selected_frame is zero when it's needed */ -char no_sel_frame[] = "There is no current stack frame."; - -/* 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 address - 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. */ - -/* FIXME, the argument "frame" is always "selected_frame". This is why - we can say "No selected frame" if it == 0. Probably shouldn't be an - argument anymore... */ - -static void -print_stack_frame (frame, level, source) - FRAME frame; - int level; - int source; -{ - struct frame_info *fi; - - if (frame == 0) - error (no_sel_frame); - fi = get_frame_info (frame); - - print_frame_info (fi, level, source, 1); -} - -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; - - sal = find_pc_line (fi->pc, fi->next_frame); - func = find_pc_function (fi->pc); - 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; - } - - if (source >= 0 || !sal.symtab) - { - if (level >= 0) - printf ("#%-2d ", level); - if (fi->pc != sal.pc || !sal.symtab) - printf ("0x%x in ", fi->pc); - printf ("%s (", funname ? funname : "??"); - if (args) - { - FRAME_NUM_ARGS (numargs, fi); - print_frame_args (func, fi, numargs, stdout); - } - printf (")"); - if (sal.symtab) - printf (" (%s line %d)", sal.symtab->filename, sal.line); - printf ("\n"); - } - - if (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 ("0x%x\t", fi->pc); - print_source_lines (sal.symtab, sal.line, sal.line + 1, 1); - } - current_source_line = max (sal.line - 5, 1); - } - 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 (); /* FIXME, never called! */ - -#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: - if (selected_frame == 0) - error (no_sel_frame); - 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 */ -} - -/* 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; - int numargs; - - frame = parse_frame_specification (addr_exp); - - 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"); - printf (" Arglist at 0x%x,", FRAME_ARGS_ADDRESS (fi)); - FRAME_NUM_ARGS (i, fi); - if (i < 0) - printf (" args: "); - else if (i == 0) - printf (" no args."); - else if (i == 1) - printf (" 1 arg: "); - else - printf (" %d args: ", i); - - FRAME_NUM_ARGS (numargs, fi); - print_frame_args (func, fi, numargs, stdout); - printf ("\n"); - count = 0; - for (i = 0; i < NUM_REGS; i++) - if (fsr.regs[i]) - { - 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; - - if (have_inferior_p () == 0 && corefile == 0) - error ("There is no running program or core file."); - - /* 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 -#if 0 - count = backtrace_limit; -#else - count = -1; -#endif - - 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 ("(More stack frames follow...)\n"); -} - -/* Print the local variables of a block B active in FRAME. */ - -static void -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; - - 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) - { - fprintf (stream, "%s = ", SYMBOL_NAME (sym)); - print_variable_value (sym, frame, stream); - fprintf (stream, "\n"); - fflush (stream); - } - } -} - -/* 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; - - block = get_frame_block (frame); - if (block == 0) - return 0; - while (block != 0) - { - print_block_frame_locals (block, frame, stream); - /* 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); - } - return 1; -} - -static void -locals_info () -{ - if (selected_frame == 0) - error(no_sel_frame); - print_frame_local_vars (selected_frame, stdout); -} - -static int -print_frame_arg_vars (frame, stream) - register FRAME frame; - register FILE *stream; -{ - struct symbol *func; - register struct block *b; - int nsyms; - register int i; - register struct symbol *sym; - - func = get_frame_function (frame); - if (func == 0) - 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_REGPARM) - { - fprintf (stream, "%s = ", SYMBOL_NAME (sym)); - print_variable_value (sym, frame, stream); - fprintf (stream, "\n"); - fflush (stream); - } - } - - return 1; -} - -static void -args_info () -{ - if (selected_frame == 0) - error(no_sel_frame); - 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; -} - -/* 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; - - if (frame == 0) - error (no_sel_frame); - /* 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; - - 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; - - 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; - - 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); -} - -/* 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); -} - -static void -return_command (retval_exp, from_tty) - char *retval_exp; - int from_tty; -{ - struct symbol *thisfun = get_frame_function (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. */ - - while (selected_frame != get_current_frame ()) - POP_FRAME; - - /* Then pop that frame. */ - - POP_FRAME; - - /* Compute the return value (if any) and store in the place - for return values. */ - - if (retval_exp) - set_return_value (parse_and_eval (retval_exp)); - - /* 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 -} - -@ - - -1.1 -log -@Initial revision -@ -text -@d2 1 -a2 1 - Copyright (C) 1986, 1987 Free Software Foundation, Inc. -d27 2 -d42 3 -d64 4 -d76 2 -d162 1 -a162 1 -void flush_cached_frames (); -d212 2 -d392 3 -d489 3 -a491 1 - register struct block *block = get_frame_block (frame); -d510 2 -d520 1 -a520 1 - struct symbol *func = get_frame_function (frame); -d526 1 -d551 2 -d610 2 -@ diff --git a/gdb/RCS/utils.c,v b/gdb/RCS/utils.c,v deleted file mode 100644 index 1d8000d4a9..0000000000 --- a/gdb/RCS/utils.c,v +++ /dev/null @@ -1,726 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.03.27.20.22.34; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.23.14.27.48; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Portability changes. If USG, we need to re-enable the SIGINT -signal handler when it is called. Also, build the sys_siglist -table at runtime, based on the actual values of the signal -#define's. Too many USG systems added Berkeley signal names -as various numbers. -@ -text -@/* General utility routines for GDB, the GNU debugger. - Copyright (C) 1986 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! -*/ - -#include -#include -#include -#include -#include "defs.h" -#include "param.h" -#ifdef HAVE_TERMIO -#include -#endif - -void error (); -void fatal (); - -/* Chain of cleanup actions established with make_cleanup, - to be executed if an error happens. */ - -static struct cleanup *cleanup_chain; - -/* Nonzero means a quit has been requested. */ - -int quit_flag; - -/* Nonzero means quit immediately if Control-C is typed now, - rather than waiting until QUIT is executed. */ - -int immediate_quit; - -/* Add a new cleanup to the cleanup_chain, - and return the previous chain pointer - to be passed later to do_cleanups or discard_cleanups. - Args are FUNCTION to clean up with, and ARG to pass to it. */ - -struct cleanup * -make_cleanup (function, arg) - void (*function) (); - int arg; -{ - register struct cleanup *new - = (struct cleanup *) xmalloc (sizeof (struct cleanup)); - register struct cleanup *old_chain = cleanup_chain; - - new->next = cleanup_chain; - new->function = function; - new->arg = arg; - cleanup_chain = new; - - return old_chain; -} - -/* Discard cleanups and do the actions they describe - until we get back to the point OLD_CHAIN in the cleanup_chain. */ - -void -do_cleanups (old_chain) - register struct cleanup *old_chain; -{ - register struct cleanup *ptr; - while ((ptr = cleanup_chain) != old_chain) - { - (*ptr->function) (ptr->arg); - cleanup_chain = ptr->next; - free (ptr); - } -} - -/* Discard cleanups, not doing the actions they describe, - until we get back to the point OLD_CHAIN in the cleanup_chain. */ - -void -discard_cleanups (old_chain) - register struct cleanup *old_chain; -{ - register struct cleanup *ptr; - while ((ptr = cleanup_chain) != old_chain) - { - cleanup_chain = ptr->next; - free (ptr); - } -} - -/* Set the cleanup_chain to 0, and return the old cleanup chain. */ -struct cleanup * -save_cleanups () -{ - struct cleanup *old_chain = cleanup_chain; - - cleanup_chain = 0; - return old_chain; -} - -/* Restore the cleanup chain from a previously saved chain. */ -void -restore_cleanups (chain) - struct cleanup *chain; -{ - cleanup_chain = chain; -} - -/* This function is useful for cleanups. - Do - - foo = xmalloc (...); - old_chain = make_cleanup (free_current_contents, &foo); - - to arrange to free the object thus allocated. */ - -void -free_current_contents (location) - char **location; -{ - free (*location); -} - -/* Generally useful subroutines used throughout the program. */ - -/* Like malloc but get error if no storage available. */ - -char * -xmalloc (size) - long size; -{ - register char *val = (char *) malloc (size); - if (!val) - fatal ("virtual memory exhausted.", 0); - return val; -} - -/* Like realloc but get error if no storage available. */ - -char * -xrealloc (ptr, size) - char *ptr; - long size; -{ - register char *val = (char *) realloc (ptr, size); - if (!val) - fatal ("virtual memory exhausted.", 0); - return val; -} - -/* Print the system error message for errno, and also mention STRING - as the file name for which the error was encountered. - Then return to command level. */ - -void -perror_with_name (string) - char *string; -{ - extern int sys_nerr; - extern char *sys_errlist[]; - extern int errno; - char *err; - char *combined; - - if (errno < sys_nerr) - err = sys_errlist[errno]; - else - err = "unknown error"; - - combined = (char *) alloca (strlen (err) + strlen (string) + 3); - strcpy (combined, string); - strcat (combined, ": "); - strcat (combined, err); - - error ("%s.", combined); -} - -/* Print the system error message for ERRCODE, and also mention STRING - as the file name for which the error was encountered. */ - -void -print_sys_errmsg (string, errcode) - char *string; - int errcode; -{ - extern int sys_nerr; - extern char *sys_errlist[]; - char *err; - char *combined; - - if (errcode < sys_nerr) - err = sys_errlist[errcode]; - else - err = "unknown error"; - - combined = (char *) alloca (strlen (err) + strlen (string) + 3); - strcpy (combined, string); - strcat (combined, ": "); - strcat (combined, err); - - printf ("%s.\n", combined); -} - -void -quit () -{ - fflush (stdout); -#ifdef HAVE_TERMIO - ioctl (fileno (stdout), TCFLSH, 1); -#else /* not HAVE_TERMIO */ - ioctl (fileno (stdout), TIOCFLUSH, 0); -#endif /* not HAVE_TERMIO */ - -#ifdef TIOCGPGRP - error ("Quit"); -#else - error ("Quit (expect signal %d when inferior is resumed)", SIGINT); -#endif /* TIOCGPGRP */ -} - -/* Control C comes here */ - -void -request_quit () -{ - quit_flag = 1; - -#ifdef USG - /* Restore the signal handler */ - signal(SIGINT, request_quit); -#endif - - if (immediate_quit) - quit (); -} - -/* Print an error message and return to command level. - STRING is the error message, used as a fprintf string, - and ARG is passed as an argument to it. */ - -void -error (string, arg1, arg2, arg3) - char *string; - int arg1, arg2, arg3; -{ - fflush (stdout); - fprintf (stderr, string, arg1, arg2, arg3); - fprintf (stderr, "\n"); - return_to_top_level (); -} - -/* Print an error message and exit reporting failure. - This is for a error that we cannot continue from. - STRING and ARG are passed to fprintf. */ - -void -fatal (string, arg) - char *string; - int arg; -{ - fprintf (stderr, "gdb: "); - fprintf (stderr, string, arg); - fprintf (stderr, "\n"); - exit (1); -} - -/* Make a copy of the string at PTR with SIZE characters - (and add a null character at the end in the copy). - Uses malloc to get the space. Returns the address of the copy. */ - -char * -savestring (ptr, size) - char *ptr; - int size; -{ - register char *p = (char *) xmalloc (size + 1); - bcopy (ptr, p, size); - p[size] = 0; - return p; -} - -char * -concat (s1, s2, s3) - char *s1, *s2, *s3; -{ - register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1; - register char *val = (char *) xmalloc (len); - strcpy (val, s1); - strcat (val, s2); - strcat (val, s3); - return val; -} - -void -print_spaces (n, file) - register int n; - register FILE *file; -{ - while (n-- > 0) - fputc (' ', file); -} - -/* Ask user a y-or-n question and return 1 iff answer is yes. - Takes three args which are given to printf to print the question. - The first, a control string, should end in "? ". - It should not say how to answer, because we do that. */ - -int -query (ctlstr, arg1, arg2) - char *ctlstr; -{ - register int answer; - - /* Automatically answer "yes" if input is not from a terminal. */ - if (!input_from_terminal_p ()) - return 1; - - while (1) - { - printf (ctlstr, arg1, arg2); - printf ("(y or n) "); - fflush (stdout); - answer = fgetc (stdin); - clearerr (stdin); /* in case of C-d */ - if (answer != '\n') - while (fgetc (stdin) != '\n') clearerr (stdin); - if (answer >= 'a') - answer -= 040; - if (answer == 'Y') - return 1; - if (answer == 'N') - return 0; - printf ("Please answer y or n.\n"); - } -} - -/* Parse a C escape sequence. STRING_PTR points to a variable - containing a pointer to the string to parse. That pointer - is updated past the characters we use. The value of the - escape sequence is returned. - - A negative value means the sequence \ newline was seen, - which is supposed to be equivalent to nothing at all. - - If \ is followed by a null character, we return a negative - value and leave the string pointer pointing at the null character. - - If \ is followed by 000, we return 0 and leave the string pointer - after the zeros. A value of 0 does not mean end of string. */ - -int -parse_escape (string_ptr) - char **string_ptr; -{ - register int c = *(*string_ptr)++; - switch (c) - { - case 'a': - return '\a'; - case 'b': - return '\b'; - case 'e': - return 033; - case 'f': - return '\f'; - case 'n': - return '\n'; - case 'r': - return '\r'; - case 't': - return '\t'; - case 'v': - return '\v'; - case '\n': - return -2; - case 0: - (*string_ptr)--; - return 0; - case '^': - c = *(*string_ptr)++; - if (c == '\\') - c = parse_escape (string_ptr); - if (c == '?') - return 0177; - return (c & 0200) | (c & 037); - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - { - register int i = c - '0'; - register int count = 0; - while (++count < 3) - { - if ((c = *(*string_ptr)++) >= '0' && c <= '7') - { - i *= 8; - i += c - '0'; - } - else - { - (*string_ptr)--; - break; - } - } - return i; - } - default: - return c; - } -} - -/* Print the character CH on STREAM as part of the contents - of a literal string whose delimiter is QUOTER. */ - -void -printchar (ch, stream, quoter) - unsigned char ch; - FILE *stream; - int quoter; -{ - register int c = ch; - if (c < 040 || c >= 0177) - { - if (c == '\n') - fprintf (stream, "\\n"); - else if (c == '\b') - fprintf (stream, "\\b"); - else if (c == '\t') - fprintf (stream, "\\t"); - else if (c == '\f') - fprintf (stream, "\\f"); - else if (c == '\r') - fprintf (stream, "\\r"); - else if (c == 033) - fprintf (stream, "\\e"); - else if (c == '\a') - fprintf (stream, "\\a"); - else - fprintf (stream, "\\%03o", c); - } - else - { - if (c == '\\' || c == quoter) - fputc ('\\', stream); - fputc (c, stream); - } -} - - -#ifdef USG -bcopy (from, to, count) -char *from, *to; -{ - memcpy (to, from, count); -} - -bcmp (from, to, count) -{ - return (memcmp (to, from, count)); -} - -bzero (to, count) -char *to; -{ - while (count--) - *to++ = 0; -} - -getwd (buf) -char *buf; -{ - getcwd (buf, MAXPATHLEN); -} - -char * -index (s, c) - char *s; -{ - char *strchr (); - return strchr (s, c); -} - -char * -rindex (s, c) - char *s; -{ - char *strrchr (); - return strrchr (s, c); -} - -/* Queue routines */ - -struct queue { - struct queue *forw; - struct queue *back; -}; - -insque (item, after) -struct queue *item; -struct queue *after; -{ - item->forw = after->forw; - after->forw->back = item; - - item->back = after; - after->forw = item; -} - -remque (item) -struct queue *item; -{ - item->forw->back = item->back; - item->back->forw = item->forw; -} - - -/* - * There is too much variation in Sys V signal numbers and names, so - * we must initialize them at runtime. If C provided a way to initialize - * an array based on subscript and value, this would not be necessary. - */ -static char undoc[] = "(undocumented)"; - -char *sys_siglist[NSIG]; - -_initialize_utils() -{ - int i; - - for (i = 0; i < NSIG; i++) - sys_siglist[i] = undoc; - -#ifdef SIGHUP - sys_siglist[SIGHUP ] = "SIGHUP"; -#endif -#ifdef SIGINT - sys_siglist[SIGINT ] = "SIGINT"; -#endif -#ifdef SIGQUIT - sys_siglist[SIGQUIT ] = "SIGQUIT"; -#endif -#ifdef SIGILL - sys_siglist[SIGILL ] = "SIGILL"; -#endif -#ifdef SIGTRAP - sys_siglist[SIGTRAP ] = "SIGTRAP"; -#endif -#ifdef SIGIOT - sys_siglist[SIGIOT ] = "SIGIOT"; -#endif -#ifdef SIGEMT - sys_siglist[SIGEMT ] = "SIGEMT"; -#endif -#ifdef SIGFPE - sys_siglist[SIGFPE ] = "SIGFPE"; -#endif -#ifdef SIGKILL - sys_siglist[SIGKILL ] = "SIGKILL"; -#endif -#ifdef SIGBUS - sys_siglist[SIGBUS ] = "SIGBUS"; -#endif -#ifdef SIGSEGV - sys_siglist[SIGSEGV ] = "SIGSEGV"; -#endif -#ifdef SIGSYS - sys_siglist[SIGSYS ] = "SIGSYS"; -#endif -#ifdef SIGPIPE - sys_siglist[SIGPIPE ] = "SIGPIPE"; -#endif -#ifdef SIGALRM - sys_siglist[SIGALRM ] = "SIGALRM"; -#endif -#ifdef SIGTERM - sys_siglist[SIGTERM ] = "SIGTERM"; -#endif -#ifdef SIGUSR1 - sys_siglist[SIGUSR1 ] = "SIGUSR1"; -#endif -#ifdef SIGUSR2 - sys_siglist[SIGUSR2 ] = "SIGUSR2"; -#endif -#ifdef SIGCLD - sys_siglist[SIGCLD ] = "SIGCLD"; -#endif -#ifdef SIGCHLD - sys_siglist[SIGCHLD ] = "SIGCHLD"; -#endif -#ifdef SIGPWR - sys_siglist[SIGPWR ] = "SIGPWR"; -#endif -#ifdef SIGTSTP - sys_siglist[SIGTSTP ] = "SIGTSTP"; -#endif -#ifdef SIGTTIN - sys_siglist[SIGTTIN ] = "SIGTTIN"; -#endif -#ifdef SIGTTOU - sys_siglist[SIGTTOU ] = "SIGTTOU"; -#endif -#ifdef SIGSTOP - sys_siglist[SIGSTOP ] = "SIGSTOP"; -#endif -#ifdef SIGXCPU - sys_siglist[SIGXCPU ] = "SIGXCPU"; -#endif -#ifdef SIGXFSZ - sys_siglist[SIGXFSZ ] = "SIGXFSZ"; -#endif -#ifdef SIGVTALRM - sys_siglist[SIGVTALRM ] = "SIGVTALRM"; -#endif -#ifdef SIGPROF - sys_siglist[SIGPROF ] = "SIGPROF"; -#endif -#ifdef SIGWINCH - sys_siglist[SIGWINCH ] = "SIGWINCH"; -#endif -#ifdef SIGCONT - sys_siglist[SIGCONT ] = "SIGCONT"; -#endif -#ifdef SIGURG - sys_siglist[SIGURG ] = "SIGURG"; -#endif -#ifdef SIGIO - sys_siglist[SIGIO ] = "SIGIO"; -#endif -#ifdef SIGWIND - sys_siglist[SIGWIND ] = "SIGWIND"; -#endif -#ifdef SIGPHONE - sys_siglist[SIGPHONE ] = "SIGPHONE"; -#endif -#ifdef SIGPOLL - sys_siglist[SIGPOLL ] = "SIGPOLL"; -#endif -} -#endif /* USG */ - -@ - - -1.1 -log -@Initial revision -@ -text -@d223 1 -d237 6 -a506 26 -char *sys_siglist[32] = { - "SIG0", - "SIGHUP", - "SIGINT", - "SIGQUIT", - "SIGILL", - "SIGTRAP", - "SIGIOT", - "SIGEMT", - "SIGFPE", - "SIGKILL", - "SIGBUS", - "SIGSEGV", - "SIGSYS", - "SIGPIPE", - "SIGALRM", - "SIGTERM", - "SIGUSR1", - "SIGUSR2", - "SIGCLD", - "SIGPWR", - "SIGWIND", - "SIGPHONE", - "SIGPOLL", -}; - -d530 124 -@ diff --git a/gdb/RCS/valprint.c,v b/gdb/RCS/valprint.c,v deleted file mode 100644 index 52d89b07b7..0000000000 --- a/gdb/RCS/valprint.c,v +++ /dev/null @@ -1,1117 +0,0 @@ -head 1.3; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.3 -date 89.04.26.01.49.11; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.04.26.00.57.15; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.04.25.15.16.40; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.3 -log -@Fix spelling Nan => NaN -@ -text -@/* Print values for GNU debugger gdb. - Copyright (C) 1986, 1988 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! -*/ - -#include -#include "defs.h" -#include "param.h" -#include "symtab.h" -#include "value.h" - -/* Maximum number of chars to print for a string pointer value - or vector contents. */ - -static int print_max; - -static void type_print_varspec_suffix (); -static void type_print_varspec_prefix (); -static void type_print_base (); -static void type_print_method_args (); - - -char **unsigned_type_table; -char **signed_type_table; -char **float_type_table; - -/* Print the value VAL in C-ish syntax on stream STREAM. - FORMAT is a format-letter, or 0 for print in natural format of data type. - If the object printed is a string pointer, returns - the number of string bytes printed. */ - -int -value_print (val, stream, format) - value val; - FILE *stream; - char format; -{ - register int i, n, typelen; - - /* A "repeated" value really contains several values in a row. - They are made by the @@ operator. - Print such values as if they were arrays. */ - - if (VALUE_REPEATED (val)) - { - n = VALUE_REPETITIONS (val); - typelen = TYPE_LENGTH (VALUE_TYPE (val)); - fputc ('{', stream); - /* Print arrays of characters using string syntax. */ - if (typelen == 1 && TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT - && format == 0) - { - fputc ('"', stream); - for (i = 0; i < n && i < print_max; i++) - { - QUIT; - printchar (VALUE_CONTENTS (val)[i], stream, '"'); - } - if (i < n) - fprintf (stream, "..."); - fputc ('"', stream); - } - else - { - for (i = 0; i < n && i < print_max; i++) - { - if (i) - fprintf (stream, ", "); - val_print (VALUE_TYPE (val), VALUE_CONTENTS (val) + typelen * i, - VALUE_ADDRESS (val) + typelen * i, - stream, format, 1); - } - if (i < n) - fprintf (stream, "..."); - } - fputc ('}', stream); - return n * typelen; - } - else - { - /* If it is a pointer, indicate what it points to. - - Print type also if it is a reference. - - C++: if it is a member pointer, we will take care - of that when we print it. */ - if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR - || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_REF) - { - fprintf (stream, "("); - type_print (VALUE_TYPE (val), "", stream, -1); - fprintf (stream, ") "); - } - return val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), - VALUE_ADDRESS (val), stream, format, 1); - } -} - -/* Print data of type TYPE located at VALADDR (within GDB), - which came from the inferior at address ADDRESS, - onto stdio stream STREAM according to FORMAT - (a letter or 0 for natural format). - - If the data are a string pointer, returns the number of - sting characters printed. - - if DEREF_REF is nonzero, then dereference references, - otherwise just print them like pointers. */ - -int -val_print (type, valaddr, address, stream, format, deref_ref) - struct type *type; - char *valaddr; - CORE_ADDR address; - FILE *stream; - char format; - int deref_ref; -{ - register int i; - int len, n_baseclasses; - struct type *elttype; - int eltlen; - LONGEST val; - unsigned char c; - - QUIT; - - switch (TYPE_CODE (type)) - { - case TYPE_CODE_ARRAY: - if (TYPE_LENGTH (type) >= 0) - { - elttype = TYPE_TARGET_TYPE (type); - eltlen = TYPE_LENGTH (elttype); - len = TYPE_LENGTH (type) / eltlen; - fprintf (stream, "{"); - /* For an array of chars, print with string syntax. */ - if (eltlen == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT - && format == 0) - { - fputc ('"', stream); - for (i = 0; i < len && i < print_max; i++) - { - QUIT; - printchar (valaddr[i], stream, '"'); - } - if (i < len) - fprintf (stream, "..."); - fputc ('"', stream); - } - else - { - for (i = 0; i < len && i < print_max; i++) - { - if (i) fprintf (stream, ", "); - val_print (elttype, valaddr + i * eltlen, - 0, stream, format, deref_ref); - } - if (i < len) - fprintf (stream, "..."); - } - fprintf (stream, "}"); - break; - } - /* Array of unspecified length: treat like pointer. */ - - case TYPE_CODE_PTR: - if (format) - { - print_scalar_formatted (valaddr, type, format, 0, stream); - break; - } - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER) - { - struct type *domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)); - struct type *target = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type)); - struct fn_field *f; - int j, len2; - char *kind = ""; - - val = unpack_long (builtin_type_int, valaddr); - if (TYPE_CODE (target) == TYPE_CODE_FUNC) - { - if (val < 128) - { - len = TYPE_NFN_FIELDS (domain); - for (i = 0; i < len; i++) - { - f = TYPE_FN_FIELDLIST1 (domain, i); - len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); - - for (j = 0; j < len2; j++) - { - QUIT; - if (TYPE_FN_FIELD_VOFFSET (f, j) == val) - { - kind = "virtual"; - goto common; - } - } - } - } - else - { - struct symbol *sym = find_pc_function ((CORE_ADDR) val); - if (sym == 0) - error ("invalid pointer to member function"); - len = TYPE_NFN_FIELDS (domain); - for (i = 0; i < len; i++) - { - f = TYPE_FN_FIELDLIST1 (domain, i); - len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); - - for (j = 0; j < len2; j++) - { - QUIT; - if (!strcmp (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j))) - goto common; - } - } - } - common: - if (i < len) - { - fputc ('&', stream); - type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0); - fprintf (stream, kind); - if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' - && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$') - type_print_method_args - (TYPE_FN_FIELD_ARGS (f, j) + 1, "~", - TYPE_FN_FIELDLIST_NAME (domain, i), stream); - else - type_print_method_args - (TYPE_FN_FIELD_ARGS (f, j), "", - TYPE_FN_FIELDLIST_NAME (domain, i), stream); - break; - } - } - else - { - /* VAL is a byte offset into the structure type DOMAIN. - Find the name of the field for that offset and - print it. */ - int extra = 0; - int bits = 0; - len = TYPE_NFIELDS (domain); - val <<= 3; /* @@@@ Make VAL into bit offset */ - for (i = 0; i < len; i++) - { - int bitpos = TYPE_FIELD_BITPOS (domain, i); - QUIT; - if (val == bitpos) - break; - if (val < bitpos && i > 0) - { - int ptrsize = (TYPE_LENGTH (builtin_type_char) * TYPE_LENGTH (target)); - /* Somehow pointing into a field. */ - i -= 1; - extra = (val - TYPE_FIELD_BITPOS (domain, i)); - if (extra & 0x3) - bits = 1; - else - extra >>= 3; - break; - } - } - if (i < len) - { - fputc ('&', stream); - type_print_base (domain, stream, 0, 0); - fprintf (stream, "::"); - fprintf (stream, "%s", TYPE_FIELD_NAME (domain, i)); - if (extra) - fprintf (stream, " + %d bytes", extra); - if (bits) - fprintf (stream, " (offset in bits)"); - break; - } - } - fputc ('(', stream); - type_print (type, "", stream, -1); - fprintf (stream, ") %d", val >> 3); - } - else - { - fprintf (stream, "0x%x", * (int *) valaddr); - /* For a pointer to char or unsigned char, - also print the string pointed to, unless pointer is null. */ - - /* For an array of chars, print with string syntax. */ - elttype = TYPE_TARGET_TYPE (type); - i = 0; /* Number of characters printed. */ - if (TYPE_LENGTH (elttype) == 1 - && TYPE_CODE (elttype) == TYPE_CODE_INT - && format == 0 - /* Convex needs this typecast to a long */ - && (long) unpack_long (type, valaddr) != 0 - && print_max) - { - fputc (' ', stream); - - /* Get first character. */ - if (read_memory ( (CORE_ADDR) unpack_long (type, valaddr), - &c, 1)) - { - /* First address out of bounds. */ - fprintf (stream, "
", - (* (int *) valaddr)); - break; - } - else - { - /* A real string. */ - int out_of_bounds = 0; - - fputc ('"', stream); - while (c) - { - QUIT; - printchar (c, stream, '"'); - if (++i >= print_max) - break; - if (read_memory ((CORE_ADDR) unpack_long (type, valaddr) - + i, &c, 1)) - { - /* This address was out of bounds. */ - fprintf (stream, - "\"***
", - (* (int *) valaddr) + i); - out_of_bounds = 1; - break; - } - } - if (!out_of_bounds) - { - fputc ('"', stream); - if (i == print_max) - fprintf (stream, "..."); - } - } - fflush (stream); - } - /* Return number of characters printed, plus one for the - terminating null if we have "reached the end". */ - return i + (print_max && i != print_max); - } - break; - - case TYPE_CODE_MEMBER: - error ("not implemented: member type in val_print"); - break; - - case TYPE_CODE_REF: - fprintf (stream, "(0x%x &) = ", * (int *) valaddr); - /* De-reference the reference. */ - if (deref_ref) - { - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF) - { - value val = value_at (TYPE_TARGET_TYPE (type), * (int *) valaddr); - val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), - VALUE_ADDRESS (val), stream, format, deref_ref); - } - else - fprintf (stream, "???"); - } - break; - - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: - fprintf (stream, "{"); - len = TYPE_NFIELDS (type); - n_baseclasses = TYPE_N_BASECLASSES (type); - for (i = 1; i <= n_baseclasses; i++) - { - fprintf (stream, "\n<%s> = ", TYPE_NAME (TYPE_BASECLASS (type, i))); - val_print (TYPE_FIELD_TYPE (type, 0), - valaddr + TYPE_FIELD_BITPOS (type, i-1) / 8, - 0, stream, 0, 0); - } - if (i > 1) fprintf (stream, "\nmembers of %s: ", TYPE_NAME (type)); - for (i -= 1; i < len; i++) - { - if (i > n_baseclasses) fprintf (stream, ", "); - fprintf (stream, "%s = ", TYPE_FIELD_NAME (type, i)); - /* check if static field */ - if (TYPE_FIELD_STATIC (type, i)) - { - value v; - - v = value_static_field (type, TYPE_FIELD_NAME (type, i), i); - val_print (TYPE_FIELD_TYPE (type, i), - VALUE_CONTENTS (v), 0, stream, format, deref_ref); - } - else if (TYPE_FIELD_PACKED (type, i)) - { - val = unpack_field_as_long (type, valaddr, i); - val_print (TYPE_FIELD_TYPE (type, i), &val, 0, - stream, format, deref_ref); - } - else - { - val_print (TYPE_FIELD_TYPE (type, i), - valaddr + TYPE_FIELD_BITPOS (type, i) / 8, - 0, stream, format, deref_ref); - } - } - fprintf (stream, "}"); - break; - - case TYPE_CODE_ENUM: - if (format) - { - print_scalar_formatted (valaddr, type, format, 0, stream); - break; - } - len = TYPE_NFIELDS (type); - val = (long) unpack_long (builtin_type_int, valaddr); - for (i = 0; i < len; i++) - { - QUIT; - if (val == TYPE_FIELD_BITPOS (type, i)) - break; - } - if (i < len) - fprintf (stream, "%s", TYPE_FIELD_NAME (type, i)); - else - fprintf (stream, "%d", val); - break; - - case TYPE_CODE_FUNC: - if (format) - { - print_scalar_formatted (valaddr, type, format, 0, stream); - break; - } - fprintf (stream, "{"); - type_print (type, "", stream, -1); - fprintf (stream, "} "); - fprintf (stream, "0x%x", address); - break; - - case TYPE_CODE_INT: - if (format) - { - print_scalar_formatted (valaddr, type, format, 0, stream); - break; - } - fprintf (stream, - TYPE_UNSIGNED (type) ? "%u" : "%d", - unpack_long (type, valaddr)); - if (TYPE_LENGTH (type) == 1) - { - fprintf (stream, " '"); - printchar ((unsigned char) unpack_long (type, valaddr), - stream, '\''); - fputc ('\'', stream); - } - break; - - case TYPE_CODE_FLT: - if (format) - { - print_scalar_formatted (valaddr, type, format, 0, stream); - break; - } - /* FIXME: When printing NaNs or invalid floats, print them - in raw hex in addition to the message. */ -#ifdef IEEE_FLOAT - if (is_nan ((void *)valaddr, TYPE_LENGTH(type))) - { - fprintf (stream, "NaN"); - break; - } -#endif - { - double doub; - int inv; - - doub = unpack_double (type, valaddr, &inv); - if (inv) - fprintf (stream, "Invalid float value"); - else - fprintf (stream, TYPE_LENGTH (type) <= 4? "%.6g": "%.16g", doub); - } - break; - - case TYPE_CODE_VOID: - fprintf (stream, "void"); - break; - - default: - error ("Invalid type code in symbol table."); - } - fflush (stream); -} - -#ifdef IEEE_FLOAT - -/* Nonzero if ARG (a double) is a NAN. */ - -int -is_nan (fp, len) - void *fp; - int len; -{ - int lowhalf, highhalf; - union ieee { - long i[2]; /* ASSUMED 32 BITS */ - float f; /* ASSUMED 32 BITS */ - double d; /* ASSUMED 64 BITS */ - } *arg; - - arg = (union ieee *)fp; - - /* - * Single precision float. - */ - if (len == sizeof(long)) { - highhalf = arg->i[0]; - return ((((highhalf >> 23) & 0xFF) == 0xFF) - && 0 != (highhalf & 0x7FFFFF)); - } - - /* Separate the high and low words of the double. - Distinguish big and little-endian machines. */ -#ifdef WORDS_BIG_ENDIAN - lowhalf = arg->i[1], highhalf = arg->i[0]; -#else - lowhalf = arg->i[0], highhalf = arg->i[1]; -#endif - - /* Nan: exponent is the maximum possible, and fraction is nonzero. */ - return (((highhalf>>20) & 0x7ff) == 0x7ff - && - ! ((highhalf & 0xfffff == 0) && (lowhalf == 0))); -} -#endif - -/* Print a description of a type TYPE - in the form of a declaration of a variable named VARSTRING. - Output goes to STREAM (via stdio). - If SHOW is positive, we show the contents of the outermost level - of structure even if there is a type name that could be used instead. - If SHOW is negative, we never show the details of elements' types. */ - -void -type_print (type, varstring, stream, show) - struct type *type; - char *varstring; - FILE *stream; - int show; -{ - type_print_1 (type, varstring, stream, show, 0); -} - -/* LEVEL is the depth to indent lines by. */ - -void -type_print_1 (type, varstring, stream, show, level) - struct type *type; - char *varstring; - FILE *stream; - int show; - int level; -{ - register enum type_code code; - type_print_base (type, stream, show, level); - code = TYPE_CODE (type); - if ((varstring && *varstring) - || - /* Need a space if going to print stars or brackets; - but not if we will print just a type name. */ - ((show > 0 || TYPE_NAME (type) == 0) - && - (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC - || code == TYPE_CODE_ARRAY - || code == TYPE_CODE_MEMBER - || code == TYPE_CODE_REF))) - fprintf (stream, " "); - type_print_varspec_prefix (type, stream, show, 0); - fprintf (stream, "%s", varstring); - type_print_varspec_suffix (type, stream, show, 0); -} - -/* Print the method arguments ARGS to the file STREAM. */ -static void -type_print_method_args (args, prefix, varstring, stream) - struct type **args; - char *prefix, *varstring; - FILE *stream; -{ - int i; - - fprintf (stream, " %s%s (", prefix, varstring); - if (args[1] && args[1]->code != TYPE_CODE_VOID) - { - i = 1; /* skip the class variable */ - while (1) - { - type_print (args[i++], "", stream, 0); - if (!args[i]) - { - fprintf (stream, " ..."); - break; - } - else if (args[i]->code != TYPE_CODE_VOID) - { - fprintf (stream, ", "); - } - else break; - } - } - fprintf (stream, ")"); -} - -/* If TYPE is a derived type, then print out derivation - information. Print out all layers of the type heirarchy - until we encounter one with multiple inheritance. - At that point, print out that ply, and return. */ -static void -type_print_derivation_info (stream, type) - FILE *stream; - struct type *type; -{ - char *name; - int i, n_baseclasses = TYPE_N_BASECLASSES (type); - struct type *basetype = 0; - - while (type && n_baseclasses == 1) - { - basetype = TYPE_BASECLASS (type, 1); - if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype))) - { - while (*name != ' ') name++; - fprintf (stream, ": %s%s %s ", - TYPE_VIA_PUBLIC (basetype) ? "public" : "private", - TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "", - name + 1); - } - n_baseclasses = TYPE_N_BASECLASSES (basetype); - type = basetype; - } - - if (type) - { - if (n_baseclasses != 0) - fprintf (stream, ": "); - for (i = 1; i <= n_baseclasses; i++) - { - basetype = TYPE_BASECLASS (type, i); - if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype))) - { - while (*name != ' ') name++; - fprintf (stream, "%s%s %s", - TYPE_VIA_PUBLIC (basetype) ? "public" : "private", - TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "", - name + 1); - } - if (i < n_baseclasses) - fprintf (stream, ", "); - } - putc (' ', stream); - } -} - -/* Print any asterisks or open-parentheses needed before the - variable name (to describe its type). - - On outermost call, pass 0 for PASSED_A_PTR. - On outermost call, SHOW > 0 means should ignore - any typename for TYPE and show its details. - SHOW is always zero on recursive calls. */ - -static void -type_print_varspec_prefix (type, stream, show, passed_a_ptr) - struct type *type; - FILE *stream; - int show; - int passed_a_ptr; -{ - if (type == 0) - return; - - if (TYPE_NAME (type) && show <= 0) - return; - - QUIT; - - switch (TYPE_CODE (type)) - { - case TYPE_CODE_PTR: - type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); - fputc ('*', stream); - break; - - case TYPE_CODE_MEMBER: - type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, - passed_a_ptr); - fputc (' ', stream); - type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, - passed_a_ptr); - fprintf (stream, "::"); - break; - - case TYPE_CODE_REF: - type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); - fputc ('&', stream); - break; - - case TYPE_CODE_FUNC: - type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, - passed_a_ptr); - if (passed_a_ptr) - fputc ('(', stream); - break; - - case TYPE_CODE_ARRAY: - type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, - passed_a_ptr); - } -} - -/* Print any array sizes, function arguments or close parentheses - needed after the variable name (to describe its type). - Args work like type_print_varspec_prefix. */ - -static void -type_print_varspec_suffix (type, stream, show, passed_a_ptr) - struct type *type; - FILE *stream; - int show; - int passed_a_ptr; -{ - if (type == 0) - return; - - if (TYPE_NAME (type) && show <= 0) - return; - - QUIT; - - switch (TYPE_CODE (type)) - { - case TYPE_CODE_ARRAY: - type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, - passed_a_ptr); - fprintf (stream, "["); - if (TYPE_LENGTH (type) >= 0 - && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0) - fprintf (stream, "%d", - TYPE_LENGTH (type) / TYPE_LENGTH (TYPE_TARGET_TYPE (type))); - fprintf (stream, "]"); - break; - - case TYPE_CODE_MEMBER: - if (passed_a_ptr) - fputc (')', stream); - type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0); - break; - - case TYPE_CODE_PTR: - case TYPE_CODE_REF: - type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1); - break; - - case TYPE_CODE_FUNC: - type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, - passed_a_ptr); - if (passed_a_ptr) - fprintf (stream, ")"); - fprintf (stream, "()"); - break; - } -} - -/* Print the name of the type (or the ultimate pointer target, - function value or array element), or the description of a - structure or union. - - SHOW nonzero means don't print this type as just its name; - show its real definition even if it has a name. - SHOW zero means print just typename or struct tag if there is one - SHOW negative means abbreviate structure elements. - SHOW is decremented for printing of structure elements. - - LEVEL is the depth to indent by. - We increase it for some recursive calls. */ - -static void -type_print_base (type, stream, show, level) - struct type *type; - FILE *stream; - int show; - int level; -{ - char *name; - register int i; - register int len; - register int lastval; - - QUIT; - - if (type == 0) - { - fprintf (stream, "type unknown"); - return; - } - - if (TYPE_NAME (type) && show <= 0) - { - fprintf (stream, TYPE_NAME (type)); - return; - } - - switch (TYPE_CODE (type)) - { - case TYPE_CODE_ARRAY: - case TYPE_CODE_PTR: - case TYPE_CODE_MEMBER: - case TYPE_CODE_REF: - case TYPE_CODE_FUNC: - type_print_base (TYPE_TARGET_TYPE (type), stream, show, level); - break; - - case TYPE_CODE_STRUCT: - fprintf (stream, "struct "); - goto struct_union; - - case TYPE_CODE_UNION: - fprintf (stream, "union "); - struct_union: - if (TYPE_NAME (type) && (name = TYPE_NAME (type))) - { - while (*name != ' ') name++; - fprintf (stream, "%s ", name + 1); - } - if (show < 0) - fprintf (stream, "{...}"); - else - { - int i; - - type_print_derivation_info (stream, type); - - fprintf (stream, "{"); - len = TYPE_NFIELDS (type); - if (len) fprintf (stream, "\n"); - else fprintf (stream, "\n"); - - /* If there is a base class for this type, - do not print the field that it occupies. */ - for (i = TYPE_N_BASECLASSES (type); i < len; i++) - { - QUIT; - /* Don't print out virtual function table. */ - if (! strncmp (TYPE_FIELD_NAME (type, i), - "_vptr$", 6)) - continue; - - print_spaces (level + 4, stream); - if (TYPE_FIELD_STATIC (type, i)) - { - fprintf (stream, "static "); - } - type_print_1 (TYPE_FIELD_TYPE (type, i), - TYPE_FIELD_NAME (type, i), - stream, show - 1, level + 4); - if (!TYPE_FIELD_STATIC (type, i) - && TYPE_FIELD_PACKED (type, i)) - { - /* ??? don't know what to put here ??? */; - } - fprintf (stream, ";\n"); - } - - /* C++: print out the methods */ - len = TYPE_NFN_FIELDS (type); - if (len) fprintf (stream, "\n"); - for (i = 0; i < len; i++) - { - struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i); - int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i); - - for (j = 0; j < len2; j++) - { - QUIT; - print_spaces (level + 4, stream); - if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) - fprintf (stream, "virtual "); - type_print (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j))), "", stream, 0); - if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' - && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$') - type_print_method_args - (TYPE_FN_FIELD_ARGS (f, j) + 1, "~", - TYPE_FN_FIELDLIST_NAME (type, i), stream); - else - type_print_method_args - (TYPE_FN_FIELD_ARGS (f, j), "", - TYPE_FN_FIELDLIST_NAME (type, i), stream); - - fprintf (stream, ";\n"); - } - if (len2) fprintf (stream, "\n"); - } - - print_spaces (level, stream); - fputc ('}', stream); - } - break; - - case TYPE_CODE_ENUM: - fprintf (stream, "enum "); - if (TYPE_NAME (type)) - { - name = TYPE_NAME (type); - while (*name != ' ') name++; - fprintf (stream, "%s ", name + 1); - } - if (show < 0) - fprintf (stream, "{...}"); - else - { - fprintf (stream, "{"); - len = TYPE_NFIELDS (type); - lastval = 0; - for (i = 0; i < len; i++) - { - QUIT; - if (i) fprintf (stream, ", "); - fprintf (stream, "%s", TYPE_FIELD_NAME (type, i)); - if (lastval != TYPE_FIELD_BITPOS (type, i)) - { - fprintf (stream, " : %d", TYPE_FIELD_BITPOS (type, i)); - lastval = TYPE_FIELD_BITPOS (type, i); - } - lastval++; - } - fprintf (stream, "}"); - } - break; - - case TYPE_CODE_INT: - if (TYPE_UNSIGNED (type)) - name = unsigned_type_table[TYPE_LENGTH (type)]; - else - name = signed_type_table[TYPE_LENGTH (type)]; - fprintf (stream, "%s", name); - break; - - case TYPE_CODE_FLT: - name = float_type_table[TYPE_LENGTH (type)]; - fprintf (stream, "%s", name); - break; - - case TYPE_CODE_VOID: - fprintf (stream, "void"); - break; - - case 0: - fprintf (stream, "struct unknown"); - break; - - default: - error ("Invalid type code in symbol table."); - } -} - -static void -set_maximum_command (arg) - char *arg; -{ - if (!arg) error_no_arg ("value for maximum elements to print"); - print_max = atoi (arg); -} - -extern struct cmd_list_element *setlist; - -void -_initialize_valprint () -{ - add_cmd ("array-max", class_vars, set_maximum_command, - "Set NUMBER as limit on string chars or array elements to print.", - &setlist); - - print_max = 200; - - unsigned_type_table - = (char **) xmalloc ((1 + sizeof (unsigned LONGEST)) * sizeof (char *)); - bzero (unsigned_type_table, (1 + sizeof (unsigned LONGEST))); - unsigned_type_table[sizeof (unsigned char)] = "unsigned char"; - unsigned_type_table[sizeof (unsigned short)] = "unsigned short"; - unsigned_type_table[sizeof (unsigned long)] = "unsigned long"; - unsigned_type_table[sizeof (unsigned int)] = "unsigned int"; -#ifdef LONG_LONG - unsigned_type_table[sizeof (unsigned long long)] = "unsigned long long"; -#endif - - signed_type_table - = (char **) xmalloc ((1 + sizeof (LONGEST)) * sizeof (char *)); - bzero (signed_type_table, (1 + sizeof (LONGEST))); - signed_type_table[sizeof (char)] = "char"; - signed_type_table[sizeof (short)] = "short"; - signed_type_table[sizeof (long)] = "long"; - signed_type_table[sizeof (int)] = "int"; -#ifdef LONG_LONG - signed_type_table[sizeof (long long)] = "long long"; -#endif - - float_type_table - = (char **) xmalloc ((1 + sizeof (double)) * sizeof (char *)); - bzero (float_type_table, (1 + sizeof (double))); - float_type_table[sizeof (float)] = "float"; - float_type_table[sizeof (double)] = "double"; -} - -@ - - -1.2 -log -@(1) Use XXX_BIG_ENDIAN macros rather than testing at runtime. -(2) Change args to is_nan, support floats, change one call to it. -(3) Change args to unpack_double. -@ -text -@d488 1 -a488 1 - fprintf (stream, "Nan"); -@ - - -1.1 -log -@Initial revision -@ -text -@d483 2 -d486 1 -a486 1 - if (is_nan (unpack_double (type, valaddr))) -d492 10 -a501 4 - if (TYPE_LENGTH (type) <= 4) - fprintf (stream, "%.6g", unpack_double (type, valaddr)); - else - fprintf (stream, "%.16g", unpack_double (type, valaddr)); -a515 5 -union ieee { - int i[2]; - double d; -}; - -d519 3 -a521 2 -is_nan (arg) - union ieee arg; -d524 16 -a539 1 - union { int i; char c; } test; -d543 5 -a547 6 - test.i = 1; - if (test.c != 1) - /* Big-endian machine */ - lowhalf = arg.i[1], highhalf = arg.i[0]; - else - lowhalf = arg.i[0], highhalf = arg.i[1]; -@ diff --git a/gdb/RCS/values.c,v b/gdb/RCS/values.c,v deleted file mode 100644 index bc32f31d23..0000000000 --- a/gdb/RCS/values.c,v +++ /dev/null @@ -1,1047 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.04.26.01.05.45; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.04.25.15.38.44; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@(1) use XXX_BIG_ENDIAN macros rather than runtime tests. -(2) Invalid values aren't stored in the value history, but they do -not cause an error; a -1 is returned as their value index. -(3) unpack_double takes a new arg, and callers check it. -@ -text -@ -/* Low level packing and unpacking of values for GDB. - Copyright (C) 1986, 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! -*/ - -#include -#include "defs.h" -#include "param.h" -#include "symtab.h" -#include "value.h" - -/* The value-history records all the values printed - by print commands during this session. Each chunk - records 60 consecutive values. The first chunk on - the chain records the most recent values. - The total number of values is in value_history_count. */ - -#define VALUE_HISTORY_CHUNK 60 - -struct value_history_chunk -{ - struct value_history_chunk *next; - value values[VALUE_HISTORY_CHUNK]; -}; - -/* Chain of chunks now in use. */ - -static struct value_history_chunk *value_history_chain; - -static int value_history_count; /* Abs number of last entry stored */ - - -/* List of all value objects currently allocated - (except for those released by calls to release_value) - This is so they can be freed after each command. */ - -static value all_values; - -/* Allocate a value that has the correct length for type TYPE. */ - -value -allocate_value (type) - struct type *type; -{ - register value val; - - val = (value) xmalloc (sizeof (struct value) + TYPE_LENGTH (type)); - VALUE_NEXT (val) = all_values; - all_values = val; - VALUE_TYPE (val) = type; - VALUE_LVAL (val) = not_lval; - VALUE_ADDRESS (val) = 0; - VALUE_FRAME (val) = 0; - VALUE_OFFSET (val) = 0; - VALUE_BITPOS (val) = 0; - VALUE_BITSIZE (val) = 0; - VALUE_REPEATED (val) = 0; - VALUE_REPETITIONS (val) = 0; - VALUE_REGNO (val) = -1; - return val; -} - -/* Allocate a value that has the correct length - for COUNT repetitions type TYPE. */ - -value -allocate_repeat_value (type, count) - struct type *type; - int count; -{ - register value val; - - val = (value) xmalloc (sizeof (struct value) + TYPE_LENGTH (type) * count); - VALUE_NEXT (val) = all_values; - all_values = val; - VALUE_TYPE (val) = type; - VALUE_LVAL (val) = not_lval; - VALUE_ADDRESS (val) = 0; - VALUE_FRAME (val) = 0; - VALUE_OFFSET (val) = 0; - VALUE_BITPOS (val) = 0; - VALUE_BITSIZE (val) = 0; - VALUE_REPEATED (val) = 1; - VALUE_REPETITIONS (val) = count; - VALUE_REGNO (val) = -1; - return val; -} - -/* Free all the values that have been allocated (except for those released). - Called after each command, successful or not. */ - -void -free_all_values () -{ - register value val, next; - - for (val = all_values; val; val = next) - { - next = VALUE_NEXT (val); - free (val); - } - - all_values = 0; -} - -/* Remove VAL from the chain all_values - so it will not be freed automatically. */ - -void -release_value (val) - register value val; -{ - register value v; - - if (all_values == val) - { - all_values = val->next; - return; - } - - for (v = all_values; v; v = v->next) - { - if (v->next == val) - { - v->next = val->next; - break; - } - } -} - -/* Return a copy of the value ARG. - It contains the same contents, for same memory address, - but it's a different block of storage. */ - -static value -value_copy (arg) - value arg; -{ - register value val; - register struct type *type = VALUE_TYPE (arg); - if (VALUE_REPEATED (arg)) - val = allocate_repeat_value (type, VALUE_REPETITIONS (arg)); - else - val = allocate_value (type); - VALUE_LVAL (val) = VALUE_LVAL (arg); - VALUE_ADDRESS (val) = VALUE_ADDRESS (arg); - VALUE_OFFSET (val) = VALUE_OFFSET (arg); - VALUE_BITPOS (val) = VALUE_BITPOS (arg); - VALUE_BITSIZE (val) = VALUE_BITSIZE (arg); - VALUE_REGNO (val) = VALUE_REGNO (arg); - bcopy (VALUE_CONTENTS (arg), VALUE_CONTENTS (val), - TYPE_LENGTH (VALUE_TYPE (arg)) - * (VALUE_REPEATED (arg) ? VALUE_REPETITIONS (arg) : 1)); - return val; -} - -/* Access to the value history. */ - -/* Record a new value in the value history. - Returns the absolute history index of the entry. */ - -int -record_latest_value (val) - value val; -{ - int i; - double foo; - - /* Check error now if about to store an invalid float. We return -1 - to the caller, but allow them to continue, e.g. to print it as "Nan". */ - if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FLT) { - foo = unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &i); - if (i) return -1; /* Indicate value not saved in history */ - } - - /* Here we treat value_history_count as origin-zero - and applying to the value being stored now. */ - - i = value_history_count % VALUE_HISTORY_CHUNK; - if (i == 0) - { - register struct value_history_chunk *new - = (struct value_history_chunk *) xmalloc (sizeof (struct value_history_chunk)); - bzero (new->values, sizeof new->values); - new->next = value_history_chain; - value_history_chain = new; - } - - value_history_chain->values[i] = val; - release_value (val); - - /* Now we regard value_history_count as origin-one - and applying to the value just stored. */ - - return ++value_history_count; -} - -/* Return a copy of the value in the history with sequence number NUM. */ - -value -access_value_history (num) - int num; -{ - register struct value_history_chunk *chunk; - register int i; - register int absnum = num; - - if (absnum <= 0) - absnum += value_history_count; - - if (absnum <= 0) - { - if (num == 0) - error ("The history is empty."); - else if (num == 1) - error ("There is only one value in the history."); - else - error ("History does not go back to $$%d.", -num); - } - if (absnum > value_history_count) - error ("History has not yet reached $%d.", absnum); - - absnum--; - - /* Now absnum is always absolute and origin zero. */ - - chunk = value_history_chain; - for (i = (value_history_count - 1) / VALUE_HISTORY_CHUNK - absnum / VALUE_HISTORY_CHUNK; - i > 0; i--) - chunk = chunk->next; - - return value_copy (chunk->values[absnum % VALUE_HISTORY_CHUNK]); -} - -/* Clear the value history entirely. - Must be done when new symbol tables are loaded, - because the type pointers become invalid. */ - -void -clear_value_history () -{ - register struct value_history_chunk *next; - register int i; - register value val; - - while (value_history_chain) - { - for (i = 0; i < VALUE_HISTORY_CHUNK; i++) - if (val = value_history_chain->values[i]) - free (val); - next = value_history_chain->next; - free (value_history_chain); - value_history_chain = next; - } - value_history_count = 0; -} - -static void -history_info (num_exp) - char *num_exp; -{ - register int i; - register value val; - register int num; - - if (num_exp) - num = parse_and_eval_address (num_exp) - 5; - else - num = value_history_count - 9; - - if (num <= 0) - num = 1; - - for (i = num; i < num + 10 && i <= value_history_count; i++) - { - val = access_value_history (i); - printf ("$%d = ", i); - value_print (val, stdout, 0); - printf ("\n"); - } -} - -/* Internal variables. These are variables within the debugger - that hold values assigned by debugger commands. - The user refers to them with a '$' prefix - that does not appear in the variable names stored internally. */ - -static struct internalvar *internalvars; - -/* Look up an internal variable with name NAME. NAME should not - normally include a dollar sign. - - If the specified internal variable does not exist, - one is created, with a void value. */ - -struct internalvar * -lookup_internalvar (name) - char *name; -{ - register struct internalvar *var; - - for (var = internalvars; var; var = var->next) - if (!strcmp (var->name, name)) - return var; - - var = (struct internalvar *) xmalloc (sizeof (struct internalvar)); - var->name = concat (name, "", ""); - var->value = allocate_value (builtin_type_void); - release_value (var->value); - var->next = internalvars; - internalvars = var; - return var; -} - -value -value_of_internalvar (var) - struct internalvar *var; -{ - register value val = value_copy (var->value); - VALUE_LVAL (val) = lval_internalvar; - VALUE_INTERNALVAR (val) = var; - return val; -} - -void -set_internalvar_component (var, offset, bitpos, bitsize, newval) - struct internalvar *var; - int offset, bitpos, bitsize; - value newval; -{ - register char *addr = VALUE_CONTENTS (var->value) + offset; - if (bitsize) - modify_field (addr, (int) value_as_long (newval), - bitpos, bitsize); - else - bcopy (VALUE_CONTENTS (newval), addr, - TYPE_LENGTH (VALUE_TYPE (newval))); -} - -void -set_internalvar (var, val) - struct internalvar *var; - value val; -{ - free (var->value); - var->value = value_copy (val); - release_value (var->value); -} - -char * -internalvar_name (var) - struct internalvar *var; -{ - return var->name; -} - -/* Free all internalvars. Done when new symtabs are loaded, - because that makes the values invalid. */ - -void -clear_internalvars () -{ - register struct internalvar *var; - - while (internalvars) - { - var = internalvars; - internalvars = var->next; - free (var->name); - free (var->value); - free (var); - } -} - -static void -convenience_info () -{ - register struct internalvar *var; - - if (internalvars) - printf ("Debugger convenience variables:\n\n"); - else - printf ("No debugger convenience variables now defined.\n\ -Convenience variables have names starting with \"$\";\n\ -use \"set\" as in \"set $foo = 5\" to define them.\n"); - - for (var = internalvars; var; var = var->next) - { - printf ("$%s: ", var->name); - value_print (var->value, stdout, 0); - printf ("\n"); - } -} - -/* Extract a value as a C number (either long or double). - Knows how to convert fixed values to double, or - floating values to long. - Does not deallocate the value. */ - -LONGEST -value_as_long (val) - register value val; -{ - return unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val)); -} - -double -value_as_double (val) - register value val; -{ - double foo; - int inv; - - foo = unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &inv); - if (inv) - error ("Invalid floating value found in program."); - return foo; -} - -/* Unpack raw data (copied from debugee) at VALADDR - as a long, or as a double, assuming the raw data is described - by type TYPE. Knows how to convert different sizes of values - and can convert between fixed and floating point. - - C++: It is assumed that the front-end has taken care of - all matters concerning pointers to members. A pointer - to member which reaches here is considered to be equivalent - to an INT (or some size). After all, it is only an offset. */ - -LONGEST -unpack_long (type, valaddr) - struct type *type; - char *valaddr; -{ - register enum type_code code = TYPE_CODE (type); - register int len = TYPE_LENGTH (type); - register int nosign = TYPE_UNSIGNED (type); - - if (code == TYPE_CODE_ENUM) - code = TYPE_CODE_INT; - if (code == TYPE_CODE_FLT) - { - if (len == sizeof (float)) - return * (float *) valaddr; - - if (len == sizeof (double)) - return * (double *) valaddr; - } - else if (code == TYPE_CODE_INT && nosign) - { - if (len == sizeof (char)) - return * (unsigned char *) valaddr; - - if (len == sizeof (short)) - return * (unsigned short *) valaddr; - - if (len == sizeof (int)) - return * (unsigned int *) valaddr; - - if (len == sizeof (long)) - return * (unsigned long *) valaddr; - } - else if (code == TYPE_CODE_INT) - { - if (len == sizeof (char)) - return * (char *) valaddr; - - if (len == sizeof (short)) - return * (short *) valaddr; - - if (len == sizeof (int)) - return * (int *) valaddr; - - if (len == sizeof (long)) - return * (long *) valaddr; - -#ifdef LONG_LONG - if (len == sizeof (long long)) - return * (long long *) valaddr; -#endif - } - else if (code == TYPE_CODE_PTR - || code == TYPE_CODE_REF) - { - if (len == sizeof (char *)) - return (CORE_ADDR) * (char **) valaddr; - } - else if (code == TYPE_CODE_MEMBER) - error ("not implemented: member types in unpack_long"); - - error ("Value not integer or pointer."); -} - -/* Return a double value from the specified type and address. - * INVP points to an int which is set to 0 for valid value, - * 1 for invalid value (bad float format). In either case, - * the returned double is OK to use. */ - -double -unpack_double (type, valaddr, invp) - struct type *type; - char *valaddr; - int *invp; -{ - register enum type_code code = TYPE_CODE (type); - register int len = TYPE_LENGTH (type); - register int nosign = TYPE_UNSIGNED (type); - - *invp = 0; /* Assume valid */ - if (code == TYPE_CODE_FLT) - { - if (INVALID_FLOAT (valaddr, len)) { - *invp = 1; - return 1.234567891011121314; - } - - if (len == sizeof (float)) - return * (float *) valaddr; - - if (len == sizeof (double)) - { - /* Some machines require doubleword alignment for doubles. - This code works on them, and on other machines. */ - double temp; - bcopy ((char *) valaddr, (char *) &temp, sizeof (double)); - return temp; - } - } - else if (code == TYPE_CODE_INT && nosign) - { - if (len == sizeof (char)) - return * (unsigned char *) valaddr; - - if (len == sizeof (short)) - return * (unsigned short *) valaddr; - - if (len == sizeof (int)) - return * (unsigned int *) valaddr; - - if (len == sizeof (long)) - return * (unsigned long *) valaddr; - -#ifdef LONG_LONG - if (len == sizeof (long long)) - return * (unsigned long long *) valaddr; -#endif - } - else if (code == TYPE_CODE_INT) - { - if (len == sizeof (char)) - return * (char *) valaddr; - - if (len == sizeof (short)) - return * (short *) valaddr; - - if (len == sizeof (int)) - return * (int *) valaddr; - - if (len == sizeof (long)) - return * (long *) valaddr; - -#ifdef LONG_LONG - if (len == sizeof (long long)) - return * (long long *) valaddr; -#endif - } - - error ("Value not floating number."); -} - -/* Given a value ARG1 of a struct or union type, - extract and return the value of one of its fields. - FIELDNO says which field. - - For C++, must also be able to return values from static fields */ - -value -value_field (arg1, fieldno) - register value arg1; - register int fieldno; -{ - register value v; - register struct type *type = TYPE_FIELD_TYPE (VALUE_TYPE (arg1), fieldno); - register int offset; - - /* Handle packed fields */ - - offset = TYPE_FIELD_BITPOS (VALUE_TYPE (arg1), fieldno) / 8; - if (TYPE_FIELD_BITSIZE (VALUE_TYPE (arg1), fieldno)) - { - v = value_from_long (type, - (LONGEST) unpack_field_as_long (VALUE_TYPE (arg1), - VALUE_CONTENTS (arg1), - fieldno)); - VALUE_BITPOS (v) = TYPE_FIELD_BITPOS (VALUE_TYPE (arg1), fieldno) % 8; - VALUE_BITSIZE (v) = TYPE_FIELD_BITSIZE (VALUE_TYPE (arg1), fieldno); - } - else - { - v = allocate_value (type); - bcopy (VALUE_CONTENTS (arg1) + offset, - VALUE_CONTENTS (v), - TYPE_LENGTH (type)); - } - VALUE_LVAL (v) = VALUE_LVAL (arg1); - if (VALUE_LVAL (arg1) == lval_internalvar) - VALUE_LVAL (v) = lval_internalvar_component; - VALUE_ADDRESS (v) = VALUE_ADDRESS (arg1); - VALUE_OFFSET (v) = offset + VALUE_OFFSET (arg1); - return v; -} - -value -value_fn_field (arg1, fieldno, subfieldno) - register value arg1; - register int fieldno; -{ - register value v; - struct fn_field *f = TYPE_FN_FIELDLIST1 (VALUE_TYPE (arg1), fieldno); - register struct type *type = TYPE_FN_FIELD_TYPE (f, subfieldno); - struct symbol *sym; - - sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, subfieldno), - 0, VAR_NAMESPACE, 0); - if (! sym) error ("Internal error: could not find physical method named %s", - TYPE_FN_FIELD_PHYSNAME (f, subfieldno)); - - v = allocate_value (type); - VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)); - VALUE_TYPE (v) = type; - return v; -} - -/* Return a virtual function as a value. - ARG1 is the object which provides the virtual function - table pointer. - F is the list of member functions which contains the desired virtual - function. - J is an index into F which provides the desired virtual function. - TYPE is the basetype which first provides the virtual function table. */ -value -value_virtual_fn_field (arg1, f, j, type) - value arg1; - struct fn_field *f; - int j; - struct type *type; -{ - /* First, get the virtual function table pointer. That comes - with a strange type, so cast it to type `pointer to long' (which - should serve just fine as a function type). Then, index into - the table, and convert final value to appropriate function type. */ - value vfn, vtbl; - value vi = value_from_long (builtin_type_int, - (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j)); - VALUE_TYPE (arg1) = TYPE_VPTR_BASETYPE (type); - - /* This type may have been defined before its virtual function table - was. If so, fill in the virtual function table entry for the - type now. */ - if (TYPE_VPTR_FIELDNO (type) < 0) - TYPE_VPTR_FIELDNO (type) - = fill_in_vptr_fieldno (type); - - /* Pretend that this array is just an array of pointers to integers. - This will have to change for multiple inheritance. */ - vtbl = value_copy (value_field (arg1, TYPE_VPTR_FIELDNO (type))); - VALUE_TYPE (vtbl) = lookup_pointer_type (builtin_type_int); - - /* Index into the virtual function table. */ - vfn = value_subscript (vtbl, vi); - - /* Reinstantiate the function pointer with the correct type. */ - VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j)); - return vfn; -} - -/* The value of a static class member does not depend - on its instance, only on its type. If FIELDNO >= 0, - then fieldno is a valid field number and is used directly. - Otherwise, FIELDNAME is the name of the field we are - searching for. If it is not a static field name, an - error is signaled. TYPE is the type in which we look for the - static field member. */ -value -value_static_field (type, fieldname, fieldno) - register struct type *type; - char *fieldname; - register int fieldno; -{ - register value v; - struct symbol *sym; - - if (fieldno < 0) - { - register struct type *t = type; - /* Look for static field. */ - while (t) - { - int i; - for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--) - if (! strcmp (TYPE_FIELD_NAME (t, i), fieldname)) - { - if (TYPE_FIELD_STATIC (t, i)) - { - fieldno = i; - goto found; - } - else - error ("field `%s' is not static"); - } - t = TYPE_BASECLASSES (t) ? TYPE_BASECLASS (t, 1) : 0; - } - - t = type; - - if (destructor_name_p (fieldname, t)) - error ("use `info method' command to print out value of destructor"); - - while (t) - { - int i, j; - - for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; i--) - { - if (! strcmp (TYPE_FN_FIELDLIST_NAME (t, i), fieldname)) - { - error ("use `info method' command to print value of method \"%s\"", fieldname); - } - } - t = TYPE_BASECLASSES (t) ? TYPE_BASECLASS (t, 1) : 0; - } - error("there is no field named %s", fieldname); - } - - found: - - sym = lookup_symbol (TYPE_FIELD_STATIC_PHYSNAME (type, fieldno), - 0, VAR_NAMESPACE, 0); - if (! sym) error ("Internal error: could not find physical static variable named %s", TYPE_FIELD_BITSIZE (type, fieldno)); - - type = TYPE_FIELD_TYPE (type, fieldno); - v = value_at (type, (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym)); - return v; -} - -long -unpack_field_as_long (type, valaddr, fieldno) - struct type *type; - char *valaddr; - int fieldno; -{ - long val; - int bitpos = TYPE_FIELD_BITPOS (type, fieldno); - int bitsize = TYPE_FIELD_BITSIZE (type, fieldno); - - bcopy (valaddr + bitpos / 8, &val, sizeof val); - - /* Extracting bits depends on endianness of the target machine. */ -#ifdef BITS_BIG_ENDIAN - val = val >> (sizeof val * 8 - bitpos % 8 - bitsize); -#else - val = val >> (bitpos % 8); -#endif - - val &= (1 << bitsize) - 1; - return val; -} - -void -modify_field (addr, fieldval, bitpos, bitsize) - char *addr; - int fieldval; - int bitpos, bitsize; -{ - long oword; - - bcopy (addr, &oword, sizeof oword); - - /* Shifting for bit field depends on endianness of the target machine. */ -#ifdef BITS_BIG_ENDIAN - bitpos = sizeof oword * 8 - bitpos - bitsize; -#endif - - oword &= ~(((1 << bitsize) - 1) << bitpos); - oword |= fieldval << bitpos; - bcopy (&oword, addr, sizeof oword); -} - -/* Convert C numbers into newly allocated values */ - -value -value_from_long (type, num) - struct type *type; - register LONGEST num; -{ - register value val = allocate_value (type); - register enum type_code code = TYPE_CODE (type); - register int len = TYPE_LENGTH (type); - - if (code == TYPE_CODE_INT || code == TYPE_CODE_ENUM) - { - if (len == sizeof (char)) - * (char *) VALUE_CONTENTS (val) = num; - else if (len == sizeof (short)) - * (short *) VALUE_CONTENTS (val) = num; - else if (len == sizeof (int)) - * (int *) VALUE_CONTENTS (val) = num; - else if (len == sizeof (long)) - * (long *) VALUE_CONTENTS (val) = num; -#ifdef LONG_LONG - else if (len == sizeof (long long)) - * (long long *) VALUE_CONTENTS (val) = num; -#endif - else - error ("Integer type encountered with unexpected data length."); - } - else - error ("Unexpected type encountered for integer constant."); - - return val; -} - -value -value_from_double (type, num) - struct type *type; - double num; -{ - register value val = allocate_value (type); - register enum type_code code = TYPE_CODE (type); - register int len = TYPE_LENGTH (type); - - if (code == TYPE_CODE_FLT) - { - if (len == sizeof (float)) - * (float *) VALUE_CONTENTS (val) = num; - else if (len == sizeof (double)) - * (double *) VALUE_CONTENTS (val) = num; - else - error ("Floating type encountered with unexpected data length."); - } - else - error ("Unexpected type encountered for floating constant."); - - return val; -} - -/* Deal with the value that is "about to be returned". */ - -/* Return the value that a function returning now - would be returning to its caller, assuming its type is VALTYPE. - RETBUF is where we look for what ought to be the contents - of the registers (in raw form). This is because it is often - desirable to restore old values to those registers - after saving the contents of interest, and then call - this function using the saved values. - struct_return is non-zero when the function in question is - using the structure return conventions on the machine in question; - 0 when it is using the value returning conventions (this often - means returning pointer to where structure is vs. returning value). */ - -value -value_being_returned (valtype, retbuf, struct_return) - register struct type *valtype; - char retbuf[REGISTER_BYTES]; - int struct_return; -{ - register value val; - - if (struct_return) - return value_at (valtype, EXTRACT_STRUCT_VALUE_ADDRESS (retbuf)); - - val = allocate_value (valtype); - EXTRACT_RETURN_VALUE (valtype, retbuf, VALUE_CONTENTS (val)); - - return val; -} - -/* Return true if the function specified is using the structure returning - convention on this machine to return arguments, or 0 if it is using - the value returning convention. FUNCTION is the value representing - the function, FUNCADDR is the address of the function, and VALUE_TYPE - is the type returned by the function */ - -struct block *block_for_pc (); - -int -using_struct_return (function, funcaddr, value_type) - value function; - CORE_ADDR funcaddr; - struct type *value_type; -{ - register enum type_code code = TYPE_CODE (value_type); - - if (code == TYPE_CODE_STRUCT || - code == TYPE_CODE_ENUM || - code == TYPE_CODE_ARRAY) - { - struct block *b = block_for_pc (funcaddr); - - if (!(BLOCK_GCC_COMPILED (b) && TYPE_LENGTH (value_type) < 8)) - return 1; - } - - return 0; -} - -/* Store VAL so it will be returned if a function returns now. - Does not verify that VAL's type matches what the current - function wants to return. */ - -void -set_return_value (val) - value val; -{ - register enum type_code code = TYPE_CODE (VALUE_TYPE (val)); - char regbuf[REGISTER_BYTES]; - double dbuf; - LONGEST lbuf; - - if (code == TYPE_CODE_STRUCT - || code == TYPE_CODE_UNION) - error ("Specifying a struct or union return value is not supported."); - - if (code == TYPE_CODE_FLT) - { - dbuf = value_as_double (val); - - STORE_RETURN_VALUE (VALUE_TYPE (val), &dbuf); - } - else - { - lbuf = value_as_long (val); - STORE_RETURN_VALUE (VALUE_TYPE (val), &lbuf); - } -} - -void -_initialize_values () -{ - add_info ("convenience", convenience_info, - "Debugger convenience (\"$foo\") variables.\n\ -These variables are created when you assign them values;\n\ -thus, \"print $foo=1\" gives \"$foo\" the value 1. Values may be any type.\n\n\ -A few convenience variables are given values automatically GDB:\n\ -\"$_\"holds the last address examined with \"x\" or \"info lines\",\n\ -\"$__\" holds the contents of the last address examined with \"x\"."); - - add_info ("history", history_info, - "Elements of value history (around item number IDX, or last ten)."); -} - -@ - - -1.1 -log -@Initial revision -@ -text -@d182 2 -a183 1 - register int i; -d185 6 -a190 3 - /* Get error now if about to store an invalid float. */ - if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FLT) - value_as_double (val); -d427 7 -a433 1 - return unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val)); -d510 5 -d516 1 -a516 1 -unpack_double (type, valaddr) -d519 1 -d525 1 -d528 4 -a531 2 - if (INVALID_FLOAT (valaddr, len)) - error ("Invalid floating value found in program."); -a770 1 - union { int i; char c; } test; -d774 6 -a779 7 - /* Extracting bits depends on endianness of the machine. */ - test.i = 1; - if (test.c == 1) - /* Little-endian. */ - val = val >> (bitpos % 8); - else - val = val >> (sizeof val * 8 - bitpos % 8 - bitsize); -a791 1 - union { int i; char c; } test; -d795 4 -a798 5 - /* Shifting for bit field depends on endianness of the machine. */ - test.i = 1; - if (test.c != 1) - /* not little-endian: assume big-endian. */ - bitpos = sizeof oword * 8 - bitpos - bitsize; -@ diff --git a/gdb/README b/gdb/README index d45a905ee1..633b4f9ba4 100644 --- a/gdb/README +++ b/gdb/README @@ -1,30 +1,127 @@ -This is GDB, a source-level debugger intended for GNU, -presently running under un*x. +This is GDB, the GNU source-level debugger, presently running under un*x. -Before compiling GDB, you must set up links to five files according to -the kind of machine you are running on. To do this, type `config.gdb -machine', where machine is something like `vax' or `sun2'. This -creates links named `param.h', `opcode.h', `pinsn.c', and `infdep.c'. +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. -About the machine-dependent files... +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 Pascal +and FORTRAN programs, 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++. + +About -gg format... + +Currently GDB version 3.x does *not* support GCC's -gg format. This +is because it is (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. -m-.h +About the machine-dependent files... +m-.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. --opcode.h, -pinsn.c +-opcode.h (opcode.h is a link to this file). +-pinsn.c (pinsn.c is a link to this file). These files contain the information necessary to print instructions for your cpu type. --dep.c +-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 usually 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 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 a.out 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 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 @@ -41,27 +138,3 @@ 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. -About languages other than C... - -C++ support has been integrated into gdb; it works, but somewhat -buggily. Pascal support has not yet been integrated in gdb; the work -is being done. - -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. - -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. - diff --git a/gdb/TAGS b/gdb/TAGS new file mode 100644 index 0000000000..b26ef5c1c9 --- /dev/null +++ b/gdb/TAGS @@ -0,0 +1,2089 @@ + +dbxread.c,2354 +#define IGNORE_SYMBOL(164,4914 +#define IGNORE_SYMBOL(169,5028 +#define MAX_OF_TYPE(4957,136182 +#define MIN_OF_TYPE(4958,136235 +#define READ_FILE_HEADERS(211,6321 +#define READ_FILE_HEADERS(218,6571 +#define READ_STRING_TABLE_SIZE(197,5872 +#define SET_ELEMENT_P(85,2728 +#define STAB_REG_TO_REGNUM(264,8007 +#define TYPE_OF_SET_ELEMENT(86,2788 +_initialize_dbxread 5237,144381 +add_bincl_to_list 1824,50638 +add_file_command 3525,97352 +add_new_header_file 686,20412 +add_old_header_file 657,19394 +add_symbol_to_list 867,25287 +add_this_object_header_file 637,18767 +add_undefined_type 3904,108372 +cleanup_undefined_types 3920,108815 +compare_misc_functions 1399,39494 +compare_psymbols 2571,70005 +compare_symbols 1487,41458 +condense_addl_misc_bunches 3322,91797 +condense_misc_bunches 1428,40167 +copy_pending 5201,143523 +dbx_alloc_type 814,24174 +dbx_create_type 797,23649 +dbx_lookup_type 746,22223 +define_symbol 3661,100810 +discard_misc_bunches 1412,39806 +end_psymtab 2595,70719 +end_symtab 1207,34565 +explicit_lookup_type 846,24755 +fill_in_vptr_fieldno 5189,143190 +fill_symbuf 1764,48931 +find_corresponding_bincl_psymtab 1849,51331 +finish_block 932,26830 +fix_common_block 5223,144077 + for 2521,68680 +free_bincl_list 1867,51719 +free_header_files 612,18133 +get_sym_file 1740,48273 +hash_symsegs 3059,84015 +hashname 3032,83492 +init_bincl_list 1812,50383 +init_header_files 599,17782 +init_misc_functions 1361,38562 +init_psymbol_list 1793,49686 +make_blockvector 1023,29323 +new_object_header_files 626,18495 +next_symbol_text 1780,49407 +obconcat 508,14582 +obsavestring 486,14075 +pop_subfile 1319,37721 +process_one_symbol 3090,84833 +psymtab_to_symtab(2736,74790 +psymtab_to_symtab_1 2673,73083 +push_subfile 1305,37370 +read_addl_syms 3365,92819 +read_args 5147,142033 +read_array_type 4797,131732 +read_dbx_symtab 1891,52496 +read_enum_type 4874,133737 +read_number 5108,141320 +read_ofile_symtab 2918,79777 +read_range_type 4961,136307 +read_struct_type 4300,118149 +read_type 3997,110898 +read_type_number 3970,110243 +really_free_pendings 896,26045 +record_line 1065,30528 +record_misc_function 1369,38676 +scan_file_globals 2845,77745 +sort_syms 1508,42042 +sort_symtab_syms 1517,42168 +start_psymtab 2540,69215 +start_subfile 1149,32781 +start_symtab 1096,31315 +symbol_file_command 1557,43492 +xxmalloc 470,13738 + +blockframe.c,647 +#define FRAMELESS_LOOK_FOR_PROLOGUE(163,4369 +_initialize_blockframe 587,15557 +block_for_pc 351,9907 +block_innermost_frame 566,15144 +create_new_frame 80,2165 +find_pc_function 422,11439 +find_pc_misc_function 521,13741 +find_pc_partial_function 437,11845 +flush_cached_frames 132,3234 +get_current_block 311,9005 +get_current_frame 64,1933 +get_frame_block 301,8854 +get_frame_function 336,9578 +get_frame_info 149,3857 +get_frame_pc 279,8317 +get_frame_saved_regs 290,8505 +get_next_frame 120,3036 +get_pc_function_start 317,9077 +get_prev_frame 108,2779 +get_prev_frame_info 186,5408 +outside_startup_file 41,1369 +set_current_frame 73,2085 + +breakpoint.c,1353 +#define ALL_BREAKPOINTS(79,2818 +_initialize_breakpoint 1222,29424 +break_command 783,19872 +break_command_1 676,17146 +breakpoint_1 425,11273 +breakpoint_auto_delete 934,23503 +breakpoint_cond_eval 349,9392 +breakpoint_here_p 333,9062 +breakpoint_stop_status 364,9891 +breakpoints_info 490,12855 +check_duplicates 555,14367 +clear_breakpoint_commands 236,6805 +clear_breakpoints 1010,25078 +clear_command 855,21469 +clear_momentary_breakpoints 626,15940 +commands_command 166,4928 +condition_command 116,3841 +decode_line_spec_1 1195,28751 +delete_breakpoint 951,23808 +delete_command 984,24430 +describe_other_breakpoints 509,13241 +disable_breakpoint 1136,27694 +disable_command 1148,27923 +do_breakpoint_commands 218,6245 +enable_breakpoint 1112,27251 +enable_command 1124,27477 +enable_delete_breakpoint 1176,28408 +enable_delete_command 1185,28545 +enable_once_breakpoint 1160,28152 +enable_once_command 1169,28290 +get_breakpoint_commands 247,7090 +ignore_command 1050,25970 +insert_breakpoints 265,7481 +map_breakpoint_numbers 1077,26570 +mark_breakpoints_out 320,8751 +remove_breakpoints 291,8118 +set_breakpoint 642,16292 +set_breakpoint_commands 253,7157 +set_default_breakpoint 538,13897 +set_ignore_count 1020,25303 +set_momentary_breakpoint 614,15691 +set_raw_breakpoint 576,14887 +tbreak_command 791,19992 +until_break_command 803,20231 + +dbxread.c,2354 +#define IGNORE_SYMBOL(164,4914 +#define IGNORE_SYMBOL(169,5028 +#define MAX_OF_TYPE(4957,136182 +#define MIN_OF_TYPE(4958,136235 +#define READ_FILE_HEADERS(211,6321 +#define READ_FILE_HEADERS(218,6571 +#define READ_STRING_TABLE_SIZE(197,5872 +#define SET_ELEMENT_P(85,2728 +#define STAB_REG_TO_REGNUM(264,8007 +#define TYPE_OF_SET_ELEMENT(86,2788 +_initialize_dbxread 5237,144381 +add_bincl_to_list 1824,50638 +add_file_command 3525,97352 +add_new_header_file 686,20412 +add_old_header_file 657,19394 +add_symbol_to_list 867,25287 +add_this_object_header_file 637,18767 +add_undefined_type 3904,108372 +cleanup_undefined_types 3920,108815 +compare_misc_functions 1399,39494 +compare_psymbols 2571,70005 +compare_symbols 1487,41458 +condense_addl_misc_bunches 3322,91797 +condense_misc_bunches 1428,40167 +copy_pending 5201,143523 +dbx_alloc_type 814,24174 +dbx_create_type 797,23649 +dbx_lookup_type 746,22223 +define_symbol 3661,100810 +discard_misc_bunches 1412,39806 +end_psymtab 2595,70719 +end_symtab 1207,34565 +explicit_lookup_type 846,24755 +fill_in_vptr_fieldno 5189,143190 +fill_symbuf 1764,48931 +find_corresponding_bincl_psymtab 1849,51331 +finish_block 932,26830 +fix_common_block 5223,144077 + for 2521,68680 +free_bincl_list 1867,51719 +free_header_files 612,18133 +get_sym_file 1740,48273 +hash_symsegs 3059,84015 +hashname 3032,83492 +init_bincl_list 1812,50383 +init_header_files 599,17782 +init_misc_functions 1361,38562 +init_psymbol_list 1793,49686 +make_blockvector 1023,29323 +new_object_header_files 626,18495 +next_symbol_text 1780,49407 +obconcat 508,14582 +obsavestring 486,14075 +pop_subfile 1319,37721 +process_one_symbol 3090,84833 +psymtab_to_symtab(2736,74790 +psymtab_to_symtab_1 2673,73083 +push_subfile 1305,37370 +read_addl_syms 3365,92819 +read_args 5147,142033 +read_array_type 4797,131732 +read_dbx_symtab 1891,52496 +read_enum_type 4874,133737 +read_number 5108,141320 +read_ofile_symtab 2918,79777 +read_range_type 4961,136307 +read_struct_type 4300,118149 +read_type 3997,110898 +read_type_number 3970,110243 +really_free_pendings 896,26045 +record_line 1065,30528 +record_misc_function 1369,38676 +scan_file_globals 2845,77745 +sort_syms 1508,42042 +sort_symtab_syms 1517,42168 +start_psymtab 2540,69215 +start_subfile 1149,32781 +start_symtab 1096,31315 +symbol_file_command 1557,43492 +xxmalloc 470,13738 + +coffread.c,1153 +_initialize_coff 1997,51184 +add_symbol_to_list 239,6659 +coff_alloc_type 216,6044 +coff_lookup_type 191,5303 +compare_misc_functions 574,15824 +compare_symbols 643,17250 +complete_symtab 420,11661 +condense_misc_bunches 600,16328 +decode_base_type 1695,43602 +decode_function_type 1680,43270 +decode_type 1611,41633 +discard_misc_bunches 587,16136 +end_symtab 443,12339 +enter_linenos 1325,33811 +fill_in_vptr_fieldno 1976,50629 +finish_block 255,7053 +free_stringtab 1244,32313 +get_sym_file 830,22060 +getfilename 1272,32775 +getsymname 1252,32409 +hashname 1349,34504 +init_lineno 1301,33409 +init_misc_functions 530,14772 +init_stringtab 1207,31526 +make_blockvector 334,9209 +patch_opaque_types 1397,35664 +patch_type 1370,34784 +process_coff_symbol 1458,37365 +psymtab_to_symtab 1989,50997 +read_aout_hdr 1143,30011 +read_coff_symtab 853,22645 +read_enum_type 1894,48302 +read_file_hdr 1106,29439 +read_one_sym 1177,30725 +read_section_hdr 1156,30264 +read_struct_type 1799,45905 +record_line 372,10317 +record_misc_function 538,14886 +sort_syms 655,17641 +start_symtab 397,10969 +symbol_file_command 680,18217 +unrecord_misc_function 563,15633 + +command.c,359 +_initialize_command 851,22915 +add_abbrev_cmd 63,1983 +add_abbrev_prefix_cmd 145,4172 +add_alias_cmd 88,2538 +add_cmd 36,1377 +add_prefix_cmd 124,3597 +complete_on_cmdlist 766,21180 +delete_cmd 167,4742 +help_cmd 202,5546 +help_cmd_list 321,9084 +help_list 261,7260 +lookup_cmd 517,15044 +lookup_cmd 633,18122 +lookup_cmd_1 397,11731 +shell_escape 815,22224 + +core.c,428 +#define N_DATADDR(60,1462 +#define N_MAGIC(37,1073 +#define N_MAGIC(39,1116 +#define N_TXTADDR(56,1392 +_initialize_core(501,11926 +close_exec_file 161,3640 +files_info 222,4960 +get_exec_file 206,4709 +have_core_file_p 216,4899 +myread 457,11172 +read_memory 274,6239 +register_addr 484,11657 +reopen_exec_file 169,3729 +specify_exec_file_hook 150,3406 +validate_files 185,4128 +write_memory 298,6798 +xfer_core_file 324,7539 + +environ.c,205 +environ_vector 87,2273 +free_environ 41,1270 +get_in_environ 96,2408 +init_environ 57,1597 +make_environ 26,972 +#define max(19,848 +#define min(18,806 +set_in_environ 115,2743 +unset_in_environ 155,3497 + +eval.c,320 +evaluate_expression 119,3366 +evaluate_subexp 138,3760 +evaluate_subexp_for_address 888,25910 +evaluate_subexp_for_sizeof 983,28436 +evaluate_subexp_with_coercion 951,27623 +evaluate_type 130,3614 +parse_and_eval 62,1782 +parse_and_eval_address 31,978 +parse_and_eval_address_1 48,1452 +parse_to_comma_and_eval 80,2239 + +expprint.c,49 +print_expression 91,3166 +print_subexp 105,3561 + +findvar.c,319 +find_saved_register 34,1194 +locate_var_value 489,13624 +read_register 207,6246 +read_register_bytes 181,5670 +read_relative_register_raw_bytes 104,3552 +read_var_value 250,7313 +supply_register 238,6995 +value_from_register 324,8965 +value_of_register 138,4309 +write_register 217,6487 +write_register_bytes 193,5953 + +infcmd.c,711 +_initialize_infcmd 1000,23564 +attach_command 879,21184 +cont_command 195,4400 +detach_command 948,22621 +environment_info 596,13961 +finish_command 509,11745 +float_info 987,23343 +have_inferior_p 113,2973 +jump_command 314,6947 +next_command 232,5120 +nexti_command 246,5322 +program_info 574,13352 +read_memory_integer 695,16288 +read_pc 751,17739 +registers_info 769,18009 +run_command 139,3401 +run_stack_dummy 409,9239 +set_args_command 119,3038 +set_environment_command 616,14363 +signal_command 367,8069 +step_1 252,5399 +step_command 224,4968 +stepi_command 240,5245 +tty_command 128,3179 +unset_environment_command 676,15776 +until_command 492,11379 +until_next_command 445,10390 +write_pc 757,17808 + +inflow.c,335 +_initialize_inflow 500,11655 +create_inferior 365,8512 +inferior_died 459,10830 +kill_command 447,10602 +new_tty 323,7661 +term_status_command 272,6237 +terminal_inferior 140,3148 +terminal_init_inferior 109,2609 +terminal_ours 193,4436 +terminal_ours_1 202,4530 +terminal_ours_for_output 180,4199 +try_writing_regs_command 474,11137 + +infrun.c,422 +_initialize_infrun 1340,40505 +attach_program 423,12649 +clear_proceed_status 238,7822 +handle_command 1135,33944 +insert_step_breakpoint 1113,33367 +normal_stop 1005,30118 +proceed 266,8680 +remove_step_breakpoint 1125,33669 +restore_inferior_status 1294,39027 +save_inferior_status 1263,37798 +signals_info 1222,36546 +start_inferior 358,11034 +start_remote 405,12289 +wait_for_inferior 447,13290 +writing_pc 345,10713 + +kdb-start.c,14 +start 29,911 + +main.c,1395 +#define ISATTY(47,1291 +add_com 1066,26905 +add_com_alias 1078,27132 +add_info 1034,26190 +add_info_alias 1045,26383 +catch_errors 177,4170 +catch_termination 763,19120 +cd_command 1318,32114 +command_line_input 818,20970 +command_loop 495,12271 +define_command 1124,27925 +disconnect 207,4712 +do_nothing 488,12171 +document_command 1164,28926 +dont_repeat 519,12935 +dump_me_command 1433,34141 +echo_command 1407,33757 +editing_info 1482,35163 +error_no_arg 1088,27330 +execute_command 445,11096 +float_handler 1665,39616 +free_command_lines 1016,25881 +gdb_readline 536,13456 +help_command 1095,27424 +info_command 1057,26711 +initialize_cmd_lists 1672,39713 +initialize_main 1686,40170 +initialize_signals 778,19567 +input_from_terminal_p 1297,31668 +main 231,5192 +parse_binary_operation 1443,34288 +print_gdb_version 1209,29850 +print_prompt 1229,30348 +pwd_command 1303,31739 +quit_command 1276,31154 +read_command_lines 965,24579 +return_to_top_level 160,3706 +set_editing 1472,34921 +set_history 1596,38350 +set_history_expansion 1580,38024 +set_history_filename 1616,38738 +set_history_size 1605,38571 +set_history_write 1588,38193 +set_prompt_command 1238,30489 +set_verbose_command 1645,39221 +source_cleanup 220,5004 +source_command 1378,33251 +stop_sig 711,17950 +symbol_completion_function 603,15200 +validate_comname 1103,27558 +verbose_info 1653,39371 +version_info 1219,30200 + +printcmd.c,943 +_initialize_printcmd 1623,38100 +address_info 592,13980 +clear_displays 914,21618 +compare_ints 1208,27665 +containing_function_bounds 1537,35960 +decode_format 80,2251 +delete_display 929,21829 +disable_current_display 1082,25057 +disable_display 1067,24819 +disable_display_command 1160,26792 +disassemble_command 1563,36620 +display_command 851,20435 +display_info 1094,25338 +do_displays 1055,24569 +do_examine 432,10303 +do_one_display 1000,23202 +enable_display 1121,26123 +free_display 902,21400 +output_command 553,13174 +print_address 404,9676 +print_command 513,12305 +print_formatted 175,4422 +print_frame_args 1221,27981 +print_frame_nameless_args 1306,30230 +print_scalar_formatted 218,5618 +print_variable_value 1198,27446 +printf_command 1331,30817 +ptype_command 766,18216 +set_command 581,13730 +set_next_address 389,9302 +undisplay_command 962,22446 +validate_format 498,11866 +whatis_command 738,17564 +x_command 678,15908 + +remote.c,714 +dcache_alloc 723,15623 +dcache_fetch 740,15991 +dcache_flush 671,14609 +dcache_hit 688,14901 +dcache_init 781,16876 +dcache_poke 757,16355 +dcache_value 709,15286 +fromhex 215,5113 +getpkt 595,12628 +putpkt 548,11720 +readchar 511,11081 +remote_close 193,4619 +remote_fetch_registers 276,6165 +remote_fetch_word 330,7185 +void remote_fetch_word 358,7686 +remote_open 142,3461 +remote_read_bytes 412,8989 +remote_read_inferior_memory(443,9668 +remote_resume 241,5502 +remote_send 533,11458 +remote_store_registers 302,6687 +remote_store_word 351,7569 +void remote_store_word 363,7803 +remote_timer 129,3258 +remote_wait 259,5776 +remote_write_bytes 377,8208 +remote_write_inferior_memory 467,10193 +tohex 229,5357 + +source.c,488 +_initialize_source 954,23365 +ambiguous_line_spec 575,13769 +directories_info 132,3510 +directory_command 156,4027 +find_source_lines 362,8523 +forward_search_command 807,19993 +get_filename_and_charpos 446,10571 +identify_source_line 478,11440 +init_source_path 138,3601 +line_info 747,18381 +list_command 587,14000 +openp 295,7020 +print_source_lines 502,12090 +reverse_search_command 877,21586 +select_source_symtab 68,2053 +source_charpos_line 420,9931 +source_line_charpos 406,9635 + +stack.c,657 +_initialize_stack 859,22042 +args_info 625,15676 +backtrace_command 432,11191 +backtrace_limit_info 418,10894 +down_command 792,20320 +find_relative_frame 682,17313 +frame_command 734,18898 +frame_info 308,8077 +get_selected_block 662,16609 +locals_info 569,14484 +parse_frame_specification 216,6084 +print_block_frame_locals 494,12726 +print_frame_arg_vars 578,14659 +print_frame_info 76,2220 +print_frame_local_vars 533,13684 +print_sel_frame 191,5582 +print_selected_frame 201,5792 +print_stack_frame 59,1892 +record_selected_frame 650,16289 +return_command 811,20839 +select_frame 636,15968 +set_backtrace_limit_command 405,10622 +up_command 767,19616 + +standalone.c,1177 +_exit 434,8321 +_flsbuf 323,6623 +_initialize_standalone 582,11467 +access 73,1514 +chdir 59,1359 +close 161,3995 +core_file_command 337,6799 +exec_file_command 334,6774 +execle 431,8307 +exit 78,1542 +fault 512,9751 +fclose 186,4368 +fdopen 180,4310 +fflush 328,6681 +fgetc 244,5237 +fopen 172,4185 +fprintf 295,6034 +fputc 311,6364 +fread 226,4925 +fstat 192,4418 +fwrite 302,6193 +get_exec_file 341,6831 +getpid 51,1314 +getrlimit 472,8793 +getwd 63,1379 +have_core_file_p 348,6964 +ioctl 42,1249 +kill 48,1302 +kill_command 353,7001 +lseek 263,5485 +malloc_warning 439,8363 +myread 205,4602 +open 126,3377 +printf 288,5881 +ptrace 425,8278 +read_inferior_register 370,7149 +read_memory 373,7179 +read_register 395,7552 +restore_gdb 526,10070 +resume 488,9217 +save_frame_pointer 500,9421 +save_registers 538,10415 +sbrk 449,8479 +setpgrp 428,8292 +int (* signal 45,1277 +sigsetmask 56,1341 +int kdb_stack_beg[STACK_SIZE / sizeof 579,11401 +terminal_inferior 358,7042 +terminal_init_inferior 364,7088 +terminal_ours 361,7067 +ulimit 461,8701 +vfork 415,7988 +vlimit 467,8743 +wait 552,10763 +write_inferior_register 367,7118 +write_memory 383,7352 +write_register 404,7721 + +stuff.c,69 +err 161,5059 +find_symbol 140,4492 +get_offset 96,2844 +main 31,990 + +symmisc.c,569 +#define CORE_RELOCATE(153,4445 +#define RELOCATE(143,4006 +#define TEXT_RELOCATE(157,4600 +#define UNRELOCATE(147,4201 +_initialize_symmisc 576,15724 +block_depth 556,15387 +free_all_psymtabs(568,15569 +free_all_symtabs 35,1081 +free_symtab 89,2472 +free_symtab_block 67,1765 +print_symbol 451,12817 +print_symtabs 383,11015 +read_symsegs 343,9859 +relocate_block 224,6565 +relocate_blockvector 212,6256 +relocate_source 321,9150 +relocate_sourcevector 309,8879 +relocate_symbol 249,7225 +relocate_symtab 178,5394 +relocate_type 290,8487 +relocate_typevector 270,7878 + +symtab.c,1477 +_initialize_symtab 2382,65276 +block_function 1102,30299 +compare_symbols 2173,59132 +completion_list_add_symbol 2239,60743 +contained_in 2224,60473 +create_array_type 604,16947 +decode_line_1 1438,39022 +decode_line_2 1800,49861 +decode_line_spec 1785,49470 +find_line_common 1354,36778 +find_line_pc 1289,34998 +find_line_pc_range 1311,35530 +find_pc_line 1155,31575 +find_pc_line_pc_range 1399,37601 +find_pc_psymbol 765,21363 +find_pc_psymtab 750,20994 +find_pc_symtab 1114,30525 +functions_info 2150,58796 +init_type 2196,59740 +list_symbols 1974,53807 +lookup_basetype_type 507,14022 +lookup_block_symbol 1007,27715 +lookup_enum 268,7169 +lookup_function_type 569,15751 +lookup_member_type 383,10719 +lookup_method_type 437,12136 +lookup_misc_func 1897,52101 +lookup_partial_symbol 945,26144 +lookup_partial_symtab 165,4536 +lookup_pointer_type 323,8661 +lookup_reference_type 350,9569 +lookup_struct 232,6203 +lookup_struct_elt_type 285,7648 +lookup_symbol 809,22646 +lookup_symtab 139,3934 +lookup_symtab_1 86,2715 +lookup_typename 183,4935 +lookup_union 250,6688 +lookup_unsigned_typename 214,5725 +make_symbol_completion_list 2264,61514 +methods_info 2164,58968 +output_source_filename 1912,52401 +smash_to_function_type 724,20334 +smash_to_member_type 658,18480 +smash_to_method_type 675,18938 +smash_to_pointer_type 631,17770 +smash_to_reference_type 695,19530 +sort_block_syms 2185,59523 +sources_info 1940,52854 +types_info 2157,58884 +variables_info 2143,58708 + +utils.c,893 +#define ISATTY(34,1102 +_initialize_utils 837,18051 +bcmp 738,16766 +bcopy 732,16693 +bzero 743,16830 +concat 315,7156 +discard_cleanups 96,2598 +do_cleanups 80,2219 +error 256,5801 +fatal 272,6217 +fatal_dump_core 286,6518 +fprintf_filtered 672,15357 +fputs_filtered 585,12889 +free_current_contents 134,3355 +getwd 750,16893 +index 757,16956 +insque 807,17512 +make_cleanup 60,1751 +parse_escape 384,8980 +perror_with_name 172,4138 +print_spaces 327,7398 +print_spaces_filtered 716,16465 +print_sys_errmsg 198,4697 +printchar 454,10140 +printf_filtered 707,16234 +prompt_for_continue 540,11786 +query 341,7762 +quit 221,5137 +reinitialize_more_filter 551,12021 +remque 818,17676 +request_quit 238,5472 +restore_cleanups 119,3077 +rindex 765,17038 +save_cleanups 109,2899 +savestring 304,6989 +screensize_info 558,12108 +set_screensize_command 500,11063 +xmalloc 145,3568 +xrealloc 157,3788 + +valarith.c,346 +binop_user_defined_p 169,4570 +int unop_user_defined_p 189,5306 +value_add 31,959 +value_binop 348,10305 +value_equal 579,14590 +value_less 623,15819 +value_lognot 668,17121 +value_neg 650,16710 +value_sub 70,1933 +value_subscript 105,2802 +value_subscripted_rvalue 119,3159 +value_x_binop 206,5888 +value_x_unop 294,8777 +value_zerop 555,14239 + +valops.c,539 +call_function 511,14326 +check_field 991,27349 +destructor_name_p 964,26652 +push_bytes 433,12639 +push_word 413,12273 +typecmp 1186,32205 +value_addr 354,10374 +value_arg_coerce 473,13432 +value_arg_push 496,13879 +value_assign 113,3260 +value_at 87,2594 +value_cast 33,1132 +value_coerce_array 326,9567 +value_ind 381,11139 +value_of_this 1214,32888 +value_of_variable 316,9365 +value_push 452,12980 +value_repeat 293,8780 +value_string 701,19888 +value_struct_elt 780,22216 +value_struct_elt_for_address 1072,29190 +value_zero 72,2297 + +valprint.c,462 +_initialize_valprint 1314,34466 +format_info 1297,34020 +is_nan 737,19321 +print_string 51,1540 +set_maximum_command 1274,33552 +set_prettyprint_command 1282,33721 +set_unionprint_command 1290,33878 +type_print 783,20553 +type_print_1 795,20784 +type_print_base 1076,28463 +type_print_derivation_info 862,22651 +type_print_method_args 824,21667 +type_print_varspec_prefix 917,24229 +type_print_varspec_suffix 985,25987 +val_print 250,6740 +value_print 132,3315 + +values.c,901 +_initialize_values 1015,26691 +access_value_history 216,5584 +allocate_repeat_value 81,2301 +allocate_value 56,1719 +clear_internalvars 417,10449 +clear_value_history 255,6544 +convenience_info 432,10685 +free_all_values 107,2964 +internalvar_name 407,10258 +lookup_internalvar 335,8628 +modify_field 842,21883 +record_latest_value 177,4455 +release_value 124,3231 +set_internalvar 392,9960 +set_internalvar_component 371,9411 +set_return_value 989,26139 +unpack_double 567,14138 +unpack_field_as_long 819,21371 +unpack_long 494,12354 +using_struct_return 964,25532 +value_as_double 471,11630 +value_as_long 464,11510 +value_being_returned 939,24782 +value_copy 150,3655 +value_field 648,16017 +value_fn_field 684,17059 +value_from_double 901,23472 +value_from_long 869,22598 +value_history_info 274,6953 +value_of_internalvar 354,9074 +value_static_field 757,19899 +value_virtual_fn_field 712,18047 + +version.c,0 + +expread.y,617 +_initialize_expread 1757,40919 +copy_name 1439,33557 +end_arglist 830,19836 +free_funcalls 844,20138 +length_of_subexp 1473,34461 +parse_c_1 1680,39165 +parse_c_expression 1725,40302 +parse_number 999,23497 +pop_type 1749,40813 +prefixify_expression 1453,33893 +prefixify_subexp 1559,36093 +push_type 1736,40511 +start_arglist 816,19477 +write_exp_elt 864,20582 +write_exp_elt_dblcst 911,21351 +write_exp_elt_intern 933,21638 +write_exp_elt_longcst 900,21206 +write_exp_elt_opcode 878,20912 +write_exp_elt_sym 889,21061 +write_exp_elt_type 922,21496 +write_exp_string 947,21920 +yyerror 1430,33402 +yylex 1140,26428 + +xgdb.c,449 +_initialize_xgdb 597,15714 +addbutton 353,8889 +breakpoint_button(259,7015 +create_buttons 378,9514 +create_label 405,10388 +create_text_widget 421,10789 +do_command(331,8518 +explicit_breakpoint_button 298,7825 +garbage 285,7558 +print_button(226,6200 +print_prompt 212,5888 +redisplay_button(345,8784 +xgdb_create_window 447,11503 +xgdb_dispatch 555,14814 +xgdb_display_exec_file 198,5604 +xgdb_display_source 90,2329 +xgdb_window_hook 588,15559 + +umax-dep.c,368 +#define N_DATADDR(301,7545 +#define N_TXTADDR(297,7475 +attach 100,2338 +call_ptrace 47,1366 +core_file_command 392,9598 +detach 116,2643 +exec_file_command 489,11999 +fetch_inferior_registers 128,2843 +kill_inferior 53,1489 +kill_inferior_fast 66,1722 +read_inferior_memory 197,4708 +resume 81,2008 +store_inferior_registers 153,3491 +write_inferior_memory 235,5820 + +gould-dep.c,333 +#define N_DATADDR(271,7135 +#define N_TXTADDR(267,7065 +call_ptrace 43,1273 +core_file_command 362,9188 +exec_file_command 454,11468 +fetch_inferior_registers 93,2171 +kill_inferior 49,1396 +kill_inferior_fast 62,1629 +read_inferior_memory 166,4258 +resume 77,1915 +store_inferior_registers 120,2930 +write_inferior_memory 204,5370 + +default-dep.c,331 +#define N_DATADDR(279,7305 +#define N_SET_MAGIC(42,1176 +#define N_TXTADDR(275,7235 +call_ptrace 55,1511 +core_file_command 370,9358 +exec_file_command 475,12049 +fetch_inferior_registers 105,2409 +kill_inferior 61,1634 +kill_inferior_fast 74,1867 +read_inferior_memory 172,4208 +resume 89,2153 +store_inferior_registers 132,3168 + +sun3-dep.c,402 +#define IS_OBJECT_FILE(313,8593 +#define N_DATADDR(303,8150 +#define N_TXTADDR(299,8080 +attach 102,2379 +call_ptrace 49,1407 +core_file_command 402,10637 +detach 118,2684 +exec_file_command 503,13724 +fetch_inferior_registers 130,2884 +kill_inferior 55,1530 +kill_inferior_fast 68,1763 +read_inferior_memory 203,5427 +resume 83,2049 +store_inferior_registers 166,4024 +write_inferior_memory 241,6539 + +sparc-dep.c,585 +#define IS_OBJECT_FILE(447,11886 +#define N_DATADDR(437,11443 +#define N_TXTADDR(433,11373 +attach 201,4808 +call_ptrace 56,1547 +core_file_command 537,13933 +detach 217,5113 +do_restore_insn 877,23985 +do_save_insn 833,22733 +exec_file_command 655,17493 +fetch_inferior_registers 229,5313 +frame_saved_pc 758,20229 +isannulled 983,26794 +kill_inferior 63,1675 +kill_inferior_fast 77,1913 +read_inferior_memory 337,8720 +resume 177,4387 +setup_arbitrary_frame 784,21093 +single_step 112,2764 +skip_prologue 906,24717 +store_inferior_registers 269,6777 +write_inferior_memory 375,9832 + +hp9k320-dep.c,481 +#define INFERIOR_AR0(97,2239 +#define N_DATADDR(367,9261 +#define N_TXTADDR(363,9191 + call_ptrace 48,1357 +core_file_command 458,11314 +exec_file_command 565,14072 + fetch_inferior_register 103,2395 + fetch_inferior_registers 188,4353 +kill_inferior 54,1477 +kill_inferior_fast 67,1710 +read_inferior_memory 256,6284 + resume 82,1996 + store_inferior_register 156,3596 + store_inferior_register_1 134,3103 +store_inferior_registers 211,5018 +write_inferior_memory 294,7396 + +hp300bsd-dep.c,200 +#define N_DATADDR(273,6789 +#define N_TXTADDR(269,6719 +core_file_command 362,8819 +exec_file_command 455,11105 + On failure 165,3796 +read_inferior_memory 169,3919 +write_inferior_memory 207,5039 + +news-dep.c,352 +#define N_DATADDR(310,8075 +#define N_TXTADDR(306,8005 +call_ptrace 45,1330 +core_file_command 401,10128 +exec_file_command 493,12408 +execle(629,15592 +fetch_inferior_registers 95,2228 +kill_inferior 51,1453 +kill_inferior_fast 64,1686 +read_inferior_memory 211,5351 +resume 79,1972 +store_inferior_registers 126,3079 +write_inferior_memory 249,6463 + +i386-dep.c,1058 +#define N_DATADDR(278,6990 +#define N_SET_MAGIC(45,1190 +#define N_SET_MAGIC(47,1250 +#define N_TXTADDR(274,6920 +#define U_FPSTATE(1141,28570 +call_ptrace 62,1570 +codestream_fill 578,14567 +#define codestream_get(574,14433 +#define codestream_peek(572,14324 +codestream_read 605,15129 +codestream_seek 595,14935 +#define codestream_tell(571,14263 +core_file_command 365,8994 +double_to_i387 980,24581 +exec_file_command 459,11340 +fetch_inferior_registers 112,2468 +i386_float_info 1144,28611 +i386_follow_jump 617,15344 +i386_frame_find_saved_regs 799,20070 +i386_get_frame_setup 666,16376 +i386_pop_frame 890,22067 +i386_push_dummy_frame 877,21711 +i386_register_u_addr 929,23064 +i386_skip_prologue 850,21208 +i387_to_double 950,23630 +kill_inferior 68,1693 +kill_inferior_fast 81,1926 +print_387_control_word 1014,25288 +print_387_status 1077,27021 +print_387_status_word 1051,26316 +read_inferior_memory 179,4266 +resume 96,2212 +static unsigned char codestream_buf[sizeof 567,14157 +store_inferior_registers 139,3227 +write_inferior_memory 217,5378 + +symmetry-dep.c,1106 +#define I386_REGNO_TO_SYMMETRY(698,18016 +#define N_DATADDR(343,9198 +#define N_TXTADDR(339,9128 +attach 114,2677 +call_ptrace 59,1703 +codestream_fill 652,16972 +#define codestream_get(647,16837 +#define codestream_peek(645,16728 +codestream_read 679,17534 +codestream_seek 669,17340 +#define codestream_tell(644,16667 +core_file_command 432,11245 +detach 130,2982 +double_to_i387 1048,26920 +exec_file_command 525,13637 +fetch_inferior_registers(208,4989 +i386_float_info 994,25379 +i386_follow_jump 1159,29727 +i386_frame_find_saved_regs 702,18143 +i386_get_frame_setup 1065,27297 +i386_skip_prologue 1203,30603 +i387_to_double 1018,25969 +kill_inferior 67,1828 +kill_inferior_fast 80,2061 +print_1167_control_word(875,22691 +print_1167_regs(950,24720 +print_387_control_word 754,19292 +print_387_status_word 791,20320 +print_fpa_status(979,25128 +print_fpu_status(816,21067 +read_inferior_memory 242,6503 +resume 95,2347 +round(625,16334 +static unsigned char codestream_buf[sizeof 640,16561 +store_inferior_registers(142,3178 +symmetry_extract_return_value(1230,31106 +write_inferior_memory 278,7596 + +convex-dep.c,1325 +_initialize_convex_dep 1883,49453 +alias_command 1562,40922 +attach 415,10525 +call_ptrace 297,7803 +comm_registers_info 1770,46540 +convex_cont_command 1749,45982 +core_file_command 891,22904 +create_inferior_hook 390,9929 +decout 1451,38265 +detach 437,10953 +exec_file_command 1061,27835 +execle 308,8054 +fetch_inferior_registers 328,8477 +is_trapped_internalvar 1323,34556 +kill_inferior 450,11200 +kill_inferior_fast 463,11439 +one_cont_command 1759,46207 +print_maps 1256,32700 +psw_info 1823,47727 +static ptr_cmp 1302,33801 +read_comm_register 576,14234 +read_inferior_memory 346,8915 +read_vector_register 476,11674 +read_vector_register_1 513,12817 +resume 616,15286 +scan_stack 856,22194 +select_thread 838,21692 +set_base_command 1494,39297 +set_fixed_scheduling 882,22743 +set_parallel_command 1532,40135 +set_pipelining_command 1513,39651 +set_thread_command 1717,45229 +set_trapped_internalvar 1423,37354 +static sig_noop 321,8315 +#define signal_stack_is_empty(164,4341 +store_inferior_registers 335,8634 +subsig_name 1650,43201 +thread_continue 643,16080 +thread_info 1620,42331 +threadstat 1699,44828 +value_of_trapped_internalvar 1345,35101 +vector_type 1408,36928 +wait 721,18383 +write_comm_register 595,14751 +write_inferior_memory 374,9507 +write_vector_register 534,13349 +xfer_core_file 1153,30129 + +altos-dep.c,363 +#define N_DATADDR(279,7070 +#define N_SET_MAGIC(50,1310 +#define N_TXTADDR(275,7000 +call_ptrace 63,1645 +core_file_command 370,9123 +exec_file_command 481,12020 +fetch_inferior_registers 113,2543 +kill_inferior 69,1768 +kill_inferior_fast 82,2001 +read_inferior_memory 180,4346 +resume 97,2287 +store_inferior_registers 140,3304 +write_inferior_memory 218,5458 + +gld-pinsn.c,79 +findarg(193,4447 +findframe(223,5160 +framechain(261,5966 +print_insn 40,1268 + +i386-pinsn.c,531 +OP_C 1751,33943 +OP_D 1759,34068 +OP_DIR 1678,32875 +OP_DSSI 1737,33781 +OP_E 1391,28097 +OP_ESDI 1729,33671 +OP_G 1506,29813 +OP_I 1584,31303 +OP_J 1636,32124 +OP_OFF 1715,33495 +OP_ONE 1745,33891 +OP_REG 1551,30489 +OP_SEG 1669,32749 +OP_ST 1315,26993 +OP_STi 1321,27047 +OP_T 1767,34193 +OP_indirE 1385,28035 +OP_rm 1774,34303 +OP_sI 1610,31706 +append_prefix 1369,27713 +ckprefix 843,18657 +dofloat 1278,26307 +get16 1542,30391 +get32 1531,30229 +i386dis 912,20222 +oappend 1361,27629 +print_insn 1795,34614 +putop 1329,27178 + +sparc-pinsn.c,73 +compare_opcodes 366,8423 +is_delayed_branch 75,1790 +print_insn 95,2205 + +vax-pinsn.c,44 +print_insn 41,1258 +print_insn_arg 85,2198 + +m68k-pinsn.c,408 +#define NEXTBYTE(45,1396 +#define NEXTDOUBLE(56,1661 +#define NEXTEXTEND(59,1719 +#define NEXTLONG(50,1513 +#define NEXTPACKED(63,1837 +#define NEXTSINGLE(53,1604 +#define NEXTWORD(47,1444 +_initialize_pinsn(860,19535 +convert_from_68881 785,18049 +convert_to_68881 821,18826 +fetch_arg 574,13657 +print_base 763,17494 +print_indexed 673,15446 +print_insn 73,2231 +print_insn_arg 167,4704 +sigemt(853,19470 + +ns32k-pinsn.c,300 +#define Adrmod_is_index(132,2910 +#define Is_gen(121,2597 +bit_extract 44,1381 +dbit_extract 84,1925 +fbit_extract 72,1760 +flip_bytes 104,2313 +get_displacement 439,10789 +ns32k_get_enter_addr 502,12482 +ns32k_localcount 473,11600 +print_insn 143,3226 +print_insn_arg 268,6487 +sign_extend 96,2164 + +convex-pinsn.c,88 +#define lit(34,1161 +int print_effa 284,7421 +print_insn 115,3284 +#define reg(30,1039 + +command.h,0 + +defs.h,40 +#define max(23,849 +#define min(22,807 + +environ.h,0 + +expression.h,0 + +frame.h,57 +#define FRAME_FP(46,1893 +#define FRAME_INFO_ID(47,1928 + +getpagesize.h,84 +#define getpagesize(12,137 +#define getpagesize(15,191 +#define getpagesize(20,302 + +inferior.h,0 + +symseg.h,0 + +symtab.h,3167 +#define BLOCKLIST(170,6455 +#define BLOCKLIST_BLOCK(181,6832 +#define BLOCKLIST_NBLOCKS(180,6774 +#define BLOCKVECTOR(171,6503 +#define BLOCKVECTOR_BLOCK(183,6951 +#define BLOCKVECTOR_NBLOCKS(182,6891 +#define BLOCK_END(189,7165 +#define BLOCK_FUNCTION(192,7275 +#define BLOCK_GCC_COMPILED(194,7363 +#define BLOCK_NSYMS(190,7201 +#define BLOCK_SHOULD_SORT(197,7489 +#define BLOCK_START(188,7125 +#define BLOCK_SUPERBLOCK(193,7317 +#define BLOCK_SYM(191,7237 +#define B_CLR(209,7970 +#define B_SET(208,7924 +#define B_TST(210,8017 +#define LINELIST(175,6603 +#define LINETABLE(176,6648 +#define SET_TYPE_FIELD_PRIVATE(249,10189 +#define SET_TYPE_FIELD_PROTECTED(250,10277 +#define SET_TYPE_FN_PRIVATE(277,11905 +#define SET_TYPE_FN_PROTECTED(278,11990 +#define SYMBOL_BLOCK_VALUE(204,7789 +#define SYMBOL_CLASS(201,7636 +#define SYMBOL_NAME(199,7540 +#define SYMBOL_NAMESPACE(200,7583 +#define SYMBOL_TYPE(205,7846 +#define SYMBOL_VALUE(202,7681 +#define SYMBOL_VALUE_BYTES(203,7732 +#define TYPEVECTOR(173,6554 +#define TYPEVECTOR_NTYPES(185,7013 +#define TYPEVECTOR_TYPE(186,7068 +#define TYPE_ARG_TYPES(233,9227 +#define TYPE_BASECLASS(234,9282 +#define TYPE_BASECLASSES(232,9168 +#define TYPE_CODE(222,8647 +#define TYPE_DOMAIN_TYPE(227,8865 +#define TYPE_FIELD(239,9572 +#define TYPE_FIELDS(224,8743 +#define TYPE_FIELD_BITPOS(243,9831 +#define TYPE_FIELD_BITSIZE(244,9899 +#define TYPE_FIELD_NAME(241,9690 +#define TYPE_FIELD_PACKED(245,9969 +#define TYPE_FIELD_PRIVATE(251,10369 +#define TYPE_FIELD_PRIVATE_BITS(247,10039 +#define TYPE_FIELD_PROTECTED(252,10452 +#define TYPE_FIELD_PROTECTED_BITS(248,10112 +#define TYPE_FIELD_STATIC(257,10713 +#define TYPE_FIELD_STATIC_PHYSNAME(258,10789 +#define TYPE_FIELD_TYPE(240,9626 +#define TYPE_FIELD_VALUE(242,9754 +#define TYPE_FLAGS(220,8527 +#define TYPE_FN_FIELD(266,11249 +#define TYPE_FN_FIELDLIST(261,10941 +#define TYPE_FN_FIELDLIST1(262,11009 +#define TYPE_FN_FIELDLISTS(260,10878 +#define TYPE_FN_FIELDLIST_LENGTH(264,11166 +#define TYPE_FN_FIELDLIST_NAME(263,11088 +#define TYPE_FN_FIELDS(229,8987 +#define TYPE_FN_FIELD_ARGS(269,11416 +#define TYPE_FN_FIELD_NAME(267,11298 +#define TYPE_FN_FIELD_PHYSNAME(270,11475 +#define TYPE_FN_FIELD_STATIC_P(272,11615 +#define TYPE_FN_FIELD_TYPE(268,11357 +#define TYPE_FN_FIELD_VIRTUAL_P(271,11542 +#define TYPE_FN_FIELD_VOFFSET(273,11687 +#define TYPE_FN_PRIVATE(279,12079 +#define TYPE_FN_PRIVATE_BITS(275,11757 +#define TYPE_FN_PROTECTED(280,12160 +#define TYPE_FN_PROTECTED_BITS(276,11829 +#define TYPE_FUNCTION_TYPE(216,8293 +#define TYPE_HAS_CONSTRUCTOR(255,10625 +#define TYPE_HAS_DESTRUCTOR(254,10540 +#define TYPE_LENGTH(219,8478 +#define TYPE_MAIN_VARIANT(217,8356 +#define TYPE_NAME(212,8063 +#define TYPE_NEXT_VARIANT(218,8417 +#define TYPE_NFIELDS(223,8692 +#define TYPE_NFN_FIELDS(230,9042 +#define TYPE_NFN_FIELDS_TOTAL(231,9099 +#define TYPE_N_BASECLASSES(235,9352 +#define TYPE_POINTER_TYPE(214,8167 +#define TYPE_REFERENCE_TYPE(215,8228 +#define TYPE_TARGET_TYPE(213,8108 +#define TYPE_UNSIGNED(221,8574 +#define TYPE_VIA_PUBLIC(236,9415 +#define TYPE_VIA_VIRTUAL(237,9492 +#define TYPE_VPTR_BASETYPE(226,8802 +#define TYPE_VPTR_FIELDNO(228,8926 + +value.h,501 +#define COERCE_ARRAY(112,4190 +#define COERCE_ENUM(124,4623 +#define VALUE_ADDRESS(95,3553 +#define VALUE_BITPOS(101,3847 +#define VALUE_BITSIZE(100,3805 +#define VALUE_CONTENTS(93,3462 +#define VALUE_FRAME(98,3720 +#define VALUE_FRAME_REGNUM(97,3663 +#define VALUE_INTERNALVAR(96,3604 +#define VALUE_LVAL(94,3517 +#define VALUE_NEXT(102,3887 +#define VALUE_OFFSET(99,3765 +#define VALUE_REGNO(105,4017 +#define VALUE_REPEATED(103,3923 +#define VALUE_REPETITIONS(104,3967 +#define VALUE_TYPE(92,3426 + +wait.h,381 +#define WCOREDUMP(13,439 +#define WCOREDUMP(22,735 +#define WIFEXITED(10,338 +#define WIFSIGNALED(9,274 +#define WIFSTOPPED(8,231 +#define WRETCODE(11,377 +#define WRETCODE(20,667 +#define WSETEXIT(15,511 +#define WSETEXIT(24,805 +#define WSETSTOP(16,556 +#define WSETSTOP(25,859 +#define WSTOPSIG(12,408 +#define WSTOPSIG(21,701 +#define WTERMSIG(14,478 +#define WTERMSIG(23,771 + +a.out.encap.h,279 +#define HEADER_OFFSET(89,2702 +#define HEADER_OFFSET(103,3171 +#define HEADER_OFFSET_FD(95,2932 +#define HEADER_OFFSET_FD(104,3198 +#define HEADER_SEEK(107,3237 +#define HEADER_SEEK_FD(108,3297 +#define N_DATADDR(127,3843 +#define N_TXTADDR(122,3686 +#define _N_HDROFF(118,3518 + +a.out.gnu.h,515 +#define N_BADMAG(57,1758 +#define N_BSSADDR(107,3102 +#define N_DATADDR(101,2883 +#define N_DATOFF(70,2129 +#define N_DRELOFF(74,2226 +#define N_FLAGS(34,1001 +#define N_MACHTYPE(33,924 +#define N_MAGIC(32,877 +#define N_SET_FLAGS(46,1439 +#define N_SET_INFO(35,1054 +#define N_SET_MACHTYPE(42,1312 +#define N_SET_MAGIC(39,1205 +#define N_STROFF(78,2329 +#define N_SYMOFF(76,2278 +#define N_TRELOFF(72,2177 +#define N_TXTADDR(81,2438 +#define N_TXTOFF(67,2019 +#define _N_BADMAG(61,1862 +#define _N_HDROFF(65,1967 + +stab.gnu.h,28 +#define __define_stab(7,87 + +m68k-opcode.h,138 +#define one(193,7500 +int numopcodes=sizeof(1675,87045 +struct m68k_opcode *endop = m68k_opcodes+sizeof(1677,87107 +#define two(194,7527 + +pn-opcode.h,94 +int numopcodes = sizeof(279,12226 +struct gld_opcode *endop = gld_opcodes + sizeof(281,12290 + +sparc-opcode.h,0 + +npl-opcode.h,94 +int numopcodes = sizeof(419,18012 +struct gld_opcode *endop = gld_opcodes + sizeof(421,18076 + +vax-opcode.h,0 + +ns32k-opcode.h,0 + +convex-opcode.h,0 + +m-hp9k320.h,1101 +#define ABOUT_TO_RETURN(117,3264 +#define EXTRACT_RETURN_VALUE(232,7243 +#define EXTRACT_STRUCT_VALUE_ADDRESS(245,7750 +#define FIX_CALL_DUMMY(480,17969 +#define FP_REGISTER_ADDR(254,8118 +#define FRAMELESS_FUNCTION_INVOCATION(292,9563 +#define FRAME_ARGS_ADDRESS(297,9741 +#define FRAME_CHAIN(277,9015 +#define FRAME_CHAIN_COMBINE(285,9271 +#define FRAME_CHAIN_VALID(282,9154 +#define FRAME_FIND_SAVED_REGS(333,11110 +#define FRAME_LOCALS_ADDRESS(299,9787 +#define FRAME_NUM_ARGS(306,10045 +#define FRAME_NUM_ARGS(309,10094 +#define FRAME_SAVED_PC(295,9664 +#define INIT_STACK(506,18793 +#define INIT_STACK(544,20002 +#define INVALID_FLOAT(121,3398 +#define REGISTER_ADDR(247,7815 +#define REGISTER_BYTE(168,5080 +#define REGISTER_CONVERTIBLE(196,6011 +#define REGISTER_CONVERT_TO_RAW(210,6474 +#define REGISTER_CONVERT_TO_VIRTUAL(201,6178 +#define REGISTER_RAW_SIZE(177,5415 +#define REGISTER_VIRTUAL_SIZE(183,5671 +#define REGISTER_VIRTUAL_TYPE(219,6755 +#define SAVED_PC_AFTER_CALL(85,2522 +#define SKIP_PROLOGUE(72,2086 +#define STORE_RETURN_VALUE(238,7447 +#define STORE_STRUCT_RETURN(225,7004 + +m-hp300bsd.h,1067 +#define ABOUT_TO_RETURN(101,2834 +#define EXTRACT_RETURN_VALUE(219,6991 +#define EXTRACT_STRUCT_VALUE_ADDRESS(232,7498 +#define FIX_CALL_DUMMY(482,18337 +#define FRAMELESS_FUNCTION_INVOCATION(294,9929 +#define FRAME_ARGS_ADDRESS(299,10107 +#define FRAME_CHAIN(279,9383 +#define FRAME_CHAIN_COMBINE(287,9637 +#define FRAME_CHAIN_VALID(284,9520 +#define FRAME_FIND_SAVED_REGS(335,11477 +#define FRAME_LOCALS_ADDRESS(301,10153 +#define FRAME_NUM_ARGS(308,10411 +#define FRAME_NUM_ARGS(311,10460 +#define FRAME_SAVED_PC(297,10030 +#define INIT_STACK(506,19143 +#define INVALID_FLOAT(105,2968 +#define REGISTER_BYTE(153,4701 +#define REGISTER_CONVERTIBLE(183,5759 +#define REGISTER_CONVERT_TO_RAW(197,6222 +#define REGISTER_CONVERT_TO_VIRTUAL(188,5926 +#define REGISTER_RAW_SIZE(164,5163 +#define REGISTER_U_ADDR(244,7954 +#define REGISTER_VIRTUAL_SIZE(170,5419 +#define REGISTER_VIRTUAL_TYPE(206,6503 +#define SAVED_PC_AFTER_CALL(73,2160 +#define SKIP_PROLOGUE(60,1724 +#define STORE_RETURN_VALUE(225,7195 +#define STORE_STRUCT_RETURN(212,6752 +#define vprintf(236,7634 + +m-i386.h,1026 +#define ABOUT_TO_RETURN(119,3253 +#define EXTRACT_RETURN_VALUE(234,6801 +#define EXTRACT_STRUCT_VALUE_ADDRESS(247,7308 +#define FIX_CALL_DUMMY(357,10929 +#define FRAMELESS_FUNCTION_INVOCATION(278,8412 +#define FRAME_ARGS_ADDRESS(283,8590 +#define FRAME_CHAIN(263,7867 +#define FRAME_CHAIN_COMBINE(271,8120 +#define FRAME_CHAIN_VALID(268,8003 +#define FRAME_FIND_SAVED_REGS(329,10148 +#define FRAME_LOCALS_ADDRESS(285,8636 +#define FRAME_NUM_ARGS(295,8965 +#define FRAME_SAVED_PC(281,8513 +#define INIT_STACK(388,11817 +#define INVALID_FLOAT(124,3443 +#define REGISTER_BYTE(183,5301 +#define REGISTER_CONVERTIBLE(206,5845 +#define REGISTER_CONVERT_TO_RAW(216,6160 +#define REGISTER_CONVERT_TO_VIRTUAL(211,5981 +#define REGISTER_RAW_SIZE(188,5426 +#define REGISTER_U_ADDR(173,4961 +#define REGISTER_VIRTUAL_SIZE(193,5545 +#define REGISTER_VIRTUAL_TYPE(221,6326 +#define SAVED_PC_AFTER_CALL(91,2581 +#define SKIP_PROLOGUE(84,2284 +#define STORE_RETURN_VALUE(240,7005 +#define STORE_STRUCT_RETURN(226,6515 +#define vfork(39,1134 + +m-i386gas.h,0 + +m-i386-sysv3.2.h,26 +#define U_FPSTATE(24,901 + +m-i386gas-sysv3.2.h,26 +#define U_FPSTATE(24,904 + +m-isi.h,1086 +#define ABOUT_TO_RETURN(111,3370 +#define EXTRACT_RETURN_VALUE(236,7904 +#define EXTRACT_STRUCT_VALUE_ADDRESS(249,8411 +#define FIX_CALL_DUMMY(468,17700 +#define FRAMELESS_FUNCTION_INVOCATION(282,9648 +#define FRAME_ARGS_ADDRESS(287,9826 +#define FRAME_CHAIN(267,9104 +#define FRAME_CHAIN_COMBINE(275,9356 +#define FRAME_CHAIN_VALID(272,9241 +#define FRAME_FIND_SAVED_REGS(317,11021 +#define FRAME_LOCALS_ADDRESS(289,9872 +#define FRAME_NUM_ARGS(294,10011 +#define FRAME_SAVED_PC(285,9749 +#define INIT_STACK(492,18506 +#define INVALID_FLOAT(115,3504 +#define N_DATADDR(95,2835 +#define N_TXTADDR(100,3014 +#define REGISTER_BYTE(172,5741 +#define REGISTER_CONVERTIBLE(200,6672 +#define REGISTER_CONVERT_TO_RAW(214,7135 +#define REGISTER_CONVERT_TO_VIRTUAL(205,6839 +#define REGISTER_RAW_SIZE(181,6076 +#define REGISTER_U_ADDR(156,5020 +#define REGISTER_VIRTUAL_SIZE(187,6332 +#define REGISTER_VIRTUAL_TYPE(223,7416 +#define SAVED_PC_AFTER_CALL(70,2214 +#define SKIP_PROLOGUE(50,1543 +#define STORE_RETURN_VALUE(242,8108 +#define STORE_STRUCT_RETURN(229,7665 +#define vprintf(387,14431 + +m-merlin.h,980 +#define ABOUT_TO_RETURN(90,2631 +#define EXTRACT_RETURN_VALUE(241,7793 +#define EXTRACT_STRUCT_VALUE_ADDRESS(254,8300 +#define FIX_CALL_DUMMY(406,13667 +#define FRAME_ARGS_ADDRESS(287,9473 +#define FRAME_CHAIN(272,9006 +#define FRAME_CHAIN_COMBINE(280,9260 +#define FRAME_CHAIN_VALID(277,9143 +#define FRAME_FIND_SAVED_REGS(329,10838 +#define FRAME_LOCALS_ADDRESS(289,9519 +#define FRAME_NUM_ARGS(294,9658 +#define FRAME_SAVED_PC(284,9364 +#define INIT_STACK(435,14654 +#define INVALID_FLOAT(94,2763 +#define REGISTER_BYTE(179,5817 +#define REGISTER_CONVERTIBLE(205,6639 +#define REGISTER_CONVERT_TO_RAW(216,6982 +#define REGISTER_CONVERT_TO_VIRTUAL(210,6773 +#define REGISTER_RAW_SIZE(186,6090 +#define REGISTER_U_ADDR(143,4420 +#define REGISTER_VIRTUAL_SIZE(192,6315 +#define REGISTER_VIRTUAL_TYPE(222,7178 +#define SAVED_PC_AFTER_CALL(62,1962 +#define SKIP_PROLOGUE(48,1465 +#define STORE_RETURN_VALUE(247,7997 +#define STORE_STRUCT_RETURN(235,7590 +#define vprintf(349,11691 + +m-altos.h,1249 +#define ABOUT_TO_RETURN(149,3914 +#define EXTRACT_RETURN_VALUE(288,8558 +#define EXTRACT_STRUCT_VALUE_ADDRESS(301,9065 +#define FIX_CALL_DUMMY(684,26496 +#define FP_REGISTER_ADDR(310,9433 +#define FRAMELESS_FUNCTION_INVOCATION(348,10878 +#define FRAME_ARGS_ADDRESS(353,11056 +#define FRAME_CHAIN(333,10332 +#define FRAME_CHAIN_COMBINE(341,10586 +#define FRAME_CHAIN_VALID(338,10469 +#define FRAME_FIND_SAVED_REGS(396,12655 +#define FRAME_FIND_SAVED_REGS(533,19900 +#define FRAME_LOCALS_ADDRESS(355,11102 +#define FRAME_NUM_ARGS(370,11584 +#define FRAME_NUM_ARGS(372,11633 +#define FRAME_NUM_ARGS(602,23239 +#define FRAME_SAVED_PC(351,10979 +#define INIT_STACK(709,27318 +#define INIT_STACK(715,27461 +#define INIT_STACK(720,27587 +#define INVALID_FLOAT(153,4048 +#define REGISTER_ADDR(303,9130 +#define REGISTER_BYTE(213,6013 +#define REGISTER_CONVERTIBLE(252,7326 +#define REGISTER_CONVERT_TO_RAW(266,7789 +#define REGISTER_CONVERT_TO_VIRTUAL(257,7493 +#define REGISTER_RAW_SIZE(224,6475 +#define REGISTER_U_ADDR(232,6808 +#define REGISTER_VIRTUAL_SIZE(230,6731 +#define REGISTER_VIRTUAL_TYPE(275,8070 +#define SAVED_PC_AFTER_CALL(119,3144 +#define SKIP_PROLOGUE(100,2474 +#define STORE_RETURN_VALUE(294,8762 +#define STORE_STRUCT_RETURN(281,8319 + +m-news.h,1092 +#define ABOUT_TO_RETURN(140,4156 +#define EXTRACT_RETURN_VALUE(271,8730 +#define EXTRACT_STRUCT_VALUE_ADDRESS(299,9765 +#define FIX_CALL_DUMMY(511,19108 +#define FRAMELESS_FUNCTION_INVOCATION(337,11164 +#define FRAME_ARGS_ADDRESS(342,11342 +#define FRAME_CHAIN(322,10618 +#define FRAME_CHAIN_COMBINE(330,10872 +#define FRAME_CHAIN_VALID(327,10755 +#define FRAME_FIND_SAVED_REGS(372,12537 +#define FRAME_LOCALS_ADDRESS(344,11388 +#define FRAME_NUM_ARGS(349,11527 +#define FRAME_SAVED_PC(340,11265 +#define INIT_STACK(536,19930 +#define INIT_STACK(541,20057 +#define INVALID_FLOAT(144,4290 +#define ISATTY(88,2727 +#define REGISTER_BYTE(206,6504 +#define REGISTER_CONVERTIBLE(234,7435 +#define REGISTER_CONVERT_TO_RAW(248,7898 +#define REGISTER_CONVERT_TO_VIRTUAL(239,7602 +#define REGISTER_RAW_SIZE(215,6839 +#define REGISTER_U_ADDR(186,5831 +#define REGISTER_VIRTUAL_SIZE(221,7095 +#define REGISTER_VIRTUAL_TYPE(257,8179 +#define SAVED_PC_AFTER_CALL(112,3462 +#define SKIP_PROLOGUE(98,2999 +#define STORE_RETURN_VALUE(284,9182 +#define STORE_STRUCT_RETURN(263,8428 +#define vprintf(303,9901 + +m-newsos3.h,67 +#define REGISTER_U_ADDR(90,3475 +#define REGISTER_U_ADDR(104,3949 + +m-npl.h,1081 +#define ABOUT_TO_RETURN(204,6901 +#define EXTRACT_RETURN_VALUE(328,11762 +#define EXTRACT_STRUCT_VALUE_ADDRESS(341,12267 +#define FIX_CALL_DUMMY(475,17198 +#define FRAME_ARGS_ADDRESS(372,13369 +#define FRAME_CHAIN(360,13021 +#define FRAME_CHAIN_COMBINE(365,13176 +#define FRAME_CHAIN_VALID(362,13077 +#define FRAME_FIND_SAVED_REGS(395,14255 +#define FRAME_LOCALS_ADDRESS(377,13503 +#define FRAME_NUM_ARGS(384,13769 +#define FRAME_SAVED_PC(369,13289 +#define IGNORE_SYMBOL(26,1010 +#define INIT_STACK(501,18034 +#define INVALID_FLOAT(207,7038 +#define READ_FILE_HEADERS(64,2306 +#define READ_STRING_TABLE_SIZE(55,1974 +#define REGISTER_BYTE(278,9909 +#define REGISTER_CONVERTIBLE(300,10722 +#define REGISTER_CONVERT_TO_RAW(309,11061 +#define REGISTER_CONVERT_TO_VIRTUAL(304,10858 +#define REGISTER_RAW_SIZE(284,10193 +#define REGISTER_U_ADDR(261,9224 +#define REGISTER_VIRTUAL_SIZE(289,10379 +#define REGISTER_VIRTUAL_TYPE(314,11255 +`#define SAVED_PC_AFTER_CALL(183,6312 +#define SKIP_PROLOGUE(112,3866 +#define STORE_RETURN_VALUE(334,11965 +#define STORE_STRUCT_RETURN(322,11559 + +m-pn.h,1077 +#define ABOUT_TO_RETURN(204,6841 +#define EXTRACT_RETURN_VALUE(312,10997 +#define EXTRACT_STRUCT_VALUE_ADDRESS(325,11502 +#define FIX_CALL_DUMMY(459,16433 +#define FRAME_ARGS_ADDRESS(356,12604 +#define FRAME_CHAIN(344,12256 +#define FRAME_CHAIN_COMBINE(349,12411 +#define FRAME_CHAIN_VALID(346,12312 +#define FRAME_FIND_SAVED_REGS(379,13490 +#define FRAME_LOCALS_ADDRESS(361,12738 +#define FRAME_NUM_ARGS(368,13004 +#define FRAME_SAVED_PC(353,12524 +#define IGNORE_SYMBOL(26,1009 +#define INIT_STACK(485,17269 +#define INVALID_FLOAT(207,6978 +#define READ_FILE_HEADERS(64,2259 +#define READ_STRING_TABLE_SIZE(55,1924 +#define REGISTER_BYTE(266,9332 +#define REGISTER_CONVERTIBLE(284,9957 +#define REGISTER_CONVERT_TO_RAW(293,10296 +#define REGISTER_CONVERT_TO_VIRTUAL(288,10093 +#define REGISTER_RAW_SIZE(270,9501 +#define REGISTER_U_ADDR(253,8824 +#define REGISTER_VIRTUAL_SIZE(274,9655 +#define REGISTER_VIRTUAL_TYPE(298,10490 +#define SAVED_PC_AFTER_CALL(183,6257 +#define SKIP_PROLOGUE(112,3820 +#define STORE_RETURN_VALUE(318,11200 +#define STORE_STRUCT_RETURN(306,10794 + +m-sparc.h,1162 +#define ABOUT_TO_RETURN(106,3444 +#define EXTRACT_RETURN_VALUE(241,8115 +#define EXTRACT_STRUCT_VALUE_ADDRESS(254,8706 +#define FIX_CALL_DUMMY(666,25193 +#define FRAMELESS_FUNCTION_INVOCATION(328,11300 +#define FRAME_ARGS_ADDRESS(336,11556 +#define FRAME_CHAIN(315,10807 +#define FRAME_CHAIN_COMBINE(321,11008 +#define FRAME_CHAIN_VALID(318,10891 +#define FRAME_FIND_SAVED_REGS(370,12938 +#define FRAME_LOCALS_ADDRESS(340,11655 +#define FRAME_NUM_ARGS(347,11913 +#define FRAME_SAVED_PC(333,11445 +#define FRAME_STRUCT_ARGS_ADDRESS(338,11602 +#define GET_RWINDOW_REG(274,9201 +#define INIT_EXTRA_FRAME_INFO(308,10593 +#define INVALID_FLOAT(111,3599 +#define PC_ADJUST(76,2571 +#define REGISTER_BYTE(170,5982 +#define REGISTER_CONVERTIBLE(210,7117 +#define REGISTER_CONVERT_TO_RAW(221,7436 +#define REGISTER_CONVERT_TO_VIRTUAL(215,7253 +#define REGISTER_IN_WINDOW_P(182,6443 +#define REGISTER_RAW_SIZE(190,6653 +#define REGISTER_VIRTUAL_SIZE(197,6817 +#define REGISTER_VIRTUAL_TYPE(227,7606 +#define SAVED_PC_AFTER_CALL(79,2674 +#define SKIP_PROLOGUE(64,2127 +#define STACK_ALIGN(90,2929 +#define STORE_RETURN_VALUE(247,8387 +#define STORE_STRUCT_RETURN(234,7864 + +m-sun2.h,1033 +#define ABOUT_TO_RETURN(87,2526 +#define EXTRACT_RETURN_VALUE(185,5701 +#define EXTRACT_STRUCT_VALUE_ADDRESS(198,6208 +#define FIX_CALL_DUMMY(408,14802 +#define FRAMELESS_FUNCTION_INVOCATION(251,8023 +#define FRAME_ARGS_ADDRESS(256,8201 +#define FRAME_CHAIN(236,7477 +#define FRAME_CHAIN_COMBINE(244,7731 +#define FRAME_CHAIN_VALID(241,7614 +#define FRAME_FIND_SAVED_REGS(292,9570 +#define FRAME_LOCALS_ADDRESS(258,8247 +#define FRAME_NUM_ARGS(265,8505 +#define FRAME_NUM_ARGS(268,8554 +#define FRAME_SAVED_PC(254,8124 +#define INIT_STACK(432,15608 +#define INVALID_FLOAT(91,2660 +#define REGISTER_BYTE(135,4179 +#define REGISTER_CONVERTIBLE(158,4797 +#define REGISTER_CONVERT_TO_RAW(168,5109 +#define REGISTER_CONVERT_TO_VIRTUAL(163,4931 +#define REGISTER_RAW_SIZE(140,4344 +#define REGISTER_U_ADDR(217,6765 +#define REGISTER_VIRTUAL_SIZE(145,4499 +#define REGISTER_VIRTUAL_TYPE(173,5274 +#define SAVED_PC_AFTER_CALL(59,1857 +#define SKIP_PROLOGUE(46,1421 +#define STORE_RETURN_VALUE(191,5905 +#define STORE_STRUCT_RETURN(178,5462 + +m-sun3.h,1000 +#define ABOUT_TO_RETURN(88,2571 +#define EXTRACT_RETURN_VALUE(205,6707 +#define EXTRACT_STRUCT_VALUE_ADDRESS(218,7214 +#define FIX_CALL_DUMMY(452,17126 +#define FRAMELESS_FUNCTION_INVOCATION(264,8715 +#define FRAME_ARGS_ADDRESS(269,8893 +#define FRAME_CHAIN(249,8169 +#define FRAME_CHAIN_COMBINE(257,8423 +#define FRAME_CHAIN_VALID(254,8306 +#define FRAME_FIND_SAVED_REGS(305,10263 +#define FRAME_LOCALS_ADDRESS(271,8939 +#define FRAME_NUM_ARGS(278,9197 +#define FRAME_NUM_ARGS(281,9246 +#define FRAME_SAVED_PC(267,8816 +#define INIT_STACK(476,17932 +#define INVALID_FLOAT(92,2714 +#define REGISTER_BYTE(139,4417 +#define REGISTER_CONVERTIBLE(169,5475 +#define REGISTER_CONVERT_TO_RAW(183,5938 +#define REGISTER_CONVERT_TO_VIRTUAL(174,5642 +#define REGISTER_RAW_SIZE(150,4879 +#define REGISTER_VIRTUAL_SIZE(156,5135 +#define REGISTER_VIRTUAL_TYPE(192,6219 +#define SAVED_PC_AFTER_CALL(63,1952 +#define SKIP_PROLOGUE(50,1514 +#define STORE_RETURN_VALUE(211,6911 +#define STORE_STRUCT_RETURN(198,6468 + +m-sun2os4.h,0 + +m-sun3os4.h,0 + +m-sun4os4.h,0 + +m-umax.h,953 +#define ABOUT_TO_RETURN(100,2754 +#define EXTRACT_RETURN_VALUE(256,7925 +#define EXTRACT_STRUCT_VALUE_ADDRESS(269,8564 +#define FIX_CALL_DUMMY(457,15149 +#define FRAME_ARGS_ADDRESS(303,9747 +#define FRAME_CHAIN(287,9278 +#define FRAME_CHAIN_COMBINE(295,9532 +#define FRAME_CHAIN_VALID(292,9415 +#define FRAME_FIND_SAVED_REGS(369,11917 +#define FRAME_LOCALS_ADDRESS(307,9876 +#define FRAME_NUM_ARGS(325,10514 +#define FRAME_SAVED_PC(299,9636 +#define INVALID_FLOAT(108,2927 +#define REGISTER_BYTE(192,5887 +#define REGISTER_CONVERTIBLE(218,6709 +#define REGISTER_CONVERT_TO_RAW(229,7052 +#define REGISTER_CONVERT_TO_VIRTUAL(223,6843 +#define REGISTER_RAW_SIZE(199,6160 +#define REGISTER_U_ADDR(156,4567 +#define REGISTER_VIRTUAL_SIZE(205,6385 +#define REGISTER_VIRTUAL_TYPE(235,7248 +#define SAVED_PC_AFTER_CALL(77,2231 +#define SKIP_PROLOGUE(63,1729 +#define STORE_RETURN_VALUE(262,8196 +#define STORE_STRUCT_RETURN(250,7722 +#define vprintf(401,13167 + +m-vax.h,1031 +#define ABOUT_TO_RETURN(124,4067 +#define EXTRACT_RETURN_VALUE(230,7586 +#define EXTRACT_STRUCT_VALUE_ADDRESS(243,8093 +#define FIX_CALL_DUMMY(390,14084 +#define FRAMELESS_FUNCTION_INVOCATION(282,9558 +#define FRAME_ARGS_ADDRESS(291,9902 +#define FRAME_CHAIN(266,8961 +#define FRAME_CHAIN_COMBINE(274,9220 +#define FRAME_CHAIN_VALID(271,9103 +#define FRAME_FIND_SAVED_REGS(314,10763 +#define FRAME_LOCALS_ADDRESS(296,10079 +#define FRAME_NUM_ARGS(301,10218 +#define FRAME_SAVED_PC(286,9650 +#define INIT_STACK(413,14868 +#define INVALID_FLOAT(129,4255 +#define REGISTER_BYTE(178,6064 +#define REGISTER_CONVERTIBLE(201,6677 +#define REGISTER_CONVERT_TO_RAW(212,6992 +#define REGISTER_CONVERT_TO_VIRTUAL(206,6811 +#define REGISTER_RAW_SIZE(183,6226 +#define REGISTER_U_ADDR(163,5488 +#define REGISTER_VIRTUAL_SIZE(188,6379 +#define REGISTER_VIRTUAL_TYPE(218,7160 +#define SAVED_PC_AFTER_CALL(97,3393 +#define SKIP_PROLOGUE(71,2233 +#define STORE_RETURN_VALUE(236,7790 +#define STORE_STRUCT_RETURN(223,7347 +#define vprintf(247,8229 + +m-symmetry.h,1043 +#define ABOUT_TO_RETURN(100,3009 +#define EXTRACT_RETURN_VALUE(349,10860 +#define EXTRACT_STRUCT_VALUE_ADDRESS(362,11376 +#define FIX_CALL_DUMMY(508,15986 +#define FRAMELESS_FUNCTION_INVOCATION(401,12684 +#define FRAME_ARGS_ADDRESS(406,12855 +#define FRAME_CHAIN(386,12194 +#define FRAME_CHAIN_COMBINE(394,12392 +#define FRAME_CHAIN_VALID(391,12330 +#define FRAME_FIND_SAVED_REGS(451,14256 +#define FRAME_LOCALS_ADDRESS(408,12901 +#define FRAME_NUM_ARGS(417,13214 +#define FRAME_SAVED_PC(404,12785 +#define INIT_STACK(537,16917 +#define INVALID_FLOAT(105,3140 +#define REGISTER_BYTE(264,8375 +#define REGISTER_CONVERTIBLE(299,9265 +#define REGISTER_CONVERT_TO_RAW(319,9841 +#define REGISTER_CONVERT_TO_VIRTUAL(309,9474 +#define REGISTER_RAW_SIZE(276,8738 +#define REGISTER_U_ADDR(165,5390 +#define REGISTER_VIRTUAL_SIZE(286,8966 +#define REGISTER_VIRTUAL_TYPE(329,10195 +#define SAVED_PC_AFTER_CALL(70,2205 +#define SKIP_PROLOGUE(63,1908 +#define STORE_RETURN_VALUE(355,11073 +#define STORE_STRUCT_RETURN(340,10541 +#define vprintf(366,11512 + +m-convex.h,1213 +#define ABOUT_TO_RETURN(161,5350 +#define EXTRACT_RETURN_VALUE(289,9422 +#define EXTRACT_STRUCT_VALUE_ADDRESS(304,10016 +#define FIX_CALL_DUMMY(558,20262 +#define FRAMELESS_FUNCTION_INVOCATION(377,12561 +#define FRAME_ARGS_ADDRESS(387,12923 +#define FRAME_CHAIN(362,11985 +#define FRAME_CHAIN_COMBINE(367,12172 +#define FRAME_CHAIN_VALID(364,12055 +#define FRAME_FIND_SAVED_REGS(416,14210 +#define FRAME_LOCALS_ADDRESS(389,12999 +#define FRAME_NUM_ARGS(394,13136 +#define FRAME_SAVED_PC(385,12856 +#define IGNORE_SYMBOL(60,1833 +#define INVALID_FLOAT(166,5500 +#define READ_FILE_HEADERS(579,20967 +#define READ_STRING_TABLE_SIZE(571,20792 +#define REGISTER_BYTE(234,7698 +#define REGISTER_CONVERTIBLE(259,8404 +#define REGISTER_CONVERT_TO_RAW(270,8745 +#define REGISTER_CONVERT_TO_VIRTUAL(264,8538 +#define REGISTER_RAW_SIZE(241,7944 +#define REGISTER_VIRTUAL_SIZE(246,8087 +#define REGISTER_VIRTUAL_TYPE(276,8938 +#define SAVED_PC_AFTER_CALL(119,3872 +#define SKIP_PROLOGUE(95,2894 +#define STAB_REG_TO_REGNUM(213,7014 +#define STORE_RETURN_VALUE(297,9704 +#define STORE_STRUCT_RETURN(282,9175 +#define is_arith_pc(134,4501 +#define is_break_pc(135,4575 +#define is_trace_pc(133,4427 +#define vprintf(309,10198 + +obstack.h,1102 +#define __INT_TO_PTR(121,5178 +#define __PTR_TO_INT(117,5107 +#define obstack_1grow(245,9539 +#define obstack_1grow(322,12241 +#define obstack_1grow_fast(207,8199 +#define obstack_alignment_mask(199,7936 +#define obstack_alloc(260,10046 +#define obstack_alloc(333,12614 +#define obstack_base(187,7607 +#define obstack_begin(204,8090 +#define obstack_blank(252,9775 +#define obstack_blank(327,12405 +#define obstack_blank_fast(209,8266 +#define obstack_chunk_size(191,7696 +#define obstack_copy(265,10201 +#define obstack_copy(336,12709 +#define obstack_copy0(270,10367 +#define obstack_copy0(339,12816 +#define obstack_finish(275,10535 +#define obstack_finish(342,12925 +#define obstack_free(287,11013 +#define obstack_free(354,13386 +#define obstack_free(361,13719 +#define obstack_grow(226,8854 +#define obstack_grow(307,11674 +#define obstack_grow0(235,9175 +#define obstack_grow0(314,11936 +#define obstack_init(201,7993 +#define obstack_next_free(195,7810 +#define obstack_object_size(218,8572 +#define obstack_object_size(301,11484 +#define obstack_room(222,8716 +#define obstack_room(304,11582 + +obstack.c,380 +POINTER 214,6647 +POINTER 220,6748 +POINTER 282,7939 +POINTER 288,8044 +POINTER 295,8180 +POINTER 303,8354 +_obstack_allocated_p 138,4635 +_obstack_begin 60,2178 +_obstack_free 162,5267 +_obstack_free 192,5977 +_obstack_newchunk 101,3425 +int 226,6859 +int 232,6970 +obstack_free 160,5215 +void 238,7067 +void 246,7231 +void 254,7397 +void 261,7532 +void 268,7658 +void 275,7803 + +regex.c,599 +#define PATFETCH(157,3945 +#define PATFETCH_RAW(162,4078 +#define PATPUSH(155,3903 +#define SIGN_EXTEND_CHAR(117,2767 +#define SYNTAX(66,1896 +#define bcmp(44,1491 +bcmp_translate 1550,40039 +#define bcopy(43,1450 +#define bzero(45,1535 +error 1731,44709 +init_syntax_once 77,2033 +insert_jump 686,16276 +main 1643,42792 +print_buf 1692,43797 +printchar 1717,44484 +re_comp 1571,40449 +re_compile_fastmap 707,16938 +re_compile_pattern 189,4788 +re_exec 1593,40911 +re_match 1010,24334 +re_match_2 1042,25428 +re_search 888,21081 +re_search_2 910,21884 +re_set_syntax 130,3124 +store_jump 669,15828 + +regex.h,0 + +malloc.c,493 +#define ASSERT(253,10112 +#define ASSERT(256,10213 +#define CHAIN(241,9658 +free 543,17151 +get_lim_data 780,22150 +get_lim_data 796,22377 +get_lim_data 803,22454 +getpool 433,14159 +malloc 472,15029 +malloc_init 293,11066 +malloc_mem_free 751,21573 +malloc_mem_used 732,21316 +malloc_stats 707,20953 +malloc_usable_size 308,11350 +memalign 662,19832 +morecore 317,11527 +realloc 600,18326 +#define start_of_data(185,7714 +#define start_of_data(190,7774 +sys_sbrk 859,24382 +valloc 689,20664 + +alloca.c,47 +alloca 139,3910 +find_stack_direction 83,2467 diff --git a/gdb/XGDB-README b/gdb/XGDB-README new file mode 100644 index 0000000000..28c9ec1b79 --- /dev/null +++ b/gdb/XGDB-README @@ -0,0 +1,57 @@ +XGDB is an attempt at a graphical interface from GDB to X windows. +Its source code is in xgdb.c. The decision of whether to include this +file is made at *link time*; compile-time conditionals for xgdb are not +allowed. See the Makefile. + +The current version does run with X11R2 but does not completely work. +For one thing it encounters an apparent bug in the predefined widget +used to display source files. This bug (which I have reported) causes +parts of the source-code display to appear blank. + +But XGDB has bugs also. I suspect that xgdb_display_source passes the +wrong line-number arguments to that widget and it may work in an +overcomplicated manner. Also, at a deeper level, it does not handle +X-events while either the inferior or a command is running. This +certainly means that the window won't refresh at such times. It's +possible that events also fail to be handled at other times, such as +after a button has been clicked, and if so this would account for some +of the failure to display the source text fully. + +I think that someone who really understands the X toolkit ought to write +something which will handle events asynchronously. + +The user interface currently implemented is not very convenient to +use. For example, it is necessary to move the mouse back and forth +often between the XGDB window and the window where XGDB's text I/O is +done. XGDB should arrange to receive keyboard input via the XGDB +window so the mouse can be left there all the time. These chars may +need to be echoed explicitly and stuffed into the keyboard buffer so +they intermix properly with those typed in the text I/O window. + +Is it worth while to have several buttons that simply use the +selection as keyboard input with a few extra characters before and +after? Perhaps it would be better to have just one button (or a mouse +click) to use the selection as text input, since this would work in +any GDB command. You would first type the command yourself, then use +the selection as input, then type RET yourself. If this is done with +a mouse click, and if keyboard input is allowed through the XGDB +window, then all this can be done with no extra mouse motion. + +There needs to be a command to find out the line number of the +selected line (or it should be displayed all the time); otherwise how +do you use the "jump" command, or go to the editor and find that line +easily? Alternatively there should be buttons for these two things. + +Some of the buttons' meanings aren't evident. For example, how does +"Brk in" differ from "Brk at"? What is "print *"? I intuitively +expected to click on a button and then select what it should apply to, +and I was surprised to find that one must do it in the other order. +There should be a "Help" button which displays a screen which explains +all the features of the graphical interface, and perhaps an "Info" +button which runs the info program to display the on-line GDB manual. + +I would suggest that someone look at other graphical debuggers +(including Sun's dbxtool) and consider how to change the interface to +be easier to use in practice. + + -- RMS diff --git a/gdb/a.out.encap.h b/gdb/a.out.encap.h index 8885455bf1..a6fa9a451e 100644 --- a/gdb/a.out.encap.h +++ b/gdb/a.out.encap.h @@ -1,7 +1,22 @@ +/* Another try at encapsulating bsd object files in coff. + Copyright (C) 1988, 1989, Free Software Foundation, Inc. + Written by Pace Willisson 12/9/88 + + This file 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 file 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 file; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + /* - * another try at encapsulating bsd object files in coff - * by Pace Willisson 12/9/88 - * * This time, we will only use the coff headers to tell the kernel * how to exec the file. Therefore, the only fields that need to * be filled in are the scnptr and vaddr for the text and data @@ -65,8 +80,11 @@ struct coffheader #ifdef i386 #define COFF_MAGIC 0514 /* I386MAGIC */ #endif +#ifdef m68k +#define COFF_MAGIC 0520 /* MC68MAGIC */ +#endif -#if defined(i386) +#ifdef COFF_MAGIC short __header_offset_temp; #define HEADER_OFFSET(f) \ (__header_offset_temp = 0, \ @@ -104,8 +122,8 @@ short __header_offset_temp; #define N_TXTADDR(x) \ ((N_FLAGS(x) & N_FLAGS_COFF_ENCAPSULATE) ? \ sizeof (struct coffheader) + sizeof (struct exec) : 0) - #define SEGMENT_SIZE 0x400000 + #define N_DATADDR(x) \ ((N_FLAGS(x) & N_FLAGS_COFF_ENCAPSULATE) ? \ (SEGMENT_SIZE + ((N_TXTADDR(x)+(x).a_text-1) & ~(SEGMENT_SIZE-1))) : \ diff --git a/gdb/a.out.gnu.h b/gdb/a.out.gnu.h index 2409becb50..e1de8f9c4f 100644 --- a/gdb/a.out.gnu.h +++ b/gdb/a.out.gnu.h @@ -58,6 +58,10 @@ enum machine_type { (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \ && N_MAGIC(x) != ZMAGIC) +#define _N_BADMAG(x) \ + (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \ + && N_MAGIC(x) != ZMAGIC) + #define _N_HDROFF(x) (1024 - sizeof (struct exec)) #define N_TXTOFF(x) \ @@ -82,9 +86,16 @@ enum machine_type { #ifdef vax #define SEGMENT_SIZE page_size #endif +#ifdef sony +#define SEGMENT_SIZE 0x2000 +#endif /* Sony. */ #ifdef is68k #define SEGMENT_SIZE 0x20000 #endif +#if defined(m68k) && defined(PORTAR) +#define PAGE_SIZE 0x400 +#define SEGMENT_SIZE PAGE_SIZE +#endif #ifndef N_DATADDR #define N_DATADDR(x) \ @@ -101,10 +112,10 @@ struct nlist { struct nlist *n_next; long n_strx; } n_un; - char n_type; + unsigned char n_type; char n_other; short n_desc; - unsigned n_value; + unsigned long n_value; }; #define N_UNDF 0 diff --git a/gdb/alloca.o b/gdb/alloca.o deleted file mode 100644 index 1d14b030902919b0132d01c24ab9b8131d1beb0d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2584 zcmah~U1(cn7=BNZwyB+v>CoX?J+@_Sq;39xOePJidN-JK$i!-z=A1T}X%h0IQwE-i zh!=`Md(n$-lquN3gdzSEDVmFdUX~%FAV`@vL%i@t84AYd{l1fvk1BX*`##_EKHvMj z@AI9cnp+zn(zb|5$FG;jy@7~FOY&d$Y^U=k<+rc=Y-vZa-gD_>waEK`MS~jFt%*(T zLFPvn>5We3cjkN+`8cj2_b}pZ*8y4AtRb&O1I(}cbnOJ<{@5aG`@1Z_CydP)Z=E%8wvd3YUMUOGZ{oQgca^HgS#&>h`>gqhMjo+e{R2+5d^DUvj`Q0-I)VPh`A+<{bBA-H zk5Qd&4Q$Twx$sNO+4AW;^HJ99A=h&0-VCr^&zWs+g6Pi)-NU`#8(pNo6`Ud{yDs6nU4{R($7{#1=j~4CZ*ct1iWyNy zJJqYH8F-smvjHBxIhux|u@wHT9xv|~XYg}hzX)0z;ZYlJ0iWc1v7bPn1eXvJo-Rvt z#w)P!>O30iJ{J^Rx4JCR6$O8#;5$96c@#XM;4=!YD7dBI>k8gg@V7=!-+p^HBR-ooBgM)W|# zShFW?1bjY(enY`mfp?L9IwSS`HOe(NakTKQE$_u=^Vh(4@yEcT{(;o!w&oM?lQza# zTF}PVf$@0~exe^OWAir@{3-BR^m7(T_D$4BKc8W_!1}hBg+Ftm&o97t@t44tYrGm2xw%Vk}KZWda4e=sde!2JCLW7LRF%_SLJ>`elsa7#l7|G#rAkhA z`=pbJVrnuf&83nljSD)dB&S}f6b+exrR-?PPqVYLl7e-@WRh2zn&%Z<%h}$;(0CeL z*iY38x-zBXA(-`qq@7!qd;RoZcb{73x;Qvz7`4=MyombAXs)ilmXc)(;LkA+bDPOr z36^sv1Rs07BxEa7!KrvOT@ZO#SWlMCiw&`YU)&aoKobe44b!ZOMAVNZGikXwP4XR< zF2wxw@7G(-lSI$rpML5YE{v}0#n;VL6$_-QwaSvo2f!c0tTqZM;Tu$is)P`g6==Td GDE + 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 "defs.h" #include "param.h" @@ -64,25 +27,19 @@ anyone else from sharing it farther. Help stamp out software hoarding! #include #endif -#ifdef UNISOFT_ASSHOLES -#define PMMU -#define NEW_PMMU -#define mc68881 /* Needed to get float in user.h!!! */ -#include /* For user.h */ -#include -#include -/* Things Unisoft defined differently from every other Unix system */ -#define NBPG PAGESIZE -#define UPAGES USIZE -#define KERNEL_U_ADDR UDOT -#endif - #include #include #include #include #include #include +#ifdef USG +#include +#ifdef ALTOS +#include +#include +#endif +#endif #ifdef COFF_ENCAPSULATE #include "a.out.encap.h" @@ -93,7 +50,7 @@ anyone else from sharing it farther. Help stamp out software hoarding! #define N_SET_MAGIC(exec, val) ((exec).a_magic = (val)) #endif -#include /* After a.out.h */ +#include /* After a.out.h */ #include #include @@ -101,28 +58,12 @@ 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. - - If you are having trouble debugging ptrace calls, turn on DEBUG - and every call to ptrace, in this module or elsewhere, will be - logged to stderr. */ + machine-dependent file. */ int call_ptrace (request, pid, arg3, arg4) int request, pid, arg3, arg4; { -#ifdef DEBUG - int result; - - fprintf(stderr, "ptrace(%x,,%x, %x) = ", request, arg3, arg4); - result=ptrace (request, pid, arg3, arg4); - fprintf(stderr, "%x\n", result); - return result; - -#define ptrace call_ptrace - -#else return ptrace (request, pid, arg3, arg4); -#endif } kill_inferior () @@ -177,7 +118,7 @@ fetch_inferior_registers () register int i; struct user u; - unsigned int offset = (char *) &u.u_ar0 - (char *) &u; + unsigned int offset = (char *) &u.u_state - (char *) &u; offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR; for (regno = 0; regno < NUM_REGS; regno++) @@ -203,20 +144,14 @@ store_inferior_registers (regno) char buf[80]; struct user u; - unsigned int offset = (char *) &u.u_ar0 - (char *) &u; + unsigned int offset = (char *) &u.u_state - (char *) &u; offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR; if (regno >= 0) { regaddr = register_addr (regno, offset); errno = 0; -#ifdef UNISOFT_ASSHOLES - /* You can't write the PC with ptrace 6, only with ptrace 11! */ - if (regno == PC_REGNUM) - ptrace(11, inferior_pid, 16, read_register(regno)); - else -#endif - ptrace (6, inferior_pid, regaddr, read_register (regno)); + ptrace (6, inferior_pid, regaddr, read_register (regno)); if (errno != 0) { sprintf (buf, "writing register number %d", regno); @@ -227,12 +162,7 @@ store_inferior_registers (regno) { regaddr = register_addr (regno, offset); errno = 0; -#ifdef UNISOFT_ASSHOLES - if (regno == PC_REGNUM) - ptrace(11, inferior_pid, 16, read_register(regno)); - else -#endif - ptrace (6, inferior_pid, regaddr, read_register (regno)); + ptrace (6, inferior_pid, regaddr, read_register (regno)); if (errno != 0) { sprintf (buf, "writing all regs, number %d", regno); @@ -341,11 +271,6 @@ write_inferior_memory (memaddr, myaddr, len) /* Work with core dump and executable files, for GDB. This code would be in core.c if it weren't machine-dependent. */ -/* Recognize COFF format systems because a.out.h defines AOUTHDR. */ -#ifdef AOUTHDR -#define COFF_FORMAT -#endif - #ifndef N_TXTADDR #define N_TXTADDR(hdr) 0 #endif /* no N_TXTADDR */ @@ -362,8 +287,10 @@ write_inferior_memory (memaddr, myaddr, len) #endif #ifndef COFF_FORMAT +#ifndef AOUTHDR #define AOUTHDR struct exec #endif +#endif extern char *sys_siglist[]; @@ -467,6 +394,9 @@ core_file_command (filename, from_tty) 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); @@ -476,26 +406,32 @@ core_file_command (filename, from_tty) { struct user u; - int reg_offset; + 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) + if (val != sizeof u) error ("Not a core file: could only read %d bytes", val); data_start = exec_data_start; +#define NBPG NBPP +#define UPAGES USIZE + data_end = data_start + NBPG * u.u_dsize; stack_start = stack_end - NBPG * u.u_ssize; - data_offset = NBPG * UPAGES; + data_offset = NBPG * UPAGES + exec_data_start % NBPG /* Not sure about this //jkp */; stack_offset = NBPG * (UPAGES + u.u_dsize); - /* Some machines put an absolute address in here; Unisoft - seems to put the offset in the upage of the regs. Sigh. */ - reg_offset = (int) u.u_ar0; + /* Some machines put an absolute address in here and some put + the offset in the upage of the regs. */ + reg_offset = (int) u.u_state; if (reg_offset > NBPG * UPAGES) reg_offset -= KERNEL_U_ADDR; + bcopy (&u.u_exdata, &core_aouthdr, sizeof (AOUTHDR)); + printf ("Core file is from \"%s\".\n", u.u_comm); + /* I don't know where to find this info. So, for now, mark it as not available. */ N_SET_MAGIC (core_aouthdr, 0); @@ -511,12 +447,17 @@ core_file_command (filename, from_tty) char buf[MAX_REGISTER_RAW_SIZE]; val = lseek (corechan, register_addr (regno, reg_offset), 0); - if (val < 0) - perror_with_name (reg_names[regno]); + 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); + } - val = myread (corechan, buf, sizeof buf); - if (val < 0) - perror_with_name (reg_names[regno]); supply_register (regno, buf); } } @@ -563,6 +504,9 @@ exec_file_command (filename, from_tty) if (filename) { + filename = tilde_expand (filename); + make_cleanup (free, filename); + execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, &execfile); if (execchan < 0) @@ -636,96 +580,4 @@ exec_file_command (filename, from_tty) if (exec_file_display_hook) (*exec_file_display_hook) (filename); } -@ - - -1.3 -log -@Remove A/UX-specific changes for shipping to FSF. -@ -text -@d30 13 -d176 7 -a182 1 - ptrace (6, inferior_pid, regaddr, read_register (regno)); -d193 6 -a198 1 - ptrace (6, inferior_pid, regaddr, read_register (regno)); -@ - - -1.2 -log -@A/UX and USG changes, and a little better error reporting. -@ -text -@a29 13 -#ifdef UNISOFT_ASSHOLES -#define PMMU -#define NEW_PMMU -#define mc68881 /* Needed to get float in user.h!!! */ -#include /* For user.h */ -#include -#include -/* Things Unisoft defined differently from every other Unix system */ -#define NBPG PAGESIZE -#define UPAGES USIZE -#define KERNEL_U_ADDR UDOT -#endif -d163 1 -a163 7 -#ifdef UNISOFT_ASSHOLES - /* You can't write the PC with ptrace 6, only with ptrace 11! */ - if (regno == PC_REGNUM) - ptrace(11, inferior_pid, 16, read_register(regno)); - else -#endif - ptrace (6, inferior_pid, regaddr, read_register (regno)); -d174 1 -a174 6 -#ifdef UNISOFT_ASSHOLES - if (regno == PC_REGNUM) - ptrace(11, inferior_pid, 16, read_register(regno)); - else -#endif - ptrace (6, inferior_pid, regaddr, read_register (regno)); -@ - - -1.1 -log -@Initial revision -@ -text -@d30 13 -a46 1 -#include -d58 2 -d67 5 -a71 1 - machine-dependent file. */ -d76 11 -d88 1 -d176 7 -a182 1 - ptrace (6, inferior_pid, regaddr, read_register (regno)); -d193 6 -a198 1 - ptrace (6, inferior_pid, regaddr, read_register (regno)); -d201 1 -a201 1 - sprintf (buf, "writing register number %d", regno); -d446 3 -a448 1 - perror_with_name (filename); -d455 6 -a460 1 - reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR; -d478 1 -a478 1 - perror_with_name (filename); -d482 1 -a482 1 - perror_with_name (filename); -@ diff --git a/gdb/blockframe.c b/gdb/blockframe.c index 451af1ad1e..3ea5919bdf 100644 --- a/gdb/blockframe.c +++ b/gdb/blockframe.c @@ -1,35 +1,48 @@ /* Get info from stack frames; convert between frames, blocks, functions and pc values. - Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1988, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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" -/* Address of end of first object file. +#include + +/* 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. */ + 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; -CORE_ADDR first_object_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) */ @@ -100,6 +113,18 @@ get_prev_frame (frame) 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. */ @@ -109,7 +134,7 @@ 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 */ } @@ -127,6 +152,33 @@ get_frame_info (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. */ @@ -138,16 +190,6 @@ get_prev_frame_info (next_frame) struct frame_info *prev; int fromleaf = 0; - /* If we are within "start" right now, don't go any higher. */ - /* This truncates stack traces of things at sigtramp() though, - because sigtramp() doesn't have a normal return PC, it has - garbage or a small value (seen: 3) in the return PC slot. - It's VITAL to see where the signal occurred, so punt this. */ -#if 0 - if (next_frame && next_frame->pc < first_object_file_end) - return 0; -#endif - /* 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. */ @@ -155,61 +197,58 @@ get_prev_frame_info (next_frame) if (!next_frame) { if (!current_frame) - error ("No frame is currently selected."); + { + 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; } - else + + /* 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)) { - /* If we have the prev one, return it */ - if (next_frame->prev) - return next_frame->prev; - - /* There is a questionable, but probably always correct - assumption being made here. The assumption is that if - functions on a specific machine has a FUNCTION_START_OFFSET, - then this is used by the function call instruction for some - purpose. If the function call instruction has this much hair - in it, it probably also sets up the frame pointer - automatically (ie. we'll never have what I am calling a - "leaf node", one which shares a frame pointer with it's - calling function). This is true on a vax. The only other - way to find this out would be to setup a seperate macro - "FUNCTION_HAS_FRAME_POINTER", which would often be equivalent - to SKIP_PROLOGUE modifying a pc value. */ - -#if FUNCTION_START_OFFSET == 0 - if (!(next_frame->next)) - { - /* Innermost */ - CORE_ADDR func_start, after_prologue; - - func_start = (get_pc_function_start (next_frame->pc) + - FUNCTION_START_OFFSET); - after_prologue = func_start; - SKIP_PROLOGUE (after_prologue); - if (after_prologue == func_start) - { - fromleaf = 1; - address = next_frame->frame; - } - } + 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. */ - address = FRAME_CHAIN (next_frame); - if (!FRAME_CHAIN_VALID (address, next_frame)) - return 0; - - /* If frame has a caller, combine the chain pointer and - the frame's own address to get the address of the caller. */ - address = FRAME_CHAIN_COMBINE (address, next_frame); - } + 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); } prev = (struct frame_info *) @@ -252,102 +291,7 @@ get_frame_saved_regs (frame_info_addr, saved_regs_addr) struct frame_info *frame_info_addr; struct frame_saved_regs *saved_regs_addr; { -#if 1 FRAME_FIND_SAVED_REGS (frame_info_addr, *saved_regs_addr); -#else - { - register int regnum; - register int regmask; - register CORE_ADDR next_addr; - register CORE_ADDR pc; - int nextinsn; - bzero (&*saved_regs_addr, sizeof *saved_regs_addr); - if ((frame_info_addr)->pc >= ((frame_info_addr)->frame - - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4) - && (frame_info_addr)->pc <= (frame_info_addr)->frame) - { - next_addr = (frame_info_addr)->frame; - pc = (frame_info_addr)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; - } - else - { - pc = get_pc_function_start ((frame_info_addr)->pc); - /* Verify we have a link a6 instruction next; - if not we lose. If we win, find the address above the saved - regs using the amount of storage from the link instruction. */ - if (044016 == read_memory_integer (pc, 2)) - { - next_addr = (frame_info_addr)->frame + read_memory_integer (pc += 2, 4); - pc += 4; - } - else if (047126 == read_memory_integer (pc, 2)) - { - next_addr = (frame_info_addr)->frame + read_memory_integer (pc += 2, 2); - pc+=2; - } - else goto lose; - - /* If have an addal #-n, sp next, adjust next_addr. */ - if ((0177777 & read_memory_integer (pc, 2)) == 0157774) - { - next_addr += read_memory_integer (pc += 2, 4); - pc += 4; - } - } - /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ - regmask = read_memory_integer (pc + 2, 2); - - /* But before that can come an fmovem. Check for it. */ - nextinsn = 0xffff & read_memory_integer (pc, 2); - if (0xf227 == nextinsn - && (regmask & 0xff00) == 0xe000) - { - pc += 4; /* Regmask's low bit is for register fp7, the first pushed */ - for (regnum = FP0_REGNUM + 7; - regnum >= FP0_REGNUM; - regnum--, regmask >>= 1) - if (regmask & 1) - (*saved_regs_addr).regs[regnum] = (next_addr -= 12); - regmask = read_memory_integer (pc + 2, 2); - } - if (0044327 == read_memory_integer (pc, 2)) - { - pc += 4; /* Regmask's low bit is for register 0, the first written */ - for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) - if (regmask & 1) - (*saved_regs_addr).regs[regnum] = (next_addr += 4) - 4; - } - else if (0044347 == read_memory_integer (pc, 2)) - { pc += 4; /* Regmask's low bit is for register 15, the first pushed */ - for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) - if (regmask & 1) - (*saved_regs_addr).regs[regnum] = (next_addr -= 4); } - else if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2))) - { regnum = 0xf & read_memory_integer (pc, 2); pc += 2; - (*saved_regs_addr).regs[regnum] = (next_addr -= 4); } - /* fmovemx to index of sp may follow. */ - regmask = read_memory_integer (pc + 2, 2); - nextinsn = 0xffff & read_memory_integer (pc, 2); - if (0xf236 == nextinsn - && (regmask & 0xff00) == 0xf000) - { - pc += 10; /* Regmask's low bit is for register fp0, the first written */ - for (regnum = FP0_REGNUM + 7; - regnum >= FP0_REGNUM; - regnum--, regmask >>= 1) - if (regmask & 1) - (*saved_regs_addr).regs[regnum] = (next_addr += 12) - 12; - regmask = read_memory_integer (pc + 2, 2); - } - /* clrw -(sp); movw ccr,-(sp) may follow. */ - if (0x426742e7 == read_memory_integer (pc, 4)) - (*saved_regs_addr).regs[PS_REGNUM] = (next_addr -= 4); - lose: ; - (*saved_regs_addr).regs[SP_REGNUM] = (frame_info_addr)->frame + 8; - (*saved_regs_addr).regs[FP_REGNUM] = (frame_info_addr)->frame; - (*saved_regs_addr).regs[PC_REGNUM] = (frame_info_addr)->frame + 4; - } -#endif } /* Return the innermost lexical block in execution @@ -430,6 +374,8 @@ block_for_pc (pc) 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); @@ -482,6 +428,91 @@ find_pc_function (pc) 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. */ + +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) + { + /* No availible symbol. */ + if (name != 0) + *name = 0; + if (address != 0) + *address = 0; + return 0; + } + + if (name) + *name = SYMBOL_NAME (f); + if (address) + *address = SYMBOL_VALUE (f); + } + + /* 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) + { + if (address != 0) + *address = 0; + if (name != 0) + *name = 0; + return 0; + } + 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; + } + else + { + if (address) + *address = SYMBOL_VALUE (psb); + if (name) + *name = SYMBOL_NAME (psb); + } + } + else + /* Must be in the misc function stuff. */ + { + miscfunc = find_pc_misc_function (pc); + if (miscfunc == -1) + return 0; + 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. */ @@ -496,6 +527,8 @@ find_pc_misc_function (pc) 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). */ @@ -506,6 +539,11 @@ find_pc_misc_function (pc) 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; diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index fd6a0ba12c..60115c4a31 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -1,22 +1,21 @@ /* Everything about breakpoints, for GDB. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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" @@ -107,6 +106,9 @@ struct command_line *breakpoint_commands; static void delete_breakpoint (); void clear_momentary_breakpoints (); void breakpoint_auto_delete (); + +/* Flag indicating extra verbosity for xgdb. */ +extern int xgdb_verbose; /* condition N EXP -- set break condition of breakpoint N to EXP. */ @@ -125,6 +127,9 @@ condition_command (arg, from_tty) p = arg; while (*p >= '0' && *p <= '9') p++; + if (p == arg) + /* There is no number here. (e.g. "cond a == b"). */ + error_no_arg ("breakpoint number"); bnum = atoi (arg); ALL_BREAKPOINTS (b) @@ -376,6 +381,9 @@ breakpoint_stop_status (pc, frame_address) int value_zero; if (b->cond) { + /* Need to select the frame, with all that implies + so that the conditions will have the right context. */ + select_frame (get_current_frame (), 0); value_zero = catch_errors (breakpoint_cond_eval, b->cond, "Error occurred in testing breakpoint condition."); @@ -420,12 +428,12 @@ breakpoint_1 (bnum) register struct breakpoint *b; register struct command_line *l; register struct symbol *sym; - CORE_ADDR last_addr = -1; + CORE_ADDR last_addr = (CORE_ADDR)-1; ALL_BREAKPOINTS (b) if (bnum == -1 || bnum == b->number) { - printf ("#%-3d %c 0x%08x ", b->number, + printf_filtered ("#%-3d %c 0x%08x ", b->number, "nyod"[(int) b->enable], b->address); last_addr = b->address; @@ -433,32 +441,48 @@ breakpoint_1 (bnum) { sym = find_pc_function (b->address); if (sym) - printf (" in %s (%s line %d)", SYMBOL_NAME (sym), - b->symtab->filename, b->line_number); + printf_filtered (" in %s (%s line %d)", SYMBOL_NAME (sym), + b->symtab->filename, b->line_number); else - printf ("%s line %d", b->symtab->filename, b->line_number); + printf_filtered ("%s line %d", b->symtab->filename, b->line_number); + } + else + { + char *name; + int addr; + + if (find_pc_partial_function (b->address, &name, &addr)) + { + if (b->address - addr) + printf_filtered ("<%s+%d>", name, b->address - addr); + else + printf_filtered ("<%s>", name); + } } - printf ("\n"); + + printf_filtered ("\n"); if (b->ignore_count) - printf ("\tignore next %d hits\n", b->ignore_count); + printf_filtered ("\tignore next %d hits\n", b->ignore_count); if (b->frame) - printf ("\tstop only in stack frame at 0x%x\n", b->frame); + printf_filtered ("\tstop only in stack frame at 0x%x\n", b->frame); if (b->cond) { - printf ("\tbreak only if "); + printf_filtered ("\tbreak only if "); print_expression (b->cond, stdout); - printf ("\n"); + printf_filtered ("\n"); } if (l = b->commands) while (l) { - printf ("\t%s\n", l->line); + printf_filtered ("\t%s\n", l->line); l = l->next; } } - if (last_addr != -1) + /* Compare against (CORE_ADDR)-1 in case some compiler decides + that a comparison of an unsigned with -1 is always false. */ + if (last_addr != (CORE_ADDR)-1) set_next_address (last_addr); } @@ -471,9 +495,9 @@ breakpoints_info (bnum_exp) if (bnum_exp) bnum = parse_and_eval_address (bnum_exp); else if (breakpoint_chain == 0) - printf ("No breakpoints.\n"); + printf_filtered ("No breakpoints.\n"); else - printf ("Breakpoints:\n\ + printf_filtered ("Breakpoints:\n\ Num Enb Address Where\n"); breakpoint_1 (bnum); @@ -686,7 +710,13 @@ break_command_1 (arg, tempflag, from_tty) error ("No default breakpoint address now."); } else - if (default_breakpoint_valid) + /* Force almost all breakpoints to be in terms of the + current_source_symtab (which is decode_line_1's default). This + should produce the results we want almost all of the time while + leaving default_breakpoint_* alone. */ + if (default_breakpoint_valid + && (!current_source_symtab + || (arg && (*arg == '+' || *arg == '-')))) sals = decode_line_1 (&arg, 1, default_breakpoint_symtab, default_breakpoint_line); else @@ -770,14 +800,15 @@ tbreak_command (arg, from_tty) * because it uses the mechanisms of breakpoints. */ void -until_break_command(arg, from_tty) +until_break_command (arg, from_tty) char *arg; int from_tty; { struct symtabs_and_lines sals; struct symtab_and_line sal; - FRAME frame = get_current_frame (); - FRAME prev_frame = get_prev_frame (frame); + FRAME prev_frame = get_prev_frame (selected_frame); + + clear_proceed_status (); /* Set a breakpoint where the user wants it and at return from this function */ @@ -803,7 +834,7 @@ until_break_command(arg, from_tty) if (sal.pc == 0) error ("No line %d in file \"%s\".", sal.line, sal.symtab->filename); - set_momentary_breakpoint (sal, 0); + set_momentary_breakpoint (sal, selected_frame); /* Keep within the current frame */ @@ -940,6 +971,10 @@ delete_breakpoint (bpt) free_command_lines (&bpt->commands); if (bpt->cond) free (bpt->cond); + + if (xgdb_verbose && bpt->number >=0) + printf ("breakpoint #%d deleted\n", bpt->number); + free (bpt); } @@ -954,7 +989,9 @@ delete_command (arg, from_tty) if (arg == 0) { - if (!from_tty || query ("Delete all breakpoints? ")) + /* Ask user only if there are some breakpoints to delete. */ + if (!from_tty + || breakpoint_chain && query ("Delete all breakpoints? ")) { /* No arg; clear all breakpoints. */ while (breakpoint_chain) @@ -1077,6 +1114,9 @@ enable_breakpoint (bpt) { bpt->enable = enabled; + if (xgdb_verbose && bpt->number >= 0) + printf ("breakpoint #%d enabled\n", bpt->number); + check_duplicates (bpt->address); } @@ -1084,7 +1124,12 @@ static void enable_command (args) char *args; { - map_breakpoint_numbers (args, enable_breakpoint); + struct breakpoint *bpt; + if (args == 0) + ALL_BREAKPOINTS (bpt) + enable_breakpoint (bpt); + else + map_breakpoint_numbers (args, enable_breakpoint); } static void @@ -1093,6 +1138,9 @@ disable_breakpoint (bpt) { bpt->enable = disabled; + if (xgdb_verbose && bpt->number >= 0) + printf ("breakpoint #%d disabled\n", bpt->number); + check_duplicates (bpt->address); } @@ -1263,12 +1311,13 @@ This command may be abbreviated \"disable\".", Arguments are breakpoint numbers with spaces in between.\n\ To delete all breakpoints, give no argument.\n\ \n\ -The \"display\" subcommand applies to auto-displays instead of breakpoints.", +Also a prefix command for deletion of other GDB objects.\n\ +The \"unset\" command is also an alias for \"delete\".", &deletelist, "delete ", 1, &cmdlist); add_com_alias ("d", "delete", class_breakpoint, 1); - add_com_alias ("unset", "delete", class_breakpoint, 1); + add_com_alias ("unset", "delete", class_alias, 1); - add_abbrev_cmd ("breakpoints", class_breakpoint, delete_command, + add_cmd ("breakpoints", class_alias, delete_command, "Delete some breakpoints or auto-display expressions.\n\ Arguments are breakpoint numbers with spaces in between.\n\ To delete all breakpoints, give no argument.\n\ diff --git a/gdb/coffread.c b/gdb/coffread.c index ae02d6fe5e..46a47a130b 100644 --- a/gdb/coffread.c +++ b/gdb/coffread.c @@ -4,22 +4,21 @@ Revised 11/27/87 ddj@cs.brown.edu Copyright (C) 1987, 1988, 1989 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! -*/ +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" @@ -37,9 +36,6 @@ anyone else from sharing it farther. Help stamp out software hoarding! #include #include -/* Avoid problems with A/UX predefine */ -#undef aux - static void add_symbol_to_list (); static void read_coff_symtab (); static void patch_opaque_types (); @@ -58,6 +54,7 @@ static char *getsymname (); static int init_lineno (); static void enter_linenos (); +extern int fclose (); extern void free_all_symtabs (); extern void free_all_psymtabs (); @@ -73,6 +70,9 @@ static char *last_source_file; static CORE_ADDR cur_src_start_addr; static CORE_ADDR cur_src_end_addr; +/* Core address of the end of the first object file. */ +static CORE_ADDR first_object_file_end; + /* End of the text segment of the executable file, as found in the symbol _etext. */ @@ -84,10 +84,11 @@ static CORE_ADDR end_of_text_addr; static FILE *nlist_stream_global; static int nlist_nsyms_global; -/* The file and text section headers of the symbol file */ +/* The file, a.out and text section headers of the symbol file */ static FILHDR file_hdr; static SCNHDR text_hdr; +static AOUTHDR aout_hdr; /* The index in the symbol table of the last coff symbol that was processed. */ @@ -172,7 +173,8 @@ struct pending_block struct pending_block *pending_blocks; -extern CORE_ADDR first_object_file_end; /* From blockframe.c */ +extern CORE_ADDR startup_file_start; /* From blockframe.c */ +extern CORE_ADDR startup_file_end; /* From blockframe.c */ /* File name symbols were loaded from. */ @@ -423,6 +425,13 @@ complete_symtab (name, start_addr, size) last_source_file = savestring (name, strlen (name)); cur_src_start_addr = start_addr; cur_src_end_addr = start_addr + size; + + if (aout_hdr.entry < cur_src_end_addr + && aout_hdr.entry >= cur_src_start_addr) + { + startup_file_start = cur_src_start_addr; + startup_file_end = cur_src_end_addr; + } } /* Finish the symbol definitions for one main source file, @@ -541,6 +550,7 @@ record_misc_function (name, address) } misc_bunch->contents[misc_bunch_index].name = savestring (name, strlen (name)); misc_bunch->contents[misc_bunch_index].address = address; + misc_bunch->contents[misc_bunch_index].type = mf_unknown; misc_bunch_index++; misc_count++; } @@ -691,6 +701,9 @@ symbol_file_command (name) return; } + name = tilde_expand (name); + make_cleanup (free, name); + if (symtab_list && !query ("Load new symbol table from \"%s\"? ", name)) error ("Not confirmed."); @@ -714,6 +727,23 @@ symbol_file_command (name) if ((num_symbols = read_file_hdr (desc, &file_hdr)) < 0) error ("File \"%s\" not in executable format.", name); + /* If an a.out header is present, read it in. If not (e.g. a .o file) + deal with its absence. */ + if (file_hdr.f_opthdr == 0 + || read_aout_hdr (desc, &aout_hdr, file_hdr.f_opthdr) < 0) + { + /* We will not actually be able to run code, since backtraces would + fly off the bottom of the stack (there is no way to reliably + detect bottom of stack), but that's fine since the kernel won't + run something without an a.out header anyway. Passive examination + of .o files is one place this might make sense. */ + /* ~0 will not be in any file. */ + aout_hdr.entry = ~0; + /* set the startup file to be an empty range. */ + startup_file_start = 0; + startup_file_end = 0; + } + if (num_symbols == 0) { free_all_symtabs (); @@ -844,7 +874,7 @@ read_coff_symtab (desc, nsyms) int fcn_start_addr; long fcn_line_ptr; struct cleanup *old_chain; - int fclose(); + newfd = dup (desc); if (newfd == -1) @@ -973,7 +1003,11 @@ read_coff_symtab (desc, nsyms) case C_FCN: if (strcmp (cs->c_name, ".bf") == 0) { +#if 0 + /* Don't do this; we want all functions to be on the + mfl now. */ unrecord_misc_function (); +#endif within_function = 1; @@ -1079,6 +1113,9 @@ read_file_hdr (chan, file_hdr) switch (file_hdr->f_magic) { +#ifdef MC68MAGIC + case MC68MAGIC: +#endif #ifdef NS32GMAGIC case NS32GMAGIC: case NS32SMAGIC: @@ -1086,15 +1123,17 @@ read_file_hdr (chan, file_hdr) #ifdef I386MAGIC case I386MAGIC: #endif +#ifdef CLIPPERMAGIC + case CLIPPERMAGIC: +#endif return file_hdr->f_nsyms; - default: #ifdef BADMAG if (BADMAG(file_hdr)) - return -1; + return -1; else - return file_hdr->f_nsyms; + return file_hdr->f_nsyms; #else return -1; #endif @@ -1289,18 +1328,20 @@ enter_linenos (file_offset, first_line, last_line) register int last_line; { register char *rawptr = &linetab[file_offset - linetab_offset]; - register struct lineno *lptr; + struct lineno lptr; /* skip first line entry for each function */ rawptr += LINESZ; /* line numbers start at one for the first line of the function */ first_line--; - for (lptr = (struct lineno *)rawptr; - lptr->l_lnno && lptr->l_lnno <= last_line; - rawptr += LINESZ, lptr = (struct lineno *)rawptr) + /* Bcopy since occaisionally rawptr isn't pointing at long + boundaries. */ + for (bcopy (rawptr, &lptr, LINESZ); + lptr.l_lnno && lptr.l_lnno <= last_line; + rawptr += LINESZ, bcopy (rawptr, &lptr, LINESZ)) { - record_line (first_line + lptr->l_lnno, lptr->l_addr.l_paddr); + record_line (first_line + lptr.l_lnno, lptr.l_addr.l_paddr); } } @@ -1478,7 +1519,6 @@ process_coff_symbol (cs, aux) break; case C_REG: - case C_REGPARM: SYMBOL_CLASS (sym) = LOC_REGISTER; add_symbol_to_list (sym, &local_symbols); break; @@ -1489,6 +1529,7 @@ process_coff_symbol (cs, aux) case C_ARG: SYMBOL_CLASS (sym) = LOC_ARG; add_symbol_to_list (sym, &local_symbols); +#ifndef clipper /* If PCC says a parameter is a short or a char, it is really an int. */ if (SYMBOL_TYPE (sym) == builtin_type_char @@ -1497,8 +1538,24 @@ process_coff_symbol (cs, aux) else if (SYMBOL_TYPE (sym) == builtin_type_unsigned_char || SYMBOL_TYPE (sym) == builtin_type_unsigned_short) SYMBOL_TYPE (sym) = builtin_type_unsigned_int; +#endif break; + case C_REGPARM: + SYMBOL_CLASS (sym) = LOC_REGPARM; + add_symbol_to_list (sym, &local_symbols); +#ifndef clipper + /* If PCC says a parameter is a short or a char, + it is really an int. */ + if (SYMBOL_TYPE (sym) == builtin_type_char + || SYMBOL_TYPE (sym) == builtin_type_short) + SYMBOL_TYPE (sym) = builtin_type_int; + else if (SYMBOL_TYPE (sym) == builtin_type_unsigned_char + || SYMBOL_TYPE (sym) == builtin_type_unsigned_short) + SYMBOL_TYPE (sym) = builtin_type_unsigned_int; +#endif + break; + case C_TPDEF: SYMBOL_CLASS (sym) = LOC_TYPEDEF; SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; @@ -1935,13 +1992,14 @@ psymtab_to_symtab () } /* These will stay zero all the time */ -struct partial_symbol *global_psymbols, *static_psymbols; +struct psymbol_allocation_list global_psymbols, static_psymbols; _initialize_coff () { symfile = 0; - static_psymbols = global_psymbols = (struct partial_symbol *) 0; + bzero (&global_psymbols, sizeof (global_psymbols)); + bzero (&static_psymbols, sizeof (static_psymbols)); add_com ("symbol-file", class_files, symbol_file_command, "Load symbol table (in coff format) from executable file FILE."); diff --git a/gdb/command.c b/gdb/command.c index 000b273622..79daea4903 100644 --- a/gdb/command.c +++ b/gdb/command.c @@ -1,115 +1,24 @@ /* Library for reading command lines and decoding commands. - Copyright (C) 1986 Free Software Foundation, Inc. - - NO WARRANTY - - BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY -NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT -WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, -RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS 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. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. -STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY -WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE -LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR -OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR -DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR -A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS -PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. - - GENERAL PUBLIC LICENSE TO COPY - - 1. You may copy and distribute verbatim copies of this source file -as you receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy a valid copyright notice "Copyright -(C) 1986 Free Software Foundation, Inc."; and include following the -copyright notice a verbatim copy of the above disclaimer of warranty -and of this License. You may charge a distribution fee for the -physical act of transferring a copy. - - 2. You may modify your copy or copies of this source file 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 or is a derivative of this - program or any part thereof, to be licensed at no charge to all - third parties on terms identical to those contained in this - License Agreement (except that you may choose to grant more extensive - warranty protection to some or all third parties, at your option). - - c) You may charge a distribution 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 unrelated program with this program (or its -derivative) on a volume of a storage or distribution medium does not bring -the other program under the scope of these terms. - - 3. You may copy and distribute this 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 - shipping charge) 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.) - -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. - - 4. You may not copy, sublicense, distribute or transfer this program -except as expressly provided under this License Agreement. Any attempt -otherwise to copy, sublicense, distribute or transfer this program is void and -your rights to use the program under this License agreement shall be -automatically terminated. However, parties who have received computer -software programs from you with this License Agreement will not have -their licenses terminated so long as such parties remain in full compliance. - - 5. If you wish to incorporate parts of this program into other free -programs whose distribution conditions are different, write to the Free -Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet -worked out a simple rule that can be stated here, but we will often permit -this. We 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. - - -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! */ + 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 - -#ifdef sparc -#include -#endif +#include extern char *xmalloc (); @@ -189,7 +98,7 @@ add_alias_cmd (name, oldname, class, abbrev_flag, list) 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); + old = lookup_cmd (&copied_name, *list, 0, 1, 1); if (old == 0) { @@ -303,7 +212,7 @@ help_cmd (command, stream) return; } - c = lookup_cmd (&command, cmdlist, "", 0); + c = lookup_cmd (&command, cmdlist, "", 0, 0); if (c == 0) return; @@ -320,10 +229,12 @@ help_cmd (command, stream) and then set class to he number of this class so that the commands in the class will be listed. */ - fprintf (stream, "%s\n", c->doc); + fputs_filtered (c->doc, stream); + fputs_filtered ("\n", stream); + if (c->prefixlist == 0 && c->function != 0) return; - fputc ('\n', stream); + fprintf_filtered (stream, "\n"); /* If this is a prefix command, print it's subcommands */ if (c->prefixlist) @@ -372,18 +283,18 @@ help_list (list, cmdtype, class, stream) } if (class == -2) - fprintf (stream, "List of classes of %scommands:\n\n", cmdtype2); + fprintf_filtered (stream, "List of classes of %scommands:\n\n", cmdtype2); else - fprintf (stream, "List of %scommands:\n\n", cmdtype2); + fprintf_filtered (stream, "List of %scommands:\n\n", cmdtype2); help_cmd_list (list, class, cmdtype, (class >= 0), stream); if (class == -2) - fprintf (stream, "\n\ + fprintf_filtered (stream, "\n\ Type \"help%s\" followed by a class name for a list of commands in that class.", cmdtype1); - fprintf (stream, "\n\ + 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); @@ -416,6 +327,14 @@ help_cmd_list (list, class, prefix, recurse, 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) { @@ -424,12 +343,20 @@ help_cmd_list (list, class, prefix, recurse, stream) || (class == -2 && c->function == 0) || (class == c->class && c->function != 0))) { - fprintf (stream, "%s%s -- ", prefix, c->name); + fprintf_filtered (stream, "%s%s -- ", prefix, c->name); /* Print just the first line */ p = c->doc; while (*p && *p != '\n') p++; - fwrite (c->doc, 1, p - c->doc, stream); - fputc('\n', stream); + 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 @@ -438,6 +365,260 @@ help_cmd_list (list, class, prefix, recurse, 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 @@ -477,12 +658,10 @@ lookup_cmd (line, list, cmdtype, allow_unknown) /* Find end of command name. */ p = *line; - if (*p == '!') - p++; - else while (*p == '-' - || (*p >= 'a' && *p <= 'z') - || (*p >= 'A' && *p <= 'Z') - || (*p >= '0' && *p <= '9')) + while (*p == '-' + || (*p >= 'a' && *p <= 'z') + || (*p >= 'A' && *p <= 'Z') + || (*p >= '0' && *p <= '9')) p++; /* Look up the command name. @@ -576,6 +755,61 @@ lookup_cmd (line, list, cmdtype, allow_unknown) 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) @@ -619,6 +853,4 @@ _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."); - - add_com_alias ("!", "shell", class_support, 1); } diff --git a/gdb/command.h b/gdb/command.h index bf7891a96f..fe28aef817 100644 --- a/gdb/command.h +++ b/gdb/command.h @@ -1,107 +1,19 @@ /* Header file for command-reading library command.c. - Copyright (C) 1986 Free Software Foundation, Inc. - - NO WARRANTY - - BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY -NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT -WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, -RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS 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. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. -STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY -WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE -LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR -OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR -DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR -A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS -PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. - - GENERAL PUBLIC LICENSE TO COPY - - 1. You may copy and distribute verbatim copies of this source file -as you receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy a valid copyright notice "Copyright -(C) 1986 Free Software Foundation, Inc."; and include following the -copyright notice a verbatim copy of the above disclaimer of warranty -and of this License. You may charge a distribution fee for the -physical act of transferring a copy. - - 2. You may modify your copy or copies of this source file 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 or is a derivative of this - program or any part thereof, to be licensed at no charge to all - third parties on terms identical to those contained in this - License Agreement (except that you may choose to grant more extensive - warranty protection to some or all third parties, at your option). - - c) You may charge a distribution 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 unrelated program with this program (or its -derivative) on a volume of a storage or distribution medium does not bring -the other program under the scope of these terms. - - 3. You may copy and distribute this 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 - shipping charge) 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.) - -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. - - 4. You may not copy, sublicense, distribute or transfer this program -except as expressly provided under this License Agreement. Any attempt -otherwise to copy, sublicense, distribute or transfer this program is void and -your rights to use the program under this License agreement shall be -automatically terminated. However, parties who have received computer -software programs from you with this License Agreement will not have -their licenses terminated so long as such parties remain in full compliance. - - 5. If you wish to incorporate parts of this program into other free -programs whose distribution conditions are different, write to the Free -Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet -worked out a simple rule that can be stated here, but we will often permit -this. We 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. - - -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! */ + 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. */ @@ -148,7 +60,9 @@ struct cmd_list_element char allow_unknown; /* Nonzero says this is an abbreviation, and should not - be mentioned in lists of commands. */ + be mentioned in lists of commands. + This allows "br" to complete to "break", which it + otherwise wouldn't. */ char abbrev_flag; }; @@ -157,6 +71,7 @@ struct cmd_list_element 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 (); +extern struct cmd_list_element *lookup_cmd (), *lookup_cmd_1 (); +extern char **complete_on_cmdlist (); extern void delete_cmd (); extern void help_cmd (); diff --git a/gdb/config.gdb b/gdb/config.gdb index 2578462155..b7ef693afd 100755 --- a/gdb/config.gdb +++ b/gdb/config.gdb @@ -1,7 +1,7 @@ #!/bin/sh # -# Shell script to create proper links to machine-dependent files in +# Shell script to do machine-dependent things in # preparation for compiling gdb. # # Usage: config.gdb machine [operating-system] @@ -10,13 +10,17 @@ # If config.gdb fails after disturbing the status quo, # config.status is removed. # +# Note: if making something gives errors like "unable to make target +# 1-dep.c", this means that the compiler has put in a builtin define +# and there is a "-U" missing from makedefine in this file. +# progname=$0 case $# in 1) machine=$1 - os="none" + os="" ;; 2) machine=$1 @@ -34,49 +38,149 @@ case $# in ;; esac -paramfile=m-${machine}.h -pinsnfile=${machine}-pinsn.c -opcodefile=${machine}-opcode.h -if [ -r ${machine}-dep.c ] +# cannonicalize the machine name. +case $machine in +news) + case $os in + os3|newsos3) + $machine=newsos3 + $os="" + ;; + esac + ;; +sun2) + case $os in + os4|sunos4) + $machine=sun2os4 + $os="" + ;; + os2|sunos2) + $machine=sun2os2 + $os="" + ;; + esac + ;; +sun3) + case $os in + os4|sunos4) + $machine=sun3os4 + $os="" + ;; + os3|sunos3) + $machine=sun3os3 + $os="" + ;; + esac + ;; +sparc|sun4) + case $os in + os4|sunos4) + $machine=sun4os4 + $os="" + ;; + esac + ;; +esac + +paramfile=m-${machine}${os}.h +pinsnfile=${machine}${os}-pinsn.c +opcodefile=${machine}${os}-opcode.h +# Set up a define for purposes of editing the makefile. +makedefine= +if [ -r ${machine}${os}-dep.c ] then - depfile=${machine}-dep.c + depfile=${machine}${os}-dep.c else depfile=default-dep.c fi # # Special cases. -# If a file is not needed, set the filename to 'skip' and it will be -# ignored. +# If a file is not needed, set the file name to something. +# It must be linked to something, or else make will try to make it. +# /dev/null will not work because on systems without symbolic links, +# it will complain that /dev/null is on a different file system. # case $machine in -aux) +altos) + makedefine="-DM_REGEX=regex.o -DM_SYSV -DM_BSD_NM" + pinsnfile=m68k-pinsn.c + opcodefile=m68k-opcode.h + ;; +altosgas) + echo "Use of the coff encapsulation features require the GNU binutils utilities" + echo "To be ahead of their System V counterparts in your path." + makedefine="-DM_REGEX=regex.o -DM_SYSV -DM_BSD_NM" pinsnfile=m68k-pinsn.c + depfile=altos-dep.c opcodefile=m68k-opcode.h ;; vax) + echo + echo "/bin/cc has been known to fail on readline.c on VAXen running BSD4.3" + echo "If this occurs, use gcc " + echo " (but see comments in Makefile.dist about compiling with gcc)." + echo pinsnfile=vax-pinsn.c opcodefile=vax-opcode.h ;; hp9k320) +# The headers in the directory hp-include override system headers +# and tell GDB to use BSD executable file format (hence -Ihp-include) + makedefine="-DM_SYSV -DM_BSD_NM -DM_REGEX=regex.o + -DM_ALLOCA=alloca.o -DM_CFLAGS=-Ihp-include" +# The following is true because gcc uses a different .o file format +# than the native HPUX compiler + echo + echo "If you compile GDB with GCC on HPUX, you must make sure" + echo "that the \`nm' used in \`munch' is GNU nm" + echo + pinsnfile=m68k-pinsn.c + opcodefile=m68k-opcode.h + ;; +hp300bsd) +# Not sure what makefile editing (if any) is necessary for this machine. pinsnfile=m68k-pinsn.c opcodefile=m68k-opcode.h ;; isi) +# ISI running bsd4.2 pinsnfile=m68k-pinsn.c opcodefile=m68k-opcode.h ;; i386) - echo "Note: i386 users need to modify \`CLIBS' & \`REGEX*' in the Makefile" - opcodefile=skip + makedefine="-DM_CLIBS=-lPW -DM_SYSV -DM_REGEX=regex.o" +# The following is a lie, but a necessary one. See comment at beginning +# of this file about unneeded files. + opcodefile=m-i386.h ;; i386gas) - echo "Note: i386 users need to modify \`CLIBS' & \`REGEX*' in the Makefile" - echo "Use of the coff encapsulation features also requires the GNU binutils utilities" + makedefine="-DM_CLIBS=-lPW -DM_SYSV -DM_REGEX=regex.o" + echo + echo "Use of the coff encapsulation features requires the GNU binary utilities" echo "to be ahead of their System V counterparts in your path." + echo pinsnfile=i386-pinsn.c depfile=i386-dep.c - opcodefile=skip +# The following is a lie, but a necessary one. See comment at beginning +# of this file about unneeded files. + opcodefile=m-i386.h + ;; +i386-sysv3.2) + makedefine="-DM_CLIBS=-lPW -DM_SYSV -DM_REGEX=regex.o" + pinsnfile=i386-pinsn.c + depfile=i386-dep.c + opcodefile=/dev/null + ;; +i386gas-sysv3.2) + makedefine="-DM_CLIBS=-lPW -DM_SYSV -DM_REGEX=regex.o" + echo + echo "Use of the coff encapsulation features requires the GNU binary utilities" + echo "to be ahead of their System V counterparts in your path." + echo + pinsnfile=i386-pinsn.c + depfile=i386-dep.c + opcodefile=/dev/null ;; merlin) pinsnfile=ns32k-pinsn.c @@ -86,6 +190,11 @@ news) pinsnfile=m68k-pinsn.c opcodefile=m68k-opcode.h ;; +newsos3) + pinsnfile=m68k-pinsn.c + opcodefile=m68k-opcode.h + depfile=news-dep.c + ;; npl) pinsnfile=gld-pinsn.c ;; @@ -93,55 +202,77 @@ pn) pinsnfile=gld-pinsn.c ;; sun2) - case $os in - os4|sunos4) - paramfile=m-sun2os4.h - ;; - os2|sunos2) - paramfile=m-sun2os2.h - esac + depfile=sun3-dep.c pinsnfile=m68k-pinsn.c opcodefile=m68k-opcode.h ;; -sun2os2) +sun2os2|sun2-os2) + depfile=default-dep.c + paramfile=m-sun2.h pinsnfile=m68k-pinsn.c opcodefile=m68k-opcode.h ;; -sun2os4) +sun2os4|sun2-os4) +# Compile GDB without shared libraries so that it can be run on itself. + makedefine=-DM_CFLAGS=-Bstatic + echo + echo "Make sure to compile any program on which you want to run gdb" + echo " without shared libraries (cc -Bstatic)" + echo + paramfile=m-sun2os4.h + depfile=sun3-dep.c pinsnfile=m68k-pinsn.c opcodefile=m68k-opcode.h ;; -sun3) - case $os in - os4|sunos4) - paramfile=m-sun3os4.h - esac +sun3os3) + paramfile=m-sun3.h + depfile=sun3-dep.c pinsnfile=m68k-pinsn.c opcodefile=m68k-opcode.h ;; -sun3os4) +sun3os4|sun3-os4) +# Compile GDB without shared libraries so that it can be run on itself. + makedefine=-DM_CFLAGS=-Bstatic + echo + echo "Make sure to compile any program on which you want to run gdb" + echo " without shared libraries (cc -Bstatic)" + echo + paramfile=m-sun3os4.h pinsnfile=m68k-pinsn.c opcodefile=m68k-opcode.h depfile=sun3-dep.c ;; -sun4os4) +sun4os4|sun4-os4) +# Compile GDB without shared libraries so that it can be run on itself. +# Undefine sparc to avoid changing sparc-dep.c to 1-dep.c + makedefine="-DM_CFLAGS=-Bstatic -Usparc" + echo + echo "Make sure to compile any program on which you want to run gdb" + echo " without shared libraries (cc -Bstatic)" + echo + paramfile=m-sun4os4.h pinsnfile=sparc-pinsn.c opcodefile=sparc-opcode.h depfile=sparc-dep.c ;; +symmetry) + pinsnfile=i386-pinsn.c +# Need *some* opcode file to keep make from trying to make opcode.h + opcodefile=/dev/null + ;; umax) pinsnfile=ns32k-pinsn.c opcodefile=ns32k-opcode.h ;; -sparc|sun4) - case $os in - os4|sunos4) - paramfile=m-sun4os4.h - esac +sparc|sun4|sun4os3|sun4-os3) + paramfile=m-sparc.h +# Undefine sparc to avoid changing sparc-dep.c to 1-dep.c + makedefine=-Usparc pinsnfile=sparc-pinsn.c opcodefile=sparc-opcode.h depfile=sparc-dep.c - paramfile=m-sparc.h + ;; +convex) ;; test) paramfile=one @@ -153,11 +284,13 @@ test) echo "Available types:" echo m-*.h | sed 's/m-//g' | sed 's/\.h//g' exit 1 + ;; esac files="$paramfile $pinsnfile $opcodefile $depfile" links="param.h pinsn.c opcode.h dep.c" +rm -f config.status while [ -n "$files" ] do # set file to car of files, files to cdr of files @@ -173,7 +306,8 @@ do exit 1 fi - rm -f $link config.status + echo "Linking \`$link' to \`$file'." + rm -f $link # Make a symlink if possible, otherwise try a hard link ln -s $file $link 2>/dev/null || ln $file $link @@ -182,11 +316,16 @@ do echo "$progname: unable to link \`$link' to \`$file'." exit 1 fi - echo "Linked \`$link' to \`$file'." fi done -echo "Links are now set up for use with a $machine." \ +# edit the makefile +echo "Editing Makefile" +cp Makefile.dist tmp.c +cc -E >Makefile tmp.c $makedefine -DM_MAKEDEFINE="$makedefine" +rm -f tmp.c + +echo "GDB is now set up for use with a $machine." \ | tee config.status exit 0 diff --git a/gdb/config.status b/gdb/config.status deleted file mode 100644 index dfeb43284b..0000000000 --- a/gdb/config.status +++ /dev/null @@ -1 +0,0 @@ -Links are now set up for use with a sun4. diff --git a/gdb/convex-dep.c b/gdb/convex-dep.c index 509012b9be..1b8e8d7a4f 100644 --- a/gdb/convex-dep.c +++ b/gdb/convex-dep.c @@ -1,211 +1,201 @@ -/* Low level interface to ptrace, for GDB when running under Unix. - Copyright (C) 1986, 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! -*/ +/* Convex stuff for 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. */ #include "defs.h" #include "param.h" +#include "command.h" +#include "symtab.h" +#include "value.h" #include "frame.h" #include "inferior.h" - -#ifdef USG -#include -#endif +#include "wait.h" #include +#include +#include +#include + #include #include -#include #include #include -#include - -#include +#include +#include +#include #include #include +#include -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); -} +#include +#include +#include +#include +#include -kill_inferior () -{ - if (remote_debugging) - return; - if (inferior_pid == 0) - return; - /* Convex ptrace needs an extra 0 arg */ - ptrace (8, inferior_pid, 0, 0, 0); - wait (0); - inferior_died (); -} +/* Per-thread data, read from the inferior at each stop and written + back at each resume. */ -/* This is used when GDB is exiting. It gives less chance of error.*/ +/* Number of active threads. + Tables are valid for thread numbers less than this. */ -kill_inferior_fast () -{ - if (remote_debugging) - return; - if (inferior_pid == 0) - return; - ptrace (8, inferior_pid, 0, 0); - wait (0); -} +static int n_threads; -/* Resume execution of the inferior process. - If STEP is nonzero, single-step it. - If SIGNAL is nonzero, give it that signal. */ +#define MAXTHREADS 8 + +/* Thread state. The remaining data is valid only if this is PI_TALIVE. */ -void -resume (step, signal) - int step; - int signal; -{ - errno = 0; - if (remote_debugging) - remote_resume (step, signal); - else - { - extern char registers[]; +static int thread_state[MAXTHREADS]; - /* Blam the trace bits in the stack's saved psws to match the - desired step mode. This is required so that single-stepping a - return doesn't restore a psw with a clear trace bit and fly away, - and conversely, proceeding through a return in a routine that was - stepped into doesn't cause a phantom break by restoring a psw - with the trace bit set. */ - scan_stack (PSW_T_BIT, step); +/* Stop pc, signal, signal subcode */ - /* Write the registers back now */ - ptrace (11, inferior_pid, 0, registers, REGISTER_BYTES); - if (errno != 0) perror_with_name ("writing registers"); +static int thread_pc[MAXTHREADS]; +static int thread_signal[MAXTHREADS]; +static int thread_sigcode[MAXTHREADS]; - errno = 0; - ptrace (step ? 9 : 7, inferior_pid, 1, &signal, sizeof signal); - if (errno) - perror_with_name ("ptrace"); - } -} - -void -fetch_inferior_registers () -{ - extern char registers[]; - ptrace (10, inferior_pid, 0, registers, REGISTER_BYTES); -} +/* Thread registers. + If thread is selected, the regs are in registers[] instead. */ -/* 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). */ +static char thread_regs[MAXTHREADS][REGISTER_BYTES]; -store_inferior_registers (regno) - int regno; -{ - /* do this only once, right before resuming inferior. */ - return; -} - -/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory - in the NEW_SUN_PTRACE case. - It ought to be straightforward. But it appears that writing did - not write the data that I specified. I cannot understand where - it got the data that it actually did write. */ +/* 1 if the top frame on the thread's stack was a context frame, + meaning that the kernel is up to something and we should not + touch the thread at all except to resume it. */ -/* 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. */ +static char thread_is_in_kernel[MAXTHREADS]; -int -read_inferior_memory (memaddr, myaddr, len) - CORE_ADDR memaddr; - char *myaddr; - int len; +/* The currently selected thread's number. */ + +static int inferior_thread; + +/* Inferior process's file handle and a process control block + to feed args to ioctl with. */ + +static int inferior_fd; +static struct pcntl ps; + +/* SOFF file headers for exec or core file. */ + +static FILEHDR filehdr; +static OPTHDR opthdr; +static SCNHDR scnhdr; + +/* Address maps constructed from section headers of exec and core files. + Defines process address -> file address translation. */ + +struct pmap { - errno = 0; - ptrace (1, inferior_pid, memaddr, myaddr, len); - if (errno) - bzero (myaddr, len); - return errno; -} + long mem_addr; /* process start address */ + long mem_end; /* process end+1 address */ + long file_addr; /* file start address */ + long thread; /* -1 shared; 0,1,... thread-local */ + long type; /* S_TEXT S_DATA S_BSS S_TBSS etc */ + long which; /* used to sort map for info files */ +}; -/* Copy LEN bytes of data from debugger memnory at MYADDR - to inferior's memory at MEMADDR. - Returns errno on failure (cannot write the inferior) */ +static int n_exec, n_core; +static struct pmap exec_map[100]; +static struct pmap core_map[100]; -int -write_inferior_memory (memaddr, myaddr, len) - CORE_ADDR memaddr; - char *myaddr; - int len; +/* Offsets in the core file of core_context and core_tcontext blocks. */ + +static int context_offset; +static int tcontext_offset[MAXTHREADS]; + +/* Core file control blocks. */ + +static struct core_context_v70 c; +static struct core_tcontext_v70 tc; +static struct user u; +static thread_t th; +static proc_t pr; + +/* The registers of the currently selected thread. */ + +extern char registers[REGISTER_BYTES]; + +/* Vector and communication registers from core dump or from inferior. + These are read on demand, ie, not normally valid. */ + +static struct vecst vector_registers; +static struct creg_ctx comm_registers; + +/* Flag, set on a vanilla CONT command and cleared when the inferior + is continued. */ + +static int all_continue; + +/* Flag, set when the inferior is continued by a vanilla CONT command, + cleared if it is continued for any other purpose. */ + +static int thread_switch_ok; + +/* Stack of signals recieved from threads but not yet delivered to gdb. */ + +struct threadpid { - errno = 0; - ptrace (4, inferior_pid, memaddr, myaddr, len); - return errno; -} - -/* Work with core dump and executable files, for GDB. - This code would be in core.c if it weren't machine-dependent. */ + int pid; + int thread; + int signo; + int subsig; + int pc; +}; -/* Required by convex's SOFF format - It may be desirable to remove the conditionals for SOFF_FORMAT, if - Convex is the only machine which will ever make use of them. */ -#ifdef SOFF_FORMAT -#include -#include -#include -#include -#endif /* SOFF_FORMAT */ +static struct threadpid signal_stack_bot[100]; +static struct threadpid *signal_stack = signal_stack_bot; -/* Recognize COFF format systems because a.out.h defines AOUTHDR. */ -#ifdef AOUTHDR -#define COFF_FORMAT -#endif +/* How to detect empty stack -- bottom frame is all zero. */ -#ifndef N_TXTADDR -#define N_TXTADDR(hdr) 0 -#endif /* no N_TXTADDR */ +#define signal_stack_is_empty() (signal_stack->pid == 0) -#ifndef N_DATADDR -#define N_DATADDR(hdr) hdr.a_text -#endif /* no N_DATADDR */ +/* Mode controlled by SET PIPE command, controls the psw SEQ bit + which forces each instruction to complete before the next one starts. */ -/* Make COFF and non-COFF names for things a little more compatible - to reduce conditionals later. */ +static int sequential = 0; -#ifdef COFF_FORMAT -#define a_magic magic -#endif +/* Mode controlled by the SET PARALLEL command. Values are: + 0 concurrency limit 1 thread, dynamic scheduling + 1 no concurrency limit, dynamic scheduling + 2 no concurrency limit, fixed scheduling */ -#ifndef COFF_FORMAT -#define AOUTHDR struct exec -#endif +static int parallel = 1; -extern char *sys_siglist[]; +/* Mode controlled by SET BASE command, output radix for unformatted + integer typeout, as in argument lists, aggregates, and so on. + Zero means guess whether it's an address (hex) or not (decimal). */ + +static int output_radix = 0; + +/* Signal subcode at last thread stop. */ +static int stop_sigcode; + +/* Hack, see wait() below. */ + +static int exec_trap_timer; + +/* Chain containing all defined commands. */ + +extern struct cmd_list_element *cmdlist; + +/* Chain containing all defined set subcommands */ + +extern struct cmd_list_element *setlist; /* Hook for `exec_file_command' command to call. */ @@ -228,7 +218,9 @@ extern int execchan; extern int exec_mtime; -/* Virtual addresses of bounds of the two areas of memory in the core file. */ +/* Virtual addresses of bounds of the two areas of memory in the core file. + NB: These variables are set to plausible but useless values on convex. */ + extern CORE_ADDR data_start; extern CORE_ADDR data_end; @@ -236,7 +228,7 @@ 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. */ + NB: Only text_start and text_end have meaningful values on convex. */ extern CORE_ADDR text_start; extern CORE_ADDR text_end; @@ -260,265 +252,1700 @@ extern int data_offset; 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; +extern struct exec core_aouthdr; /* a.out header of exec file. */ -extern AOUTHDR exec_aouthdr; +extern struct exec exec_aouthdr; + +/* Routine to check for exec-core mismatch. */ 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. */ +/* Nonzero if we are debugging an attached outside process + rather than an inferior. */ - if (corefile) - free (corefile); - corefile = 0; +extern int attach_flag; - 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. */ +static struct type *vector_type (); +static long *read_vector_register (); +static long *read_vector_register_1 (); +static void write_vector_register (); +static REGISTER_TYPE read_comm_register (); +static void write_comm_register (); +static void convex_cont_command (); +static void thread_continue (); +static void select_thread (); +static void scan_stack (); +static void set_fixed_scheduling (); +static char *subsig_name (); +static void psw_info (); +static sig_noop (); +static ptr_cmp (); - if (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); +extern char *sys_siglist[]; +extern int errno; + +/* Execute ptrace. Convex V7 replaced ptrace with pattach. + Allow ptrace (0) as a no-op. */ -#ifdef SOFF_FORMAT - { - extern char *sys_errlist[], *sys_siglist[]; - extern int sys_nerr; - int stop_signal; - struct core_hdr corehdr; - struct user u; +int +call_ptrace (request, pid, procaddr, buf) + int request, pid, procaddr, buf; +{ + if (request == 0) + return; + error ("no ptrace"); +} - if (myread (corechan, &corehdr, sizeof corehdr) < 0) - perror_with_name (filename); - if (corehdr.c_magic != CH_MAGIC) - error ("%s: not a core file.", filename); +/* Replacement for system execle routine. + Convert it to an equivalent exect, which pattach insists on. */ - lseek (corechan, corehdr.c_user, 0); - if (myread (corechan, &u, sizeof u) < 0) - perror_with_name (filename); +execle (name, argv) + char *name, *argv; +{ + char ***envp = (char ***) &argv; + while (*envp++) ; - lseek (corechan, corehdr.c_syscall_context, 0); - if (myread (corechan, registers, REGISTER_BYTES) < 0) - perror_with_name (filename); + signal (SIGTRAP, sig_noop); + exect (name, &argv, *envp); +} - if (corehdr.c_vecst) - { - lseek (corechan, corehdr.c_vecst, 0); - if (myread (corechan, vecst, sizeof vecst) < 0) - perror_with_name (filename); - } +/* Stupid handler for stupid trace trap that otherwise causes + startup to stupidly hang. */ - data_offset = corehdr.c_data; - data_start = exec_data_start; - data_end = data_start + ctob (u.u_dsize); +static sig_noop () +{} - stack_offset = corehdr.c_stack; - stack_start = stack_end - ctob (u.u_ssize); +/* Read registers from inferior into registers[] array. + For convex, they are already there, read in when the inferior stops. */ - printf ("Program %s", u.u_comm ); - if (u.u_error >= sys_nerr) - printf (", last error: %d (undocumented),\n", u.u_error); - else if (u.u_error != 0) - printf (", last error: %s,", sys_errlist[u.u_error]); +void +fetch_inferior_registers () +{ +} - stop_signal = u.u_arg[0]; - printf (" received signal %d, %s\n", stop_signal, - stop_signal < NSIG ? sys_siglist[stop_signal] : "(undocumented)"); +/* Store our register values back into the inferior. + For Convex, do this only once, right before resuming inferior. */ - core_aouthdr.a_magic = 0; - } -#ifdef SOFF_FORMAT +store_inferior_registers (regno) + int regno; +{ +} - if (filename[0] == '/') - corefile = savestring (filename, strlen (filename)); - else - { - corefile = concat (current_directory, "/", filename); - } +/* 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. */ - /* Convex-specific code: remove the frame stored by a - user-mode trap, if present */ +int +read_inferior_memory (memaddr, myaddr, len) + CORE_ADDR memaddr; + char *myaddr; + int len; +{ + errno = 0; + while (len > 0) + { + /* little-known undocumented max request size */ + int i = (len < 12288) ? len : 12288; - if (read_register (PC_REGNUM) > STACK_END_ADDR) - { - POP_FRAME; - } + lseek (inferior_fd, memaddr, 0); + read (inferior_fd, myaddr, i); - set_current_frame ( create_new_frame (read_register (FP_REGNUM), - read_pc ())); - select_frame (get_current_frame (), 0); - validate_files (); + memaddr += i; + myaddr += i; + len -= i; } - else if (from_tty) - printf ("No core file now.\n"); + if (errno) + bzero (myaddr, len); + return errno; } - -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) - { - execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, - &execfile); - if (execchan < 0) - perror_with_name (filename); +/* Copy LEN bytes of data from debugger memory at MYADDR + to inferior's memory at MEMADDR. + Returns errno on failure (cannot write the inferior) */ -#ifdef COFF_FORMAT - { - int aout_hdrsize; - int num_sections; +int +write_inferior_memory (memaddr, myaddr, len) + CORE_ADDR memaddr; + char *myaddr; + int len; +{ + errno = 0; + lseek (inferior_fd, memaddr, 0); + write (inferior_fd, myaddr, len); + return errno; +} - if (read_file_hdr (execchan, &file_hdr) < 0) - error ("\"%s\": not in executable format.", execfile); +/* Here from create_inferior when the inferior process has been created + and started up. We must do a pattach to grab it for debugging. - aout_hdrsize = file_hdr.f_opthdr; - num_sections = file_hdr.f_nscns; + Also, intercept the CONT command by altering its dispatch address. */ - if (read_aout_hdr (execchan, &exec_aouthdr, aout_hdrsize) < 0) - error ("\"%s\": can't read optional aouthdr", execfile); +create_inferior_hook (pid) + int pid; +{ + static char cont[] = "cont"; + static char cont1[] = "c"; + char *linep = cont; + char *linep1 = cont1; + char **line = &linep; + char **line1 = &linep1; + struct cmd_list_element *c; + + c = lookup_cmd (line, cmdlist, "", 0); + c->function = convex_cont_command; + c = lookup_cmd (line1, cmdlist, "", 0); + c->function = convex_cont_command; + + inferior_fd = pattach (pid, O_EXCL); + if (inferior_fd < 0) + perror_with_name ("pattach"); + inferior_thread = 0; + set_fixed_scheduling (pid, parallel == 2); +} - if (read_section_hdr (execchan, _TEXT, &text_hdr, num_sections) < 0) - error ("\"%s\": can't read text section header", execfile); +/* Attach process PID for debugging. */ - if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections) < 0) - error ("\"%s\": can't read data section header", execfile); +attach (pid) + int pid; +{ + int fd = pattach (pid, O_EXCL); + if (fd < 0) + perror_with_name ("pattach"); + attach_flag = 1; + /* wait for strange kernel reverberations to go away */ + sleep (1); + + setpgrp (pid, pid); + + inferior_fd = fd; + inferior_thread = 0; + return pid; +} - 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; +/* Stop debugging the process whose number is PID + and continue it with signal number SIGNAL. + SIGNAL = 0 means just continue it. */ - val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR)); +void +detach (signal) + int signal; +{ + signal_stack = signal_stack_bot; + thread_continue (-1, 0, signal); + ioctl (inferior_fd, PIXDETACH, &ps); + close (inferior_fd); + inferior_fd = 0; + attach_flag = 0; +} - if (val < 0) - perror_with_name (filename); +/* Kill off the inferior process. */ - /* Convex-specific SOFF-FORMAT */ -#ifdef SOFF_FORMAT - if (IS_SOFF_MAGIC (exec_aouthdr.a_magic)) - { - FILEHDR filhdr; - OPTHDR opthdr; - SCNHDR scnhdr; - int n, gotem; - - lseek (execchan, 0L, 0); - if (myread (execchan, &filhdr, sizeof filhdr) < 0) - perror_with_name (filename); - if (myread (execchan, &opthdr, filhdr.h_opthdr) <= 0) - perror_with_name (filename); - - lseek (execchan, (long) filhdr.h_scnptr, 0); - n = -1; - gotem = 0; - while (++n < filhdr.h_nscns && gotem < 2) - { - if (myread (execchan, &scnhdr, SCNHSZ) < 0) - perror_with_name (filename); - if ((scnhdr.s_flags & S_TYPMASK) == S_TEXT) +kill_inferior () +{ + if (remote_debugging) + return; + if (inferior_pid == 0) + return; + ioctl (inferior_fd, PIXTERMINATE, 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; + ioctl (inferior_fd, PIXTERMINATE, 0); + wait (0); +} + +/* Read vector register REG, and return a pointer to the value. */ + +static long * +read_vector_register (reg) + int reg; +{ + if (have_inferior_p ()) + { + errno = 0; + ps.pi_buffer = (char *) &vector_registers; + ps.pi_nbytes = sizeof vector_registers; + ps.pi_offset = 0; + ps.pi_thread = inferior_thread; + ioctl (inferior_fd, PIXRDVREGS, &ps); + if (errno) + bzero (&vector_registers, sizeof vector_registers); + } + else if (corechan >= 0) + { + lseek (corechan, tcontext_offset[inferior_thread], 0); + if (myread (corechan, &tc, sizeof tc) < 0) + perror_with_name (corefile); + lseek (corechan, tc.core_thread_p, 0); + if (myread (corechan, &th, sizeof th) < 0) + perror_with_name (corefile); + lseek (corechan, tc.core_vregs_p, 0); + if (myread (corechan, &vector_registers, 16*128) < 0) + perror_with_name (corefile); + vector_registers.vm[0] = th.t_vect_ctx.vc_vm[0]; + vector_registers.vm[1] = th.t_vect_ctx.vc_vm[1]; + vector_registers.vls = th.t_vect_ctx.vc_vls; + } + + return read_vector_register_1 (reg); +} + +/* Return a pointer to vector register REG, which must already have been + fetched from the inferior or core file. */ + +static long * +read_vector_register_1 (reg) + int reg; +{ + switch (reg) + { + case VM_REGNUM: + return (long *) vector_registers.vm; + case VS_REGNUM: + return (long *) &vector_registers.vls; + case VL_REGNUM: + return 1 + (long *) &vector_registers.vls; + default: + return (long *) &vector_registers.vr[reg]; + } +} + +/* Write vector register REG, element ELEMENT, new value VAL. + NB: must use read-modify-write on the entire vector state, + since pattach does not do offsetted writes correctly. */ + +static void +write_vector_register (reg, element, val) + int reg, element; + REGISTER_TYPE val; +{ + if (have_inferior_p ()) + { + errno = 0; + ps.pi_thread = inferior_thread; + ps.pi_offset = 0; + ps.pi_buffer = (char *) &vector_registers; + ps.pi_nbytes = sizeof vector_registers; + + ioctl (inferior_fd, PIXRDVREGS, &ps); + + switch (reg) + { + case VL_REGNUM: + vector_registers.vls = + (vector_registers.vls & 0xffffffff00000000LL) + + (unsigned long) val; + break; + + case VS_REGNUM: + vector_registers.vls = + (val << 32) + (unsigned long) vector_registers.vls; + break; + + default: + vector_registers.vr[reg].el[element] = val; + break; + } + + ioctl (inferior_fd, PIXWRVREGS, &ps); + + if (errno) + perror_with_name ("writing vector register"); + } +} + +/* Return the contents of communication register NUM. */ + +static REGISTER_TYPE +read_comm_register (num) + int num; +{ + if (have_inferior_p ()) + { + ps.pi_buffer = (char *) &comm_registers; + ps.pi_nbytes = sizeof comm_registers; + ps.pi_offset = 0; + ps.pi_thread = inferior_thread; + ioctl (inferior_fd, PIXRDCREGS, &ps); + } + return comm_registers.crreg.r4[num]; +} + +/* Store a new value VAL into communication register NUM. + NB: Must use read-modify-write on the whole comm register set + since pattach does not do offsetted writes correctly. */ + +static void +write_comm_register (num, val) + int num; + REGISTER_TYPE val; +{ + if (have_inferior_p ()) + { + ps.pi_buffer = (char *) &comm_registers; + ps.pi_nbytes = sizeof comm_registers; + ps.pi_offset = 0; + ps.pi_thread = inferior_thread; + ioctl (inferior_fd, PIXRDCREGS, &ps); + comm_registers.crreg.r4[num] = val; + ioctl (inferior_fd, PIXWRCREGS, &ps); + } +} + +/* 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 + if (step || signal) + thread_continue (inferior_thread, step, signal); + else + thread_continue (-1, 0, 0); +} + +/* Maybe resume some threads. + THREAD is which thread to resume, or -1 to resume them all. + STEP and SIGNAL are as in resume. + + Global variable ALL_CONTINUE is set when we are here to do a + `cont' command; otherwise we may be doing `finish' or a call or + something else that will not tolerate an automatic thread switch. + + If there are stopped threads waiting to deliver signals, and + ALL_CONTINUE, do not actually resume anything. gdb will do a wait + and see one of the stopped threads in the queue. */ + +static void +thread_continue (thread, step, signal) + int thread, step, signal; +{ + int n; + + /* If we are to continue all threads, but not for the CONTINUE command, + pay no attention and continue only the selected thread. */ + + if (thread < 0 && ! all_continue) + thread = inferior_thread; + + /* If we are not stepping, we have now executed the continue part + of a CONTINUE command. */ + + if (! step) + all_continue = 0; + + /* Allow wait() to switch threads if this is an all-out continue. */ + + thread_switch_ok = thread < 0; + + /* If there are threads queued up, don't resume. */ + + if (thread_switch_ok && ! signal_stack_is_empty ()) + return; + + /* OK, do it. */ + + for (n = 0; n < n_threads; n++) + if (thread_state[n] == PI_TALIVE) + { + select_thread (n); + + if ((thread < 0 || n == thread) && ! thread_is_in_kernel[n]) + { + /* Blam the trace bits in the stack's saved psws to match + the desired step mode. This is required so that + single-stepping a return doesn't restore a psw with a + clear trace bit and fly away, and conversely, + proceeding through a return in a routine that was + stepped into doesn't cause a phantom break by restoring + a psw with the trace bit set. */ + scan_stack (PSW_T_BIT, step); + scan_stack (PSW_S_BIT, sequential); + } + + ps.pi_buffer = registers; + ps.pi_nbytes = REGISTER_BYTES; + ps.pi_offset = 0; + ps.pi_thread = n; + if (! thread_is_in_kernel[n]) + if (ioctl (inferior_fd, PIXWRREGS, &ps)) + perror_with_name ("PIXWRREGS"); + + if (thread < 0 || n == thread) + { + ps.pi_pc = 1; + ps.pi_signo = signal; + if (ioctl (inferior_fd, step ? PIXSTEP : PIXCONTINUE, &ps) < 0) + perror_with_name ("PIXCONTINUE"); + } + } + + if (ioctl (inferior_fd, PIXRUN, &ps) < 0) + perror_with_name ("PIXRUN"); +} + +/* Replacement for system wait routine. + + The system wait returns with one or more threads stopped by + signals. Put stopped threads on a stack and return them one by + one, so that it appears that wait returns one thread at a time. + + Global variable THREAD_SWITCH_OK is set when gdb can tolerate wait + returning a new thread. If it is false, then only one thread is + running; we will do a real wait, the thread will do something, and + we will return that. */ + +wait (w) + union wait *w; +{ + int pid; + + if (!w) + return wait3 (0, 0, 0); + + /* Do a real wait if we were told to, or if there are no queued threads. */ + + if (! thread_switch_ok || signal_stack_is_empty ()) + { + int thread; + + pid = wait3 (w, 0, 0); + + if (!WIFSTOPPED (*w) || pid != inferior_pid) + return pid; + + /* The inferior has done something and stopped. Read in all the + threads' registers, and queue up any signals that happened. */ + + if (ioctl (inferior_fd, PIXGETTHCOUNT, &ps) < 0) + perror_with_name ("PIXGETTHCOUNT"); + + n_threads = ps.pi_othdcnt; + for (thread = 0; thread < n_threads; thread++) + { + ps.pi_thread = thread; + if (ioctl (inferior_fd, PIXGETSUBCODE, &ps) < 0) + perror_with_name ("PIXGETSUBCODE"); + thread_state[thread] = ps.pi_otstate; + + if (ps.pi_otstate == PI_TALIVE) + { + select_thread (thread); + ps.pi_buffer = registers; + ps.pi_nbytes = REGISTER_BYTES; + ps.pi_offset = 0; + ps.pi_thread = thread; + if (ioctl (inferior_fd, PIXRDREGS, &ps) < 0) + perror_with_name ("PIXRDREGS"); + + thread_pc[thread] = read_pc (); + thread_signal[thread] = ps.pi_osigno; + thread_sigcode[thread] = ps.pi_osigcode; + + /* If the thread's stack has a context frame + on top, something fucked is going on. I do not + know what, but do I know this: the only thing you + can do with such a thread is continue it. */ + + thread_is_in_kernel[thread] = + ((read_register (PS_REGNUM) >> 25) & 3) == 0; + + /* Signals push an extended frame and then fault + with a ridiculous pc. Pop the frame. */ + + if (thread_pc[thread] > STACK_END_ADDR) { - text_start = scnhdr.s_vaddr; - text_end = text_start + scnhdr.s_size; - text_offset = scnhdr.s_scnptr; - ++gotem; + POP_FRAME; + if (is_break_pc (thread_pc[thread])) + thread_pc[thread] = read_pc () - 2; + else + thread_pc[thread] = read_pc (); + write_register (PC_REGNUM, thread_pc[thread]); } - else if ((scnhdr.s_flags & S_TYPMASK) == S_DATA) + + if (ps.pi_osigno || ps.pi_osigcode) { - exec_data_start = scnhdr.s_vaddr; - exec_data_end = exec_data_start + scnhdr.s_size; - exec_data_offset = scnhdr.s_scnptr; - data_start = exec_data_start; - data_end += exec_data_start; - ++gotem; + signal_stack++; + signal_stack->pid = pid; + signal_stack->thread = thread; + signal_stack->signo = thread_signal[thread]; + signal_stack->subsig = thread_sigcode[thread]; + signal_stack->pc = thread_pc[thread]; } + + /* The following hackery is caused by a unix 7.1 feature: + the inferior's fixed scheduling mode is cleared when + it execs the shell (since the shell is not a parallel + program). So, note the 5.4 trap we get when + the shell does its exec, then catch the 5.0 trap + that occurs when the debuggee starts, and set fixed + scheduling mode properly. */ + + if (ps.pi_osigno == 5 && ps.pi_osigcode == 4) + exec_trap_timer = 1; + else + exec_trap_timer--; + + if (ps.pi_osigno == 5 && exec_trap_timer == 0) + set_fixed_scheduling (pid, parallel == 2); + } + } + + if (signal_stack_is_empty ()) + error ("no active threads?!"); + } + + /* Select the thread that stopped, and return *w saying why. */ + + select_thread (signal_stack->thread); + + stop_signal = signal_stack->signo; + stop_sigcode = signal_stack->subsig; + + WSETSTOP (*w, signal_stack->signo); + w->w_thread = signal_stack->thread; + return (signal_stack--)->pid; +} + +/* Select thread THREAD -- its registers, stack, per-thread memory. + This is the only routine that may assign to inferior_thread + or thread_regs[]. */ + +static void +select_thread (thread) + int thread; +{ + if (thread == inferior_thread) + return; + + bcopy (registers, thread_regs[inferior_thread], REGISTER_BYTES); + ps.pi_thread = inferior_thread = thread; + if (have_inferior_p ()) + ioctl (inferior_fd, PISETRWTID, &ps); + bcopy (thread_regs[thread], registers, REGISTER_BYTES); +} + +/* Routine to set or clear a psw bit in the psw and also all psws + saved on the stack. Quits when we get to a frame in which the + saved psw is correct. */ + +static void +scan_stack (bit, val) + long bit, val; +{ + long ps = read_register (PS_REGNUM); + long fp; + if (val ? !(ps & bit) : (ps & bit)) + { + ps ^= bit; + write_register (PS_REGNUM, ps); + + fp = read_register (FP_REGNUM); + while (fp & 0x80000000) + { + ps = read_memory_integer (fp + 4, 4); + if (val ? (ps & bit) : !(ps & bit)) + break; + ps ^= bit; + write_memory (fp + 4, &ps, 4); + fp = read_memory_integer (fp + 8, 4); + } + } +} + +/* Set fixed scheduling (alliant mode) of process PID to ARG (0 or 1). */ + +static void +set_fixed_scheduling (pid, arg) + int arg; +{ + struct pattributes pattr; + getpattr (pid, &pattr); + pattr.pattr_pfixed = arg; + setpattr (pid, &pattr); +} + +core_file_command (filename, from_tty) + char *filename; + int from_tty; +{ + int n; + + /* 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; + n_core = 0; + + /* 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); + + if (myread (corechan, &filehdr, sizeof filehdr) < 0) + perror_with_name (filename); + + if (!IS_CORE_SOFF_MAGIC (filehdr.h_magic)) + error ("%s: not a core file.\n", filename); + + if (myread (corechan, &opthdr, filehdr.h_opthdr) < 0) + perror_with_name (filename); + + /* Read through the section headers. + For text, data, etc, record an entry in the core file map. + For context and tcontext, record the file address of + the context blocks. */ + + lseek (corechan, (long) filehdr.h_scnptr, 0); + + n_threads = 0; + for (n = 0; n < filehdr.h_nscns; n++) + { + if (myread (corechan, &scnhdr, sizeof scnhdr) < 0) + perror_with_name (filename); + if ((scnhdr.s_flags & S_TYPMASK) >= S_TEXT + && (scnhdr.s_flags & S_TYPMASK) <= S_COMON) + { + core_map[n_core].mem_addr = scnhdr.s_vaddr; + core_map[n_core].mem_end = scnhdr.s_vaddr + scnhdr.s_size; + core_map[n_core].file_addr = scnhdr.s_scnptr; + core_map[n_core].type = scnhdr.s_flags & S_TYPMASK; + if (core_map[n_core].type != S_TBSS + && core_map[n_core].type != S_TDATA + && core_map[n_core].type != S_TTEXT) + core_map[n_core].thread = -1; + else if (n_core == 0 + || core_map[n_core-1].mem_addr != scnhdr.s_vaddr) + core_map[n_core].thread = 0; + else + core_map[n_core].thread = core_map[n_core-1].thread + 1; + n_core++; } + else if ((scnhdr.s_flags & S_TYPMASK) == S_CONTEXT) + context_offset = scnhdr.s_scnptr; + else if ((scnhdr.s_flags & S_TYPMASK) == S_TCONTEXT) + tcontext_offset[n_threads++] = scnhdr.s_scnptr; } + + /* Read the context block, struct user, struct proc, + and the comm regs. */ + + lseek (corechan, context_offset, 0); + if (myread (corechan, &c, sizeof c) < 0) + perror_with_name (filename); + lseek (corechan, c.core_user_p, 0); + if (myread (corechan, &u, sizeof u) < 0) + perror_with_name (filename); + lseek (corechan, c.core_proc_p, 0); + if (myread (corechan, &pr, sizeof pr) < 0) + perror_with_name (filename); + comm_registers = pr.p_creg; + + /* Core file apparently is really there. Make it really exist + for xfer_core_file so we can do read_memory on it. */ + + if (filename[0] == '/') + corefile = savestring (filename, strlen (filename)); else -#endif SOFF_FORMAT - { - text_start = N_TXTADDR (exec_aouthdr); - text_end = text_start + exec_aouthdr.a_text; - text_offset = N_TXTOFF (exec_aouthdr); - exec_data_start = N_DATADDR (exec_aouthdr); - exec_data_end = exec_data_start + exec_aouthdr.a_data; - exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text; - data_start = exec_data_start; - data_end += exec_data_start; + corefile = concat (current_directory, "/", filename); + + printf_filtered ("Program %s ", u.u_comm); + + /* Read the thread registers and fill in the thread_xxx[] data. */ + + for (n = 0; n < n_threads; n++) + { + select_thread (n); + + lseek (corechan, tcontext_offset[n], 0); + if (myread (corechan, &tc, sizeof tc) < 0) + perror_with_name (corefile); + lseek (corechan, tc.core_thread_p, 0); + if (myread (corechan, &th, sizeof th) < 0) + perror_with_name (corefile); + + lseek (corechan, tc.core_syscall_context_p, 0); + if (myread (corechan, registers, REGISTER_BYTES) < 0) + perror_with_name (corefile); + + thread_signal[n] = th.t_cursig; + thread_sigcode[n] = th.t_code; + thread_state[n] = th.t_state; + thread_pc[n] = read_pc (); + + if (thread_pc[n] > STACK_END_ADDR) + { + POP_FRAME; + if (is_break_pc (thread_pc[n])) + thread_pc[n] = read_pc () - 2; + else + thread_pc[n] = read_pc (); + write_register (PC_REGNUM, thread_pc[n]); + } + + printf_filtered ("thread %d received signal %d, %s\n", + n, thread_signal[n], + thread_signal[n] < NSIG + ? sys_siglist[thread_signal[n]] + : "(undocumented)"); } - fstat (execchan, &st_exec); - exec_mtime = st_exec.st_mtime; - } -#endif /* not COFF_FORMAT */ + /* Select an interesting thread -- also-rans died with SIGKILL, + so find one that didn't. */ + + for (n = 0; n < n_threads; n++) + if (thread_signal[n] != 0 && thread_signal[n] != SIGKILL) + { + select_thread (n); + stop_signal = thread_signal[n]; + stop_sigcode = thread_sigcode[n]; + break; + } + + core_aouthdr.a_magic = 0; + + flush_cached_frames (); + set_current_frame (create_new_frame (read_register (FP_REGNUM), + read_pc ())); + select_frame (get_current_frame (), 0); validate_files (); + + print_sel_frame (1); } else if (from_tty) - printf ("No exec file now.\n"); + printf_filtered ("No core file now.\n"); +} + +exec_file_command (filename, from_tty) + char *filename; + int from_tty; +{ + int val; + int n; + struct stat st_exec; + + /* Eliminate all traces of old exec file. + Mark text segment as empty. */ + + if (execfile) + free (execfile); + execfile = 0; + data_start = 0; + data_end = 0; + text_start = 0; + text_end = 0; + exec_data_start = 0; + exec_data_end = 0; + if (execchan >= 0) + close (execchan); + execchan = -1; + + n_exec = 0; + + /* 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); + + if (myread (execchan, &filehdr, sizeof filehdr) < 0) + perror_with_name (filename); + + if (! IS_SOFF_MAGIC (filehdr.h_magic)) + error ("%s: not an executable file.", filename); + + if (myread (execchan, &opthdr, filehdr.h_opthdr) <= 0) + perror_with_name (filename); + + /* Read through the section headers. + For text, data, etc, record an entry in the exec file map. + Record text_start and text_end. */ + + lseek (execchan, (long) filehdr.h_scnptr, 0); + + for (n = 0; n < filehdr.h_nscns; n++) + { + if (myread (execchan, &scnhdr, sizeof scnhdr) < 0) + perror_with_name (filename); + + if ((scnhdr.s_flags & S_TYPMASK) >= S_TEXT + && (scnhdr.s_flags & S_TYPMASK) <= S_COMON) + { + exec_map[n_exec].mem_addr = scnhdr.s_vaddr; + exec_map[n_exec].mem_end = scnhdr.s_vaddr + scnhdr.s_size; + exec_map[n_exec].file_addr = scnhdr.s_scnptr; + exec_map[n_exec].type = scnhdr.s_flags & S_TYPMASK; + n_exec++; + + if ((scnhdr.s_flags & S_TYPMASK) == S_TEXT) + { + text_start = scnhdr.s_vaddr; + text_end = scnhdr.s_vaddr + scnhdr.s_size; + } + } + } + + fstat (execchan, &st_exec); + exec_mtime = st_exec.st_mtime; + + validate_files (); + } + else if (from_tty) + printf_filtered ("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); } +/* Read data from SOFF exec or core file. + Return 0 on success, 1 if address could not be read. */ + +int +xfer_core_file (memaddr, myaddr, len) + CORE_ADDR memaddr; + char *myaddr; + int len; +{ + register int i; + register int n; + register int val; + int xferchan; + char **xferfile; + int fileptr; + int returnval = 0; + + 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. */ + + i = len; + + for (n = 0; n < n_core; n++) + { + if (memaddr >= core_map[n].mem_addr && memaddr < core_map[n].mem_end + && (core_map[n].thread == -1 + || core_map[n].thread == inferior_thread)) + { + i = min (len, core_map[n].mem_end - memaddr); + fileptr = core_map[n].file_addr + memaddr - core_map[n].mem_addr; + if (core_map[n].file_addr) + { + xferfile = &corefile; + xferchan = corechan; + } + break; + } + else if (core_map[n].mem_addr >= memaddr + && core_map[n].mem_addr < memaddr + i) + i = core_map[n].mem_addr - memaddr; + } + + if (!xferfile) + for (n = 0; n < n_exec; n++) + { + if (memaddr >= exec_map[n].mem_addr + && memaddr < exec_map[n].mem_end) + { + i = min (len, exec_map[n].mem_end - memaddr); + fileptr = exec_map[n].file_addr + memaddr + - exec_map[n].mem_addr; + if (exec_map[n].file_addr) + { + xferfile = &execfile; + xferchan = execchan; + } + break; + } + else if (exec_map[n].mem_addr >= memaddr + && exec_map[n].mem_addr < memaddr + i) + i = exec_map[n].mem_addr - memaddr; + } + + /* 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 < 0) + 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. */ + else + { + bzero (myaddr, i); + returnval = 1; + } + + memaddr += i; + myaddr += i; + len -= i; + } + return returnval; +} + + +/* Here from info files command to print an address map. */ + +print_maps () +{ + struct pmap ptrs[200]; + int n; + + /* ID strings for core and executable file sections */ + + static char *idstr[] = + { + "0", "text", "data", "tdata", "bss", "tbss", + "common", "ttext", "ctx", "tctx", "10", "11", "12", + }; + + for (n = 0; n < n_core; n++) + { + core_map[n].which = 0; + ptrs[n] = core_map[n]; + } + for (n = 0; n < n_exec; n++) + { + exec_map[n].which = 1; + ptrs[n_core+n] = exec_map[n]; + } + + qsort (ptrs, n_core + n_exec, sizeof *ptrs, ptr_cmp); + + for (n = 0; n < n_core + n_exec; n++) + { + struct pmap *p = &ptrs[n]; + if (n > 0) + { + if (p->mem_addr < ptrs[n-1].mem_end) + p->mem_addr = ptrs[n-1].mem_end; + if (p->mem_addr >= p->mem_end) + continue; + } + printf_filtered ("%08x .. %08x %-6s %s\n", + p->mem_addr, p->mem_end, idstr[p->type], + p->which ? execfile : corefile); + } +} + +/* Compare routine to put file sections in order. + Sort into increasing order on address, and put core file sections + before exec file sections if both files contain the same addresses. */ + +static ptr_cmp (a, b) + struct pmap *a, *b; +{ + if (a->mem_addr != b->mem_addr) return a->mem_addr - b->mem_addr; + return a->which - b->which; +} + +/* Trapped internal variables are used to handle special registers. + A trapped i.v. calls a hook here every time it is dereferenced, + to provide a new value for the variable, and it calls a hook here + when a new value is assigned, to do something with the value. + + The vector registers are $vl, $vs, $vm, $vN, $VN (N in 0..7). + The communication registers are $cN, $CN (N in 0..63). + They not handled as regular registers because it's expensive to + read them, and their size varies, and they have too many names. */ + + +/* Return 1 if NAME is a trapped internal variable, else 0. */ + +int +is_trapped_internalvar (name) + char *name; +{ + if ((name[0] == 'c' || name[0] == 'C') + && name[1] >= '0' && name[1] <= '9' + && (name[2] == '\0' + || (name[2] >= '0' && name[2] <= '9' + && name[3] == '\0' && name[1] != '0')) + && atoi (&name[1]) < 64) return 1; + + if ((name[0] == 'v' || name[0] == 'V') + && (((name[1] & -8) == '0' && name[2] == '\0') + || !strcmp (name, "vl") + || !strcmp (name, "vs") + || !strcmp (name, "vm"))) + return 1; + else return 0; +} + +/* Return the value of trapped internal variable VAR */ + +value +value_of_trapped_internalvar (var) + struct internalvar *var; +{ + char *name = var->name; + value val; + struct type *type; + long len = *read_vector_register (VL_REGNUM); + if (len <= 0 || len > 128) len = 128; + + if (!strcmp (name, "vl")) + { + val = value_from_long (builtin_type_int, + (LONGEST) *read_vector_register_1 (VL_REGNUM)); + } + else if (!strcmp (name, "vs")) + { + val = value_from_long (builtin_type_int, + (LONGEST) *read_vector_register_1 (VS_REGNUM)); + } + else if (!strcmp (name, "vm")) + { + long vm[4]; + long i, *p; + bcopy (read_vector_register_1 (VM_REGNUM), vm, sizeof vm); + type = vector_type (builtin_type_int, len); + val = allocate_value (type); + p = (long *) VALUE_CONTENTS (val); + for (i = 0; i < len; i++) + *p++ = !! (vm[3 - (i >> 5)] & (1 << (i & 037))); + } + else if (name[0] == 'V') + { + type = vector_type (builtin_type_long_long, len); + val = allocate_value (type); + bcopy (read_vector_register_1 (name[1] - '0'), + VALUE_CONTENTS (val), TYPE_LENGTH (type)); + } + else if (name[0] == 'v') + { + long *p1, *p2; + type = vector_type (builtin_type_long, len); + val = allocate_value (type); + p1 = read_vector_register_1 (name[1] - '0'); + p2 = (long *) VALUE_CONTENTS (val); + while (--len >= 0) {p1++; *p2++ = *p1++;} + } + + else if (name[0] == 'c') + val = value_from_long (builtin_type_int, + read_comm_register (atoi (&name[1]))); + else if (name[0] == 'C') + val = value_from_long (builtin_type_long_long, + read_comm_register (atoi (&name[1]))); + + VALUE_LVAL (val) = lval_internalvar; + VALUE_INTERNALVAR (val) = var; + return val; +} + +/* Construct the type for a vector register's value -- + array[LENGTH] of ELEMENT_TYPE. */ + +static struct type * +vector_type (element_type, length) + struct type *element_type; + long length; +{ + struct type *type = (struct type *) xmalloc (sizeof (struct type)); + bzero (type, sizeof type); + TYPE_CODE (type) = TYPE_CODE_ARRAY; + TYPE_TARGET_TYPE (type) = element_type; + TYPE_LENGTH (type) = length * TYPE_LENGTH (TYPE_TARGET_TYPE (type)); + return type; +} + +/* Handle a new value assigned to a trapped internal variable */ + +void +set_trapped_internalvar (var, val, bitpos, bitsize, offset) + struct internalvar *var; + value val; + int bitpos, bitsize, offset; +{ + char *name = var->name; + long long newval = value_as_long (val); + + if (!strcmp (name, "vl")) + write_vector_register (VL_REGNUM, 0, newval); + else if (!strcmp (name, "vs")) + write_vector_register (VS_REGNUM, 0, newval); + else if (name[0] == 'c' || name[0] == 'C') + write_comm_register (atoi (&name[1]), newval); + else if (!strcmp (name, "vm")) + error ("can't assign to $vm"); + else + { + offset /= bitsize / 8; + write_vector_register (name[1] - '0', offset, newval); + } +} + +/* Print an integer value when no format was specified. gdb normally + prints these values in decimal, but the the leading 0x80000000 of + pointers produces intolerable 10-digit negative numbers. + If it looks like an address, print it in hex instead. */ + +decout (stream, type, val) + FILE *stream; + struct type *type; + LONGEST val; +{ + long lv = val; + + switch (output_radix) + { + case 0: + if ((lv == val || (unsigned) lv == val) + && ((lv & 0xf0000000) == 0x80000000 + || ((lv & 0xf0000000) == 0xf0000000 && lv < STACK_END_ADDR))) + { + fprintf_filtered (stream, "%#x", lv); + return; + } + + case 10: + fprintf_filtered (stream, TYPE_UNSIGNED (type) ? "%llu" : "%lld", val); + return; + + case 8: + if (TYPE_LENGTH (type) <= sizeof lv) + fprintf_filtered (stream, "%#o", lv); + else + fprintf_filtered (stream, "%#llo", val); + return; + + case 16: + if (TYPE_LENGTH (type) <= sizeof lv) + fprintf_filtered (stream, "%#x", lv); + else + fprintf_filtered (stream, "%#llx", val); + return; + } +} + +/* Change the default output radix to 10 or 16, or set it to 0 (heuristic). + This command is mostly obsolete now that the print command allows + formats to apply to aggregates, but is still handy occasionally. */ + +static void +set_base_command (arg) + char *arg; +{ + int new_radix; + + if (!arg) + output_radix = 0; + else + { + new_radix = atoi (arg); + if (new_radix != 10 && new_radix != 16 && new_radix != 8) + error ("base must be 8, 10 or 16, or null"); + else output_radix = new_radix; + } +} + +/* Turn pipelining on or off in the inferior. */ + +static void +set_pipelining_command (arg) + char *arg; +{ + if (!arg) + { + sequential = !sequential; + printf_filtered ("%s\n", sequential ? "off" : "on"); + } + else if (!strcmp (arg, "on")) + sequential = 0; + else if (!strcmp (arg, "off")) + sequential = 1; + else error ("valid args are `on', to allow instructions to overlap, or\n\ +`off', to prevent it and thereby pinpoint exceptions."); +} + +/* Enable, disable, or force parallel execution in the inferior. */ + +static void +set_parallel_command (arg) + char *arg; +{ + struct rlimit rl; + int prevparallel = parallel; + + if (!strncmp (arg, "fixed", strlen (arg))) + parallel = 2; + else if (!strcmp (arg, "on")) + parallel = 1; + else if (!strcmp (arg, "off")) + parallel = 0; + else error ("valid args are `on', to allow multiple threads, or\n\ +`fixed', to force multiple threads, or\n\ +`off', to run with one thread only."); + + if ((prevparallel == 0) != (parallel == 0) && inferior_pid) + printf_filtered ("will take effect at next run.\n"); + + getrlimit (RLIMIT_CONCUR, &rl); + rl.rlim_cur = parallel ? rl.rlim_max : 1; + setrlimit (RLIMIT_CONCUR, &rl); + + if (inferior_pid) + set_fixed_scheduling (inferior_pid, parallel == 2); +} + +/* Add a new name for an existing command. */ + +static void +alias_command (arg) + char *arg; +{ + static char *aliaserr = "usage is `alias NEW OLD', no args allowed"; + char *newname = arg; + struct cmd_list_element *new, *old; + + if (!arg) + error_no_arg ("newname oldname"); + + new = lookup_cmd (&arg, cmdlist, "", -1); + if (new && !strncmp (newname, new->name, strlen (new->name))) + { + newname = new->name; + if (!(*arg == '-' + || (*arg >= 'a' && *arg <= 'z') + || (*arg >= 'A' && *arg <= 'Z') + || (*arg >= '0' && *arg <= '9'))) + error (aliaserr); + } + else + { + arg = newname; + while (*arg == '-' + || (*arg >= 'a' && *arg <= 'z') + || (*arg >= 'A' && *arg <= 'Z') + || (*arg >= '0' && *arg <= '9')) + arg++; + if (*arg != ' ' && *arg != '\t') + error (aliaserr); + *arg = '\0'; + arg++; + } + + old = lookup_cmd (&arg, cmdlist, "", 0); + + if (*arg != '\0') + error (aliaserr); + + if (new && !strncmp (newname, new->name, strlen (new->name))) + { + char *tem; + if (new->class == (int) class_user || new->class == (int) class_alias) + tem = "Redefine command \"%s\"? "; + else + tem = "Really redefine built-in command \"%s\"? "; + if (!query (tem, new->name)) + error ("Command \"%s\" not redefined.", new->name); + } + + add_com (newname, class_alias, old->function, old->doc); +} + + + +/* Print the current thread number, and any threads with signals in the + queue. */ + +thread_info () +{ + struct threadpid *p; + + if (have_inferior_p ()) + { + ps.pi_buffer = (char *) &comm_registers; + ps.pi_nbytes = sizeof comm_registers; + ps.pi_offset = 0; + ps.pi_thread = inferior_thread; + ioctl (inferior_fd, PIXRDCREGS, &ps); + } + + printf_filtered ("Current thread %d stopped with signal %d.%d (%s).\n", + inferior_thread, stop_signal, stop_sigcode, + subsig_name (stop_signal, stop_sigcode)); + + for (p = signal_stack; p->pid; p--) + printf_filtered ("Thread %d stopped with signal %d.%d (%s).\n", + p->thread, p->signo, p->subsig, + subsig_name (p->signo, p->subsig)); + + if (iscrlbit (comm_registers.crctl.lbits.cc, 64+13)) + printf_filtered ("New thread start pc %#x\n", + (long) (comm_registers.crreg.pcpsw >> 32)); +} + +/* Return string describing a signal.subcode number */ + +static char * +subsig_name (signo, subcode) + int signo, subcode; +{ + static char *subsig4[] = { + "error exit", "privileged instruction", "unknown", + "unknown", "undefined opcode", + 0}; + static char *subsig5[] = {0, + "breakpoint", "single step", "fork trap", "exec trap", "pfork trap", + "join trap", "idle trap", "last thread", "wfork trap", + "process breakpoint", "trap instruction", + 0}; + static char *subsig8[] = {0, + "int overflow", "int divide check", "float overflow", + "float divide check", "float underflow", "reserved operand", + "sqrt error", "exp error", "ln error", "sin error", "cos error", + 0}; + static char *subsig10[] = {0, + "invalid inward ring address", "invalid outward ring call", + "invalid inward ring return", "invalid syscall gate", + "invalid rtn frame length", "invalid comm reg address", + "invalid trap gate", + 0}; + static char *subsig11[] = {0, + "read access denied", "write access denied", "execute access denied", + "segment descriptor fault", "page table fault", "data reference fault", + "i/o access denied", "levt pte invalid", + 0}; + + static char **subsig_list[] = + {0, 0, 0, 0, subsig4, subsig5, 0, 0, subsig8, 0, subsig10, subsig11, 0}; + + int i; + char *p = signo < NSIG ? sys_siglist[signo] : "unknown"; + + if (signo >= (sizeof subsig_list / sizeof *subsig_list) + || !subsig_list[signo]) + return p; + for (i = 1; subsig_list[signo][i]; i++) + if (i == subcode) + return subsig_list[signo][subcode]; + return p; +} + + +/* Print a compact display of thread status, essentially x/i $pc + for all active threads. */ + +static void +threadstat () +{ + int t; + + for (t = 0; t < n_threads; t++) + if (thread_state[t] == PI_TALIVE) + { + printf_filtered ("%d%c %08x%c %d.%d ", t, + (t == inferior_thread ? '*' : ' '), thread_pc[t], + (thread_is_in_kernel[t] ? '#' : ' '), + thread_signal[t], thread_sigcode[t]); + print_insn (thread_pc[t], stdout); + printf_filtered ("\n"); + } +} + +/* Change the current thread to ARG. */ + +set_thread_command (arg) + char *arg; +{ + int thread; + + if (!arg) + { + threadstat (); + return; + } + + thread = parse_and_eval_address (arg); + + if (thread < 0 || thread > n_threads || thread_state[thread] != PI_TALIVE) + error ("no such thread."); + + select_thread (thread); + + stop_pc = read_pc (); + flush_cached_frames (); + set_current_frame (create_new_frame (read_register (FP_REGNUM), + read_pc ())); + select_frame (get_current_frame (), 0); + print_sel_frame (1); +} + +/* Here on CONT command; gdb's dispatch address is changed to come here. + Set global variable ALL_CONTINUE to tell resume() that it should + start up all threads, and that a thread switch will not blow gdb's + mind. */ + +static void +convex_cont_command (proc_count_exp, from_tty) + char *proc_count_exp; + int from_tty; +{ + all_continue = 1; + cont_command (proc_count_exp, from_tty); +} + +/* Here on 1CONT command. Resume only the current thread. */ + +one_cont_command (proc_count_exp, from_tty) + char *proc_count_exp; + int from_tty; +{ + cont_command (proc_count_exp, from_tty); +} + +/* Print the contents and lock bits of all communication registers, + or just register ARG if ARG is a communication register, + or the 3-word resource structure in memory at address ARG. */ + +comm_registers_info (arg) + char *arg; +{ + int i, regnum; + + if (arg) + { + if (sscanf (arg, "0x%x", ®num) == 1) + { + if (regnum > 0) + regnum &= ~0x8000; + } + else if (sscanf (arg, "%d", ®num) == 1) + ; + else if (sscanf (arg, "$c%d", ®num) == 1) + ; + else if (sscanf (arg, "$C%d", ®num) == 1) + ; + else + regnum = parse_and_eval_address (arg); + + if (regnum >= 64) + error ("%s: invalid register name.", arg); + + /* if we got a (user) address, examine the resource struct there */ + + if (regnum < 0) + { + static int buf[3]; + read_memory (regnum, buf, sizeof buf); + printf_filtered ("%08x %08x%08x%s\n", regnum, buf[1], buf[2], + buf[0] & 0xff ? " locked" : ""); + return; + } + } + + ps.pi_buffer = (char *) &comm_registers; + ps.pi_nbytes = sizeof comm_registers; + ps.pi_offset = 0; + ps.pi_thread = inferior_thread; + ioctl (inferior_fd, PIXRDCREGS, &ps); + + for (i = 0; i < 64; i++) + if (!arg || i == regnum) + printf_filtered ("%2d 0x8%03x %016llx%s\n", i, i, + comm_registers.crreg.r4[i], + (iscrlbit (comm_registers.crctl.lbits.cc, i) + ? " locked" : "")); +} + +/* Print the psw */ + +static void +psw_info (arg) + char *arg; +{ + struct pswbit + { + int bit; + int pos; + char *text; + }; + + static struct pswbit pswbit[] = + { + { 0x80000000, -1, "A carry" }, + { 0x40000000, -1, "A integer overflow" }, + { 0x20000000, -1, "A zero divide" }, + { 0x10000000, -1, "Integer overflow enable" }, + { 0x08000000, -1, "Trace" }, + { 0x06000000, 25, "Frame length" }, + { 0x01000000, -1, "Sequential" }, + { 0x00800000, -1, "S carry" }, + { 0x00400000, -1, "S integer overflow" }, + { 0x00200000, -1, "S zero divide" }, + { 0x00100000, -1, "Zero divide enable" }, + { 0x00080000, -1, "Floating underflow" }, + { 0x00040000, -1, "Floating overflow" }, + { 0x00020000, -1, "Floating reserved operand" }, + { 0x00010000, -1, "Floating zero divide" }, + { 0x00008000, -1, "Floating error enable" }, + { 0x00004000, -1, "Floating underflow enable" }, + { 0x00002000, -1, "IEEE" }, + { 0x00001000, -1, "Sequential stores" }, + { 0x00000800, -1, "Intrinsic error" }, + { 0x00000400, -1, "Intrinsic error enable" }, + { 0x00000200, -1, "Trace thread creates" }, + { 0x00000100, -1, "Thread init trap" }, + { 0x000000e0, 5, "Reserved" }, + { 0x0000001f, 0, "Intrinsic error code" }, + {0, 0, 0}, + }; + + long psw; + + struct pswbit *p; + + if (arg) + psw = parse_and_eval_address (arg); + else + psw = read_register (PS_REGNUM); + + for (p = pswbit; p->bit; p++) + { + if (p->pos < 0) + printf_filtered ("%08x %s %s\n", p->bit, + (psw & p->bit) ? "yes" : "no ", p->text); + else + printf_filtered ("%08x %3d %s\n", p->bit, + (psw & p->bit) >> p->pos, p->text); + } +} + +_initialize_convex_dep () +{ + add_com ("alias", class_support, alias_command, + "Add a new name for an existing command."); + + add_cmd ("base", class_vars, set_base_command, + "Change the integer output radix to 8, 10 or 16\n\ +or use just `set base' with no args to return to the ad-hoc default,\n\ +which is 16 for integers that look like addresses, 10 otherwise.", + &setlist); + + add_cmd ("pipeline", class_run, set_pipelining_command, + "Enable or disable overlapped execution of instructions.\n\ +With `set pipe off', exceptions are reported with\n\ +$pc pointing at the instruction after the faulting one.\n\ +The default is `set pipe on', which runs faster.", + &setlist); + + add_cmd ("parallel", class_run, set_parallel_command, + "Enable or disable multi-threaded execution of parallel code.\n\ +`set parallel off' means run the program on a single CPU.\n\ +`set parallel fixed' means run the program with all CPUs assigned to it.\n\ +`set parallel on' means run the program on any CPUs that are available.", + &setlist); + + add_com ("1cont", class_run, one_cont_command, + "Continue the program, activating only the current thread.\n\ +Args are the same as the `cont' command."); + + add_com ("thread", class_run, set_thread_command, + "Change the current thread, the one under scrutiny and control.\n\ +With no arg, show the active threads, the current one marked with *."); + + add_info ("threads", thread_info, + "List status of active threads."); + + add_info ("comm-registers", comm_registers_info, + "List communication registers and their contents.\n\ +A communication register name as argument means describe only that register.\n\ +An address as argument means describe the resource structure at that address.\n\ +`Locked' means that the register has been sent to but not yet received from."); + + add_info ("psw", psw_info, + "Display $ps, the processor status word, bit by bit.\n\ +An argument means display that value's interpretation as a psw."); + + add_cmd ("convex", no_class, 0, "Convex-specific commands.\n\ +32-bit registers $pc $ps $sp $ap $fp $a1-5 $s0-7 $v0-7 $vl $vs $vm $c0-63\n\ +64-bit registers $S0-7 $V0-7 $C0-63\n\ +\n\ +info threads display info on stopped threads waiting to signal\n\ +thread display list of active threads\n\ +thread N select thread N (its registers, stack, memory, etc.)\n\ +step, next, etc step selected thread only\n\ +1cont continue selected thread only\n\ +cont continue all threads\n\ +info comm-registers display contents of comm register(s) or a resource struct\n\ +info psw display processor status word $ps\n\ +set base N change integer radix used by `print' without a format\n\ +set pipeline off exceptions are precise, $pc points after the faulting insn\n\ +set pipeline on normal mode, $pc is somewhere ahead of faulting insn\n\ +set parallel off program runs on a single CPU\n\ +set parallel fixed all CPUs are assigned to the program\n\ +set parallel on normal mode, parallel execution on random available CPUs\n\ +", + &cmdlist); + +} + diff --git a/gdb/convex-opcode.h b/gdb/convex-opcode.h new file mode 100644 index 0000000000..382e05be12 --- /dev/null +++ b/gdb/convex-opcode.h @@ -0,0 +1,1674 @@ +/* Include information for instruction dissasembly on the Convex. + Copyright (C) 1989, Free Software Foundation. + +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 xxx 0 +#define rrr 1 +#define rr 2 +#define rxr 3 +#define r 4 +#define nops 5 +#define nr 6 +#define pcrel 7 +#define lr 8 +#define rxl 9 +#define rlr 10 +#define rrl 11 +#define iml 12 +#define imr 13 +#define a1r 14 +#define a1l 15 +#define a2r 16 +#define a2l 17 +#define a3 18 +#define a4 19 +#define a5 20 +#define V 1 +#define S 2 +#define VM 3 +#define A 4 +#define VL 5 +#define VS 6 +#define VLS 7 +#define PSW 8 +#define PC 9 +#define ITR 10 +#define VV 11 +#define ITSR 12 +#define TOC 13 +#define CIR 14 +#define TTR 15 +#define VMU 16 +#define VML 17 +#define ICR 18 +#define TCPU 19 +#define CPUID 20 +#define TID 21 +char *op[] = { + "", + "v0\0v1\0v2\0v3\0v4\0v5\0v6\0v7", + "s0\0s1\0s2\0s3\0s4\0s5\0s6\0s7", + "vm", + "sp\0a1\0a2\0a3\0a4\0a5\0ap\0fp", + "vl", + "vs", + "vls", + "psw", + "pc", + "itr", + "vv", + "itsr", + "toc", + "cir", + "ttr", + "vmu", + "vml", + "icr", + "tcpu", + "cpuid", + "tid", +}; +struct formstr format0[] = { + {0,0,rrr,V,S,S}, /* mov */ + {0,0,rrr,S,S,V}, /* mov */ + {1,1,rrr,V,V,V}, /* merg.t */ + {2,1,rrr,V,V,V}, /* mask.t */ + {1,2,rrr,V,S,V}, /* merg.f */ + {2,2,rrr,V,S,V}, /* mask.f */ + {1,1,rrr,V,S,V}, /* merg.t */ + {2,1,rrr,V,S,V}, /* mask.t */ + {3,3,rrr,V,V,V}, /* mul.s */ + {3,4,rrr,V,V,V}, /* mul.d */ + {4,3,rrr,V,V,V}, /* div.s */ + {4,4,rrr,V,V,V}, /* div.d */ + {3,3,rrr,V,S,V}, /* mul.s */ + {3,4,rrr,V,S,V}, /* mul.d */ + {4,3,rrr,V,S,V}, /* div.s */ + {4,4,rrr,V,S,V}, /* div.d */ + {5,0,rrr,V,V,V}, /* and */ + {6,0,rrr,V,V,V}, /* or */ + {7,0,rrr,V,V,V}, /* xor */ + {8,0,rrr,V,V,V}, /* shf */ + {5,0,rrr,V,S,V}, /* and */ + {6,0,rrr,V,S,V}, /* or */ + {7,0,rrr,V,S,V}, /* xor */ + {8,0,rrr,V,S,V}, /* shf */ + {9,3,rrr,V,V,V}, /* add.s */ + {9,4,rrr,V,V,V}, /* add.d */ + {10,3,rrr,V,V,V}, /* sub.s */ + {10,4,rrr,V,V,V}, /* sub.d */ + {9,3,rrr,V,S,V}, /* add.s */ + {9,4,rrr,V,S,V}, /* add.d */ + {10,3,rrr,V,S,V}, /* sub.s */ + {10,4,rrr,V,S,V}, /* sub.d */ + {9,5,rrr,V,V,V}, /* add.b */ + {9,6,rrr,V,V,V}, /* add.h */ + {9,7,rrr,V,V,V}, /* add.w */ + {9,8,rrr,V,V,V}, /* add.l */ + {9,5,rrr,V,S,V}, /* add.b */ + {9,6,rrr,V,S,V}, /* add.h */ + {9,7,rrr,V,S,V}, /* add.w */ + {9,8,rrr,V,S,V}, /* add.l */ + {10,5,rrr,V,V,V}, /* sub.b */ + {10,6,rrr,V,V,V}, /* sub.h */ + {10,7,rrr,V,V,V}, /* sub.w */ + {10,8,rrr,V,V,V}, /* sub.l */ + {10,5,rrr,V,S,V}, /* sub.b */ + {10,6,rrr,V,S,V}, /* sub.h */ + {10,7,rrr,V,S,V}, /* sub.w */ + {10,8,rrr,V,S,V}, /* sub.l */ + {3,5,rrr,V,V,V}, /* mul.b */ + {3,6,rrr,V,V,V}, /* mul.h */ + {3,7,rrr,V,V,V}, /* mul.w */ + {3,8,rrr,V,V,V}, /* mul.l */ + {3,5,rrr,V,S,V}, /* mul.b */ + {3,6,rrr,V,S,V}, /* mul.h */ + {3,7,rrr,V,S,V}, /* mul.w */ + {3,8,rrr,V,S,V}, /* mul.l */ + {4,5,rrr,V,V,V}, /* div.b */ + {4,6,rrr,V,V,V}, /* div.h */ + {4,7,rrr,V,V,V}, /* div.w */ + {4,8,rrr,V,V,V}, /* div.l */ + {4,5,rrr,V,S,V}, /* div.b */ + {4,6,rrr,V,S,V}, /* div.h */ + {4,7,rrr,V,S,V}, /* div.w */ + {4,8,rrr,V,S,V}, /* div.l */ +}; +struct formstr format1[] = { + {11,0,xxx,0,0,0}, /* exit */ + {12,0,a3,0,0,0}, /* jmp */ + {13,2,a3,0,0,0}, /* jmpi.f */ + {13,1,a3,0,0,0}, /* jmpi.t */ + {14,2,a3,0,0,0}, /* jmpa.f */ + {14,1,a3,0,0,0}, /* jmpa.t */ + {15,2,a3,0,0,0}, /* jmps.f */ + {15,1,a3,0,0,0}, /* jmps.t */ + {16,0,a3,0,0,0}, /* tac */ + {17,0,a1r,A,0,0}, /* ldea */ + {18,8,a1l,VLS,0,0}, /* ld.l */ + {18,9,a1l,VM,0,0}, /* ld.x */ + {19,0,a3,0,0,0}, /* tas */ + {20,0,a3,0,0,0}, /* pshea */ + {21,8,a2l,VLS,0,0}, /* st.l */ + {21,9,a2l,VM,0,0}, /* st.x */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {22,0,a3,0,0,0}, /* call */ + {23,0,a3,0,0,0}, /* calls */ + {24,0,a3,0,0,0}, /* callq */ + {25,0,a1r,A,0,0}, /* pfork */ + {26,5,a2r,S,0,0}, /* ste.b */ + {26,6,a2r,S,0,0}, /* ste.h */ + {26,7,a2r,S,0,0}, /* ste.w */ + {26,8,a2r,S,0,0}, /* ste.l */ + {18,5,a1r,A,0,0}, /* ld.b */ + {18,6,a1r,A,0,0}, /* ld.h */ + {18,7,a1r,A,0,0}, /* ld.w */ + {27,7,a1r,A,0,0}, /* incr.w */ + {21,5,a2r,A,0,0}, /* st.b */ + {21,6,a2r,A,0,0}, /* st.h */ + {21,7,a2r,A,0,0}, /* st.w */ + {27,8,a1r,S,0,0}, /* incr.l */ + {18,5,a1r,S,0,0}, /* ld.b */ + {18,6,a1r,S,0,0}, /* ld.h */ + {18,7,a1r,S,0,0}, /* ld.w */ + {18,8,a1r,S,0,0}, /* ld.l */ + {21,5,a2r,S,0,0}, /* st.b */ + {21,6,a2r,S,0,0}, /* st.h */ + {21,7,a2r,S,0,0}, /* st.w */ + {21,8,a2r,S,0,0}, /* st.l */ + {18,5,a1r,V,0,0}, /* ld.b */ + {18,6,a1r,V,0,0}, /* ld.h */ + {18,7,a1r,V,0,0}, /* ld.w */ + {18,8,a1r,V,0,0}, /* ld.l */ + {21,5,a2r,V,0,0}, /* st.b */ + {21,6,a2r,V,0,0}, /* st.h */ + {21,7,a2r,V,0,0}, /* st.w */ + {21,8,a2r,V,0,0}, /* st.l */ +}; +struct formstr format2[] = { + {28,5,rr,A,A,0}, /* cvtw.b */ + {28,6,rr,A,A,0}, /* cvtw.h */ + {29,7,rr,A,A,0}, /* cvtb.w */ + {30,7,rr,A,A,0}, /* cvth.w */ + {28,5,rr,S,S,0}, /* cvtw.b */ + {28,6,rr,S,S,0}, /* cvtw.h */ + {29,7,rr,S,S,0}, /* cvtb.w */ + {30,7,rr,S,S,0}, /* cvth.w */ + {28,3,rr,S,S,0}, /* cvtw.s */ + {31,7,rr,S,S,0}, /* cvts.w */ + {32,3,rr,S,S,0}, /* cvtd.s */ + {31,4,rr,S,S,0}, /* cvts.d */ + {31,8,rr,S,S,0}, /* cvts.l */ + {32,8,rr,S,S,0}, /* cvtd.l */ + {33,3,rr,S,S,0}, /* cvtl.s */ + {33,4,rr,S,S,0}, /* cvtl.d */ + {34,0,rr,A,A,0}, /* ldpa */ + {8,0,nr,A,0,0}, /* shf */ + {18,6,nr,A,0,0}, /* ld.h */ + {18,7,nr,A,0,0}, /* ld.w */ + {33,7,rr,S,S,0}, /* cvtl.w */ + {28,8,rr,S,S,0}, /* cvtw.l */ + {35,1,rr,S,S,0}, /* plc.t */ + {36,0,rr,S,S,0}, /* tzc */ + {37,6,rr,A,A,0}, /* eq.h */ + {37,7,rr,A,A,0}, /* eq.w */ + {37,6,nr,A,0,0}, /* eq.h */ + {37,7,nr,A,0,0}, /* eq.w */ + {37,5,rr,S,S,0}, /* eq.b */ + {37,6,rr,S,S,0}, /* eq.h */ + {37,7,rr,S,S,0}, /* eq.w */ + {37,8,rr,S,S,0}, /* eq.l */ + {38,6,rr,A,A,0}, /* leu.h */ + {38,7,rr,A,A,0}, /* leu.w */ + {38,6,nr,A,0,0}, /* leu.h */ + {38,7,nr,A,0,0}, /* leu.w */ + {38,5,rr,S,S,0}, /* leu.b */ + {38,6,rr,S,S,0}, /* leu.h */ + {38,7,rr,S,S,0}, /* leu.w */ + {38,8,rr,S,S,0}, /* leu.l */ + {39,6,rr,A,A,0}, /* ltu.h */ + {39,7,rr,A,A,0}, /* ltu.w */ + {39,6,nr,A,0,0}, /* ltu.h */ + {39,7,nr,A,0,0}, /* ltu.w */ + {39,5,rr,S,S,0}, /* ltu.b */ + {39,6,rr,S,S,0}, /* ltu.h */ + {39,7,rr,S,S,0}, /* ltu.w */ + {39,8,rr,S,S,0}, /* ltu.l */ + {40,6,rr,A,A,0}, /* le.h */ + {40,7,rr,A,A,0}, /* le.w */ + {40,6,nr,A,0,0}, /* le.h */ + {40,7,nr,A,0,0}, /* le.w */ + {40,5,rr,S,S,0}, /* le.b */ + {40,6,rr,S,S,0}, /* le.h */ + {40,7,rr,S,S,0}, /* le.w */ + {40,8,rr,S,S,0}, /* le.l */ + {41,6,rr,A,A,0}, /* lt.h */ + {41,7,rr,A,A,0}, /* lt.w */ + {41,6,nr,A,0,0}, /* lt.h */ + {41,7,nr,A,0,0}, /* lt.w */ + {41,5,rr,S,S,0}, /* lt.b */ + {41,6,rr,S,S,0}, /* lt.h */ + {41,7,rr,S,S,0}, /* lt.w */ + {41,8,rr,S,S,0}, /* lt.l */ + {9,7,rr,S,A,0}, /* add.w */ + {8,0,rr,A,A,0}, /* shf */ + {0,0,rr,A,A,0}, /* mov */ + {0,0,rr,S,A,0}, /* mov */ + {0,7,rr,S,S,0}, /* mov.w */ + {8,0,rr,S,S,0}, /* shf */ + {0,0,rr,S,S,0}, /* mov */ + {0,0,rr,A,S,0}, /* mov */ + {5,0,rr,A,A,0}, /* and */ + {6,0,rr,A,A,0}, /* or */ + {7,0,rr,A,A,0}, /* xor */ + {42,0,rr,A,A,0}, /* not */ + {5,0,rr,S,S,0}, /* and */ + {6,0,rr,S,S,0}, /* or */ + {7,0,rr,S,S,0}, /* xor */ + {42,0,rr,S,S,0}, /* not */ + {40,3,rr,S,S,0}, /* le.s */ + {40,4,rr,S,S,0}, /* le.d */ + {41,3,rr,S,S,0}, /* lt.s */ + {41,4,rr,S,S,0}, /* lt.d */ + {9,3,rr,S,S,0}, /* add.s */ + {9,4,rr,S,S,0}, /* add.d */ + {10,3,rr,S,S,0}, /* sub.s */ + {10,4,rr,S,S,0}, /* sub.d */ + {37,3,rr,S,S,0}, /* eq.s */ + {37,4,rr,S,S,0}, /* eq.d */ + {43,6,rr,A,A,0}, /* neg.h */ + {43,7,rr,A,A,0}, /* neg.w */ + {3,3,rr,S,S,0}, /* mul.s */ + {3,4,rr,S,S,0}, /* mul.d */ + {4,3,rr,S,S,0}, /* div.s */ + {4,4,rr,S,S,0}, /* div.d */ + {9,6,rr,A,A,0}, /* add.h */ + {9,7,rr,A,A,0}, /* add.w */ + {9,6,nr,A,0,0}, /* add.h */ + {9,7,nr,A,0,0}, /* add.w */ + {9,5,rr,S,S,0}, /* add.b */ + {9,6,rr,S,S,0}, /* add.h */ + {9,7,rr,S,S,0}, /* add.w */ + {9,8,rr,S,S,0}, /* add.l */ + {10,6,rr,A,A,0}, /* sub.h */ + {10,7,rr,A,A,0}, /* sub.w */ + {10,6,nr,A,0,0}, /* sub.h */ + {10,7,nr,A,0,0}, /* sub.w */ + {10,5,rr,S,S,0}, /* sub.b */ + {10,6,rr,S,S,0}, /* sub.h */ + {10,7,rr,S,S,0}, /* sub.w */ + {10,8,rr,S,S,0}, /* sub.l */ + {3,6,rr,A,A,0}, /* mul.h */ + {3,7,rr,A,A,0}, /* mul.w */ + {3,6,nr,A,0,0}, /* mul.h */ + {3,7,nr,A,0,0}, /* mul.w */ + {3,5,rr,S,S,0}, /* mul.b */ + {3,6,rr,S,S,0}, /* mul.h */ + {3,7,rr,S,S,0}, /* mul.w */ + {3,8,rr,S,S,0}, /* mul.l */ + {4,6,rr,A,A,0}, /* div.h */ + {4,7,rr,A,A,0}, /* div.w */ + {4,6,nr,A,0,0}, /* div.h */ + {4,7,nr,A,0,0}, /* div.w */ + {4,5,rr,S,S,0}, /* div.b */ + {4,6,rr,S,S,0}, /* div.h */ + {4,7,rr,S,S,0}, /* div.w */ + {4,8,rr,S,S,0}, /* div.l */ +}; +struct formstr format3[] = { + {32,3,rr,V,V,0}, /* cvtd.s */ + {31,4,rr,V,V,0}, /* cvts.d */ + {33,4,rr,V,V,0}, /* cvtl.d */ + {32,8,rr,V,V,0}, /* cvtd.l */ + {0,0,rrl,S,S,VM}, /* mov */ + {0,0,rlr,S,VM,S}, /* mov */ + {0,0,0,0,0,0}, + {44,0,rr,S,S,0}, /* lop */ + {36,0,rr,V,V,0}, /* tzc */ + {44,0,rr,V,V,0}, /* lop */ + {0,0,0,0,0,0}, + {42,0,rr,V,V,0}, /* not */ + {8,0,rr,S,V,0}, /* shf */ + {35,1,rr,V,V,0}, /* plc.t */ + {45,2,rr,V,V,0}, /* cprs.f */ + {45,1,rr,V,V,0}, /* cprs.t */ + {37,3,rr,V,V,0}, /* eq.s */ + {37,4,rr,V,V,0}, /* eq.d */ + {43,3,rr,V,V,0}, /* neg.s */ + {43,4,rr,V,V,0}, /* neg.d */ + {37,3,rr,S,V,0}, /* eq.s */ + {37,4,rr,S,V,0}, /* eq.d */ + {43,3,rr,S,S,0}, /* neg.s */ + {43,4,rr,S,S,0}, /* neg.d */ + {40,3,rr,V,V,0}, /* le.s */ + {40,4,rr,V,V,0}, /* le.d */ + {41,3,rr,V,V,0}, /* lt.s */ + {41,4,rr,V,V,0}, /* lt.d */ + {40,3,rr,S,V,0}, /* le.s */ + {40,4,rr,S,V,0}, /* le.d */ + {41,3,rr,S,V,0}, /* lt.s */ + {41,4,rr,S,V,0}, /* lt.d */ + {37,5,rr,V,V,0}, /* eq.b */ + {37,6,rr,V,V,0}, /* eq.h */ + {37,7,rr,V,V,0}, /* eq.w */ + {37,8,rr,V,V,0}, /* eq.l */ + {37,5,rr,S,V,0}, /* eq.b */ + {37,6,rr,S,V,0}, /* eq.h */ + {37,7,rr,S,V,0}, /* eq.w */ + {37,8,rr,S,V,0}, /* eq.l */ + {40,5,rr,V,V,0}, /* le.b */ + {40,6,rr,V,V,0}, /* le.h */ + {40,7,rr,V,V,0}, /* le.w */ + {40,8,rr,V,V,0}, /* le.l */ + {40,5,rr,S,V,0}, /* le.b */ + {40,6,rr,S,V,0}, /* le.h */ + {40,7,rr,S,V,0}, /* le.w */ + {40,8,rr,S,V,0}, /* le.l */ + {41,5,rr,V,V,0}, /* lt.b */ + {41,6,rr,V,V,0}, /* lt.h */ + {41,7,rr,V,V,0}, /* lt.w */ + {41,8,rr,V,V,0}, /* lt.l */ + {41,5,rr,S,V,0}, /* lt.b */ + {41,6,rr,S,V,0}, /* lt.h */ + {41,7,rr,S,V,0}, /* lt.w */ + {41,8,rr,S,V,0}, /* lt.l */ + {43,5,rr,V,V,0}, /* neg.b */ + {43,6,rr,V,V,0}, /* neg.h */ + {43,7,rr,V,V,0}, /* neg.w */ + {43,8,rr,V,V,0}, /* neg.l */ + {43,5,rr,S,S,0}, /* neg.b */ + {43,6,rr,S,S,0}, /* neg.h */ + {43,7,rr,S,S,0}, /* neg.w */ + {43,8,rr,S,S,0}, /* neg.l */ +}; +struct formstr format4[] = { + {46,0,nops,0,0,0}, /* nop */ + {47,0,pcrel,0,0,0}, /* br */ + {48,2,pcrel,0,0,0}, /* bri.f */ + {48,1,pcrel,0,0,0}, /* bri.t */ + {49,2,pcrel,0,0,0}, /* bra.f */ + {49,1,pcrel,0,0,0}, /* bra.t */ + {50,2,pcrel,0,0,0}, /* brs.f */ + {50,1,pcrel,0,0,0}, /* brs.t */ +}; +struct formstr format5[] = { + {51,5,rr,V,V,0}, /* ldvi.b */ + {51,6,rr,V,V,0}, /* ldvi.h */ + {51,7,rr,V,V,0}, /* ldvi.w */ + {51,8,rr,V,V,0}, /* ldvi.l */ + {28,3,rr,V,V,0}, /* cvtw.s */ + {31,7,rr,V,V,0}, /* cvts.w */ + {28,8,rr,V,V,0}, /* cvtw.l */ + {33,7,rr,V,V,0}, /* cvtl.w */ + {52,5,rxr,V,V,0}, /* stvi.b */ + {52,6,rxr,V,V,0}, /* stvi.h */ + {52,7,rxr,V,V,0}, /* stvi.w */ + {52,8,rxr,V,V,0}, /* stvi.l */ + {52,5,rxr,S,V,0}, /* stvi.b */ + {52,6,rxr,S,V,0}, /* stvi.h */ + {52,7,rxr,S,V,0}, /* stvi.w */ + {52,8,rxr,S,V,0}, /* stvi.l */ +}; +struct formstr format6[] = { + {53,0,r,A,0,0}, /* ldsdr */ + {54,0,r,A,0,0}, /* ldkdr */ + {55,3,r,S,0,0}, /* ln.s */ + {55,4,r,S,0,0}, /* ln.d */ + {56,0,nops,0,0,0}, /* patu */ + {57,0,r,A,0,0}, /* pate */ + {58,0,nops,0,0,0}, /* pich */ + {59,0,nops,0,0,0}, /* plch */ + {0,0,lr,PSW,A,0}, /* mov */ + {0,0,rxl,A,PSW,0}, /* mov */ + {0,0,lr,PC,A,0}, /* mov */ + {60,0,r,S,0,0}, /* idle */ + {0,0,lr,ITR,S,0}, /* mov */ + {0,0,rxl,S,ITR,0}, /* mov */ + {0,0,0,0,0,0}, + {0,0,rxl,S,ITSR,0}, /* mov */ + {61,0,nops,0,0,0}, /* rtnq */ + {62,0,nops,0,0,0}, /* cfork */ + {63,0,nops,0,0,0}, /* rtn */ + {64,0,nops,0,0,0}, /* wfork */ + {65,0,nops,0,0,0}, /* join */ + {66,0,nops,0,0,0}, /* rtnc */ + {67,3,r,S,0,0}, /* exp.s */ + {67,4,r,S,0,0}, /* exp.d */ + {68,3,r,S,0,0}, /* sin.s */ + {68,4,r,S,0,0}, /* sin.d */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {69,3,r,S,0,0}, /* cos.s */ + {69,4,r,S,0,0}, /* cos.d */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {70,7,r,A,0,0}, /* psh.w */ + {0,0,0,0,0,0}, + {71,7,r,A,0,0}, /* pop.w */ + {0,0,0,0,0,0}, + {70,7,r,S,0,0}, /* psh.w */ + {70,8,r,S,0,0}, /* psh.l */ + {71,7,r,S,0,0}, /* pop.w */ + {71,8,r,S,0,0}, /* pop.l */ + {72,0,nops,0,0,0}, /* eni */ + {73,0,nops,0,0,0}, /* dsi */ + {74,0,nops,0,0,0}, /* bkpt */ + {75,0,nops,0,0,0}, /* msync */ + {76,0,r,S,0,0}, /* mski */ + {77,0,r,S,0,0}, /* xmti */ + {0,0,rxl,S,VV,0}, /* mov */ + {78,0,nops,0,0,0}, /* tstvv */ + {0,0,lr,VS,A,0}, /* mov */ + {0,0,rxl,A,VS,0}, /* mov */ + {0,0,lr,VL,A,0}, /* mov */ + {0,0,rxl,A,VL,0}, /* mov */ + {0,7,lr,VS,S,0}, /* mov.w */ + {0,7,rxl,S,VS,0}, /* mov.w */ + {0,7,lr,VL,S,0}, /* mov.w */ + {0,7,rxl,S,VL,0}, /* mov.w */ + {79,0,r,A,0,0}, /* diag */ + {80,0,nops,0,0,0}, /* pbkpt */ + {81,3,r,S,0,0}, /* sqrt.s */ + {81,4,r,S,0,0}, /* sqrt.d */ + {82,0,nops,0,0,0}, /* casr */ + {0,0,0,0,0,0}, + {83,3,r,S,0,0}, /* atan.s */ + {83,4,r,S,0,0}, /* atan.d */ +}; +struct formstr format7[] = { + {84,5,r,V,0,0}, /* sum.b */ + {84,6,r,V,0,0}, /* sum.h */ + {84,7,r,V,0,0}, /* sum.w */ + {84,8,r,V,0,0}, /* sum.l */ + {85,0,r,V,0,0}, /* all */ + {86,0,r,V,0,0}, /* any */ + {87,0,r,V,0,0}, /* parity */ + {0,0,0,0,0,0}, + {88,5,r,V,0,0}, /* max.b */ + {88,6,r,V,0,0}, /* max.h */ + {88,7,r,V,0,0}, /* max.w */ + {88,8,r,V,0,0}, /* max.l */ + {89,5,r,V,0,0}, /* min.b */ + {89,6,r,V,0,0}, /* min.h */ + {89,7,r,V,0,0}, /* min.w */ + {89,8,r,V,0,0}, /* min.l */ + {84,3,r,V,0,0}, /* sum.s */ + {84,4,r,V,0,0}, /* sum.d */ + {90,3,r,V,0,0}, /* prod.s */ + {90,4,r,V,0,0}, /* prod.d */ + {88,3,r,V,0,0}, /* max.s */ + {88,4,r,V,0,0}, /* max.d */ + {89,3,r,V,0,0}, /* min.s */ + {89,4,r,V,0,0}, /* min.d */ + {90,5,r,V,0,0}, /* prod.b */ + {90,6,r,V,0,0}, /* prod.h */ + {90,7,r,V,0,0}, /* prod.w */ + {90,8,r,V,0,0}, /* prod.l */ + {35,2,lr,VM,S,0}, /* plc.f */ + {35,1,lr,VM,S,0}, /* plc.t */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, +}; +struct formstr formatx[] = { + {0,0,0,0,0,0}, +}; +struct formstr format1a[] = { + {91,0,imr,A,0,0}, /* halt */ + {92,0,a4,0,0,0}, /* sysc */ + {18,6,imr,A,0,0}, /* ld.h */ + {18,7,imr,A,0,0}, /* ld.w */ + {5,0,imr,A,0,0}, /* and */ + {6,0,imr,A,0,0}, /* or */ + {7,0,imr,A,0,0}, /* xor */ + {8,0,imr,A,0,0}, /* shf */ + {9,6,imr,A,0,0}, /* add.h */ + {9,7,imr,A,0,0}, /* add.w */ + {10,6,imr,A,0,0}, /* sub.h */ + {10,7,imr,A,0,0}, /* sub.w */ + {3,6,imr,A,0,0}, /* mul.h */ + {3,7,imr,A,0,0}, /* mul.w */ + {4,6,imr,A,0,0}, /* div.h */ + {4,7,imr,A,0,0}, /* div.w */ + {18,7,iml,VL,0,0}, /* ld.w */ + {18,7,iml,VS,0,0}, /* ld.w */ + {0,0,0,0,0,0}, + {8,7,imr,S,0,0}, /* shf.w */ + {93,0,a5,0,0,0}, /* trap */ + {0,0,0,0,0,0}, + {37,6,imr,A,0,0}, /* eq.h */ + {37,7,imr,A,0,0}, /* eq.w */ + {38,6,imr,A,0,0}, /* leu.h */ + {38,7,imr,A,0,0}, /* leu.w */ + {39,6,imr,A,0,0}, /* ltu.h */ + {39,7,imr,A,0,0}, /* ltu.w */ + {40,6,imr,A,0,0}, /* le.h */ + {40,7,imr,A,0,0}, /* le.w */ + {41,6,imr,A,0,0}, /* lt.h */ + {41,7,imr,A,0,0}, /* lt.w */ +}; +struct formstr format1b[] = { + {18,4,imr,S,0,0}, /* ld.d */ + {18,10,imr,S,0,0}, /* ld.u */ + {18,8,imr,S,0,0}, /* ld.l */ + {18,7,imr,S,0,0}, /* ld.w */ + {5,0,imr,S,0,0}, /* and */ + {6,0,imr,S,0,0}, /* or */ + {7,0,imr,S,0,0}, /* xor */ + {8,0,imr,S,0,0}, /* shf */ + {9,6,imr,S,0,0}, /* add.h */ + {9,7,imr,S,0,0}, /* add.w */ + {10,6,imr,S,0,0}, /* sub.h */ + {10,7,imr,S,0,0}, /* sub.w */ + {3,6,imr,S,0,0}, /* mul.h */ + {3,7,imr,S,0,0}, /* mul.w */ + {4,6,imr,S,0,0}, /* div.h */ + {4,7,imr,S,0,0}, /* div.w */ + {9,3,imr,S,0,0}, /* add.s */ + {10,3,imr,S,0,0}, /* sub.s */ + {3,3,imr,S,0,0}, /* mul.s */ + {4,3,imr,S,0,0}, /* div.s */ + {40,3,imr,S,0,0}, /* le.s */ + {41,3,imr,S,0,0}, /* lt.s */ + {37,6,imr,S,0,0}, /* eq.h */ + {37,7,imr,S,0,0}, /* eq.w */ + {38,6,imr,S,0,0}, /* leu.h */ + {38,7,imr,S,0,0}, /* leu.w */ + {39,6,imr,S,0,0}, /* ltu.h */ + {39,7,imr,S,0,0}, /* ltu.w */ + {40,6,imr,S,0,0}, /* le.h */ + {40,7,imr,S,0,0}, /* le.w */ + {41,6,imr,S,0,0}, /* lt.h */ + {41,7,imr,S,0,0}, /* lt.w */ +}; +struct formstr e0_format0[] = { + {10,3,rrr,S,V,V}, /* sub.s */ + {10,4,rrr,S,V,V}, /* sub.d */ + {4,3,rrr,S,V,V}, /* div.s */ + {4,4,rrr,S,V,V}, /* div.d */ + {10,11,rrr,S,V,V}, /* sub.s.f */ + {10,12,rrr,S,V,V}, /* sub.d.f */ + {4,11,rrr,S,V,V}, /* div.s.f */ + {4,12,rrr,S,V,V}, /* div.d.f */ + {3,11,rrr,V,V,V}, /* mul.s.f */ + {3,12,rrr,V,V,V}, /* mul.d.f */ + {4,11,rrr,V,V,V}, /* div.s.f */ + {4,12,rrr,V,V,V}, /* div.d.f */ + {3,11,rrr,V,S,V}, /* mul.s.f */ + {3,12,rrr,V,S,V}, /* mul.d.f */ + {4,11,rrr,V,S,V}, /* div.s.f */ + {4,12,rrr,V,S,V}, /* div.d.f */ + {5,2,rrr,V,V,V}, /* and.f */ + {6,2,rrr,V,V,V}, /* or.f */ + {7,2,rrr,V,V,V}, /* xor.f */ + {8,2,rrr,V,V,V}, /* shf.f */ + {5,2,rrr,V,S,V}, /* and.f */ + {6,2,rrr,V,S,V}, /* or.f */ + {7,2,rrr,V,S,V}, /* xor.f */ + {8,2,rrr,V,S,V}, /* shf.f */ + {9,11,rrr,V,V,V}, /* add.s.f */ + {9,12,rrr,V,V,V}, /* add.d.f */ + {10,11,rrr,V,V,V}, /* sub.s.f */ + {10,12,rrr,V,V,V}, /* sub.d.f */ + {9,11,rrr,V,S,V}, /* add.s.f */ + {9,12,rrr,V,S,V}, /* add.d.f */ + {10,11,rrr,V,S,V}, /* sub.s.f */ + {10,12,rrr,V,S,V}, /* sub.d.f */ + {9,13,rrr,V,V,V}, /* add.b.f */ + {9,14,rrr,V,V,V}, /* add.h.f */ + {9,15,rrr,V,V,V}, /* add.w.f */ + {9,16,rrr,V,V,V}, /* add.l.f */ + {9,13,rrr,V,S,V}, /* add.b.f */ + {9,14,rrr,V,S,V}, /* add.h.f */ + {9,15,rrr,V,S,V}, /* add.w.f */ + {9,16,rrr,V,S,V}, /* add.l.f */ + {10,13,rrr,V,V,V}, /* sub.b.f */ + {10,14,rrr,V,V,V}, /* sub.h.f */ + {10,15,rrr,V,V,V}, /* sub.w.f */ + {10,16,rrr,V,V,V}, /* sub.l.f */ + {10,13,rrr,V,S,V}, /* sub.b.f */ + {10,14,rrr,V,S,V}, /* sub.h.f */ + {10,15,rrr,V,S,V}, /* sub.w.f */ + {10,16,rrr,V,S,V}, /* sub.l.f */ + {3,13,rrr,V,V,V}, /* mul.b.f */ + {3,14,rrr,V,V,V}, /* mul.h.f */ + {3,15,rrr,V,V,V}, /* mul.w.f */ + {3,16,rrr,V,V,V}, /* mul.l.f */ + {3,13,rrr,V,S,V}, /* mul.b.f */ + {3,14,rrr,V,S,V}, /* mul.h.f */ + {3,15,rrr,V,S,V}, /* mul.w.f */ + {3,16,rrr,V,S,V}, /* mul.l.f */ + {4,13,rrr,V,V,V}, /* div.b.f */ + {4,14,rrr,V,V,V}, /* div.h.f */ + {4,15,rrr,V,V,V}, /* div.w.f */ + {4,16,rrr,V,V,V}, /* div.l.f */ + {4,13,rrr,V,S,V}, /* div.b.f */ + {4,14,rrr,V,S,V}, /* div.h.f */ + {4,15,rrr,V,S,V}, /* div.w.f */ + {4,16,rrr,V,S,V}, /* div.l.f */ +}; +struct formstr e0_format1[] = { + {0,0,0,0,0,0}, + {94,0,a3,0,0,0}, /* tst */ + {95,0,a3,0,0,0}, /* lck */ + {96,0,a3,0,0,0}, /* ulk */ + {17,0,a1r,S,0,0}, /* ldea */ + {97,0,a1r,A,0,0}, /* spawn */ + {98,0,a1r,A,0,0}, /* ldcmr */ + {99,0,a2r,A,0,0}, /* stcmr */ + {100,0,a1r,A,0,0}, /* popr */ + {101,0,a2r,A,0,0}, /* pshr */ + {102,7,a1r,A,0,0}, /* rcvr.w */ + {103,7,a2r,A,0,0}, /* matm.w */ + {104,7,a2r,A,0,0}, /* sndr.w */ + {104,8,a2r,S,0,0}, /* sndr.l */ + {102,8,a1r,S,0,0}, /* rcvr.l */ + {103,8,a2r,S,0,0}, /* matm.l */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {105,7,a2r,A,0,0}, /* putr.w */ + {105,8,a2r,S,0,0}, /* putr.l */ + {106,7,a1r,A,0,0}, /* getr.w */ + {106,8,a1r,S,0,0}, /* getr.l */ + {26,13,a2r,S,0,0}, /* ste.b.f */ + {26,14,a2r,S,0,0}, /* ste.h.f */ + {26,15,a2r,S,0,0}, /* ste.w.f */ + {26,16,a2r,S,0,0}, /* ste.l.f */ + {107,7,a2r,A,0,0}, /* matr.w */ + {108,7,a2r,A,0,0}, /* mat.w */ + {109,7,a1r,A,0,0}, /* get.w */ + {110,7,a1r,A,0,0}, /* rcv.w */ + {0,0,0,0,0,0}, + {111,7,a1r,A,0,0}, /* inc.w */ + {112,7,a2r,A,0,0}, /* put.w */ + {113,7,a2r,A,0,0}, /* snd.w */ + {107,8,a2r,S,0,0}, /* matr.l */ + {108,8,a2r,S,0,0}, /* mat.l */ + {109,8,a1r,S,0,0}, /* get.l */ + {110,8,a1r,S,0,0}, /* rcv.l */ + {0,0,0,0,0,0}, + {111,8,a1r,S,0,0}, /* inc.l */ + {112,8,a2r,S,0,0}, /* put.l */ + {113,8,a2r,S,0,0}, /* snd.l */ + {18,13,a1r,V,0,0}, /* ld.b.f */ + {18,14,a1r,V,0,0}, /* ld.h.f */ + {18,15,a1r,V,0,0}, /* ld.w.f */ + {18,16,a1r,V,0,0}, /* ld.l.f */ + {21,13,a2r,V,0,0}, /* st.b.f */ + {21,14,a2r,V,0,0}, /* st.h.f */ + {21,15,a2r,V,0,0}, /* st.w.f */ + {21,16,a2r,V,0,0}, /* st.l.f */ +}; +struct formstr e0_format2[] = { + {28,5,rr,V,V,0}, /* cvtw.b */ + {28,6,rr,V,V,0}, /* cvtw.h */ + {29,7,rr,V,V,0}, /* cvtb.w */ + {30,7,rr,V,V,0}, /* cvth.w */ + {28,13,rr,V,V,0}, /* cvtw.b.f */ + {28,14,rr,V,V,0}, /* cvtw.h.f */ + {29,15,rr,V,V,0}, /* cvtb.w.f */ + {30,15,rr,V,V,0}, /* cvth.w.f */ + {31,8,rr,V,V,0}, /* cvts.l */ + {32,7,rr,V,V,0}, /* cvtd.w */ + {33,3,rr,V,V,0}, /* cvtl.s */ + {28,4,rr,V,V,0}, /* cvtw.d */ + {31,16,rr,V,V,0}, /* cvts.l.f */ + {32,15,rr,V,V,0}, /* cvtd.w.f */ + {33,11,rr,V,V,0}, /* cvtl.s.f */ + {28,12,rr,V,V,0}, /* cvtw.d.f */ + {114,0,rr,S,S,0}, /* enal */ + {8,7,rr,S,S,0}, /* shf.w */ + {115,0,rr,S,S,0}, /* enag */ + {0,0,0,0,0,0}, + {28,4,rr,S,S,0}, /* cvtw.d */ + {32,7,rr,S,S,0}, /* cvtd.w */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {116,3,rr,S,S,0}, /* frint.s */ + {116,4,rr,S,S,0}, /* frint.d */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {116,3,rr,V,V,0}, /* frint.s */ + {116,4,rr,V,V,0}, /* frint.d */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {116,11,rr,V,V,0}, /* frint.s.f */ + {116,12,rr,V,V,0}, /* frint.d.f */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {81,3,rr,V,V,0}, /* sqrt.s */ + {81,4,rr,V,V,0}, /* sqrt.d */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {81,11,rr,V,V,0}, /* sqrt.s.f */ + {81,12,rr,V,V,0}, /* sqrt.d.f */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, +}; +struct formstr e0_format3[] = { + {32,11,rr,V,V,0}, /* cvtd.s.f */ + {31,12,rr,V,V,0}, /* cvts.d.f */ + {33,12,rr,V,V,0}, /* cvtl.d.f */ + {32,16,rr,V,V,0}, /* cvtd.l.f */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {36,2,rr,V,V,0}, /* tzc.f */ + {44,2,rr,V,V,0}, /* lop.f */ + {117,2,rr,V,V,0}, /* xpnd.f */ + {42,2,rr,V,V,0}, /* not.f */ + {8,2,rr,S,V,0}, /* shf.f */ + {35,17,rr,V,V,0}, /* plc.t.f */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {37,11,rr,V,V,0}, /* eq.s.f */ + {37,12,rr,V,V,0}, /* eq.d.f */ + {43,11,rr,V,V,0}, /* neg.s.f */ + {43,12,rr,V,V,0}, /* neg.d.f */ + {37,11,rr,S,V,0}, /* eq.s.f */ + {37,12,rr,S,V,0}, /* eq.d.f */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {40,11,rr,V,V,0}, /* le.s.f */ + {40,12,rr,V,V,0}, /* le.d.f */ + {41,11,rr,V,V,0}, /* lt.s.f */ + {41,12,rr,V,V,0}, /* lt.d.f */ + {40,11,rr,S,V,0}, /* le.s.f */ + {40,12,rr,S,V,0}, /* le.d.f */ + {41,11,rr,S,V,0}, /* lt.s.f */ + {41,12,rr,S,V,0}, /* lt.d.f */ + {37,13,rr,V,V,0}, /* eq.b.f */ + {37,14,rr,V,V,0}, /* eq.h.f */ + {37,15,rr,V,V,0}, /* eq.w.f */ + {37,16,rr,V,V,0}, /* eq.l.f */ + {37,13,rr,S,V,0}, /* eq.b.f */ + {37,14,rr,S,V,0}, /* eq.h.f */ + {37,15,rr,S,V,0}, /* eq.w.f */ + {37,16,rr,S,V,0}, /* eq.l.f */ + {40,13,rr,V,V,0}, /* le.b.f */ + {40,14,rr,V,V,0}, /* le.h.f */ + {40,15,rr,V,V,0}, /* le.w.f */ + {40,16,rr,V,V,0}, /* le.l.f */ + {40,13,rr,S,V,0}, /* le.b.f */ + {40,14,rr,S,V,0}, /* le.h.f */ + {40,15,rr,S,V,0}, /* le.w.f */ + {40,16,rr,S,V,0}, /* le.l.f */ + {41,13,rr,V,V,0}, /* lt.b.f */ + {41,14,rr,V,V,0}, /* lt.h.f */ + {41,15,rr,V,V,0}, /* lt.w.f */ + {41,16,rr,V,V,0}, /* lt.l.f */ + {41,13,rr,S,V,0}, /* lt.b.f */ + {41,14,rr,S,V,0}, /* lt.h.f */ + {41,15,rr,S,V,0}, /* lt.w.f */ + {41,16,rr,S,V,0}, /* lt.l.f */ + {43,13,rr,V,V,0}, /* neg.b.f */ + {43,14,rr,V,V,0}, /* neg.h.f */ + {43,15,rr,V,V,0}, /* neg.w.f */ + {43,16,rr,V,V,0}, /* neg.l.f */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, +}; +struct formstr e0_format4[] = { + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, +}; +struct formstr e0_format5[] = { + {51,13,rr,V,V,0}, /* ldvi.b.f */ + {51,14,rr,V,V,0}, /* ldvi.h.f */ + {51,15,rr,V,V,0}, /* ldvi.w.f */ + {51,16,rr,V,V,0}, /* ldvi.l.f */ + {28,11,rr,V,V,0}, /* cvtw.s.f */ + {31,15,rr,V,V,0}, /* cvts.w.f */ + {28,16,rr,V,V,0}, /* cvtw.l.f */ + {33,15,rr,V,V,0}, /* cvtl.w.f */ + {52,13,rxr,V,V,0}, /* stvi.b.f */ + {52,14,rxr,V,V,0}, /* stvi.h.f */ + {52,15,rxr,V,V,0}, /* stvi.w.f */ + {52,16,rxr,V,V,0}, /* stvi.l.f */ + {52,13,rxr,S,V,0}, /* stvi.b.f */ + {52,14,rxr,S,V,0}, /* stvi.h.f */ + {52,15,rxr,S,V,0}, /* stvi.w.f */ + {52,16,rxr,S,V,0}, /* stvi.l.f */ +}; +struct formstr e0_format6[] = { + {0,0,rxl,S,CIR,0}, /* mov */ + {0,0,lr,CIR,S,0}, /* mov */ + {0,0,lr,TOC,S,0}, /* mov */ + {0,0,lr,CPUID,S,0}, /* mov */ + {0,0,rxl,S,TTR,0}, /* mov */ + {0,0,lr,TTR,S,0}, /* mov */ + {118,0,nops,0,0,0}, /* ctrsl */ + {119,0,nops,0,0,0}, /* ctrsg */ + {0,0,rxl,S,VMU,0}, /* mov */ + {0,0,lr,VMU,S,0}, /* mov */ + {0,0,rxl,S,VML,0}, /* mov */ + {0,0,lr,VML,S,0}, /* mov */ + {0,0,rxl,S,ICR,0}, /* mov */ + {0,0,lr,ICR,S,0}, /* mov */ + {0,0,rxl,S,TCPU,0}, /* mov */ + {0,0,lr,TCPU,S,0}, /* mov */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {120,0,nops,0,0,0}, /* stop */ + {0,0,0,0,0,0}, + {0,0,rxl,S,TID,0}, /* mov */ + {0,0,lr,TID,S,0}, /* mov */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, +}; +struct formstr e0_format7[] = { + {84,13,r,V,0,0}, /* sum.b.f */ + {84,14,r,V,0,0}, /* sum.h.f */ + {84,15,r,V,0,0}, /* sum.w.f */ + {84,16,r,V,0,0}, /* sum.l.f */ + {85,2,r,V,0,0}, /* all.f */ + {86,2,r,V,0,0}, /* any.f */ + {87,2,r,V,0,0}, /* parity.f */ + {0,0,0,0,0,0}, + {88,13,r,V,0,0}, /* max.b.f */ + {88,14,r,V,0,0}, /* max.h.f */ + {88,15,r,V,0,0}, /* max.w.f */ + {88,16,r,V,0,0}, /* max.l.f */ + {89,13,r,V,0,0}, /* min.b.f */ + {89,14,r,V,0,0}, /* min.h.f */ + {89,15,r,V,0,0}, /* min.w.f */ + {89,16,r,V,0,0}, /* min.l.f */ + {84,11,r,V,0,0}, /* sum.s.f */ + {84,12,r,V,0,0}, /* sum.d.f */ + {90,11,r,V,0,0}, /* prod.s.f */ + {90,12,r,V,0,0}, /* prod.d.f */ + {88,11,r,V,0,0}, /* max.s.f */ + {88,12,r,V,0,0}, /* max.d.f */ + {89,11,r,V,0,0}, /* min.s.f */ + {89,12,r,V,0,0}, /* min.d.f */ + {90,13,r,V,0,0}, /* prod.b.f */ + {90,14,r,V,0,0}, /* prod.h.f */ + {90,15,r,V,0,0}, /* prod.w.f */ + {90,16,r,V,0,0}, /* prod.l.f */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, +}; +struct formstr e1_format0[] = { + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {10,18,rrr,S,V,V}, /* sub.s.t */ + {10,19,rrr,S,V,V}, /* sub.d.t */ + {4,18,rrr,S,V,V}, /* div.s.t */ + {4,19,rrr,S,V,V}, /* div.d.t */ + {3,18,rrr,V,V,V}, /* mul.s.t */ + {3,19,rrr,V,V,V}, /* mul.d.t */ + {4,18,rrr,V,V,V}, /* div.s.t */ + {4,19,rrr,V,V,V}, /* div.d.t */ + {3,18,rrr,V,S,V}, /* mul.s.t */ + {3,19,rrr,V,S,V}, /* mul.d.t */ + {4,18,rrr,V,S,V}, /* div.s.t */ + {4,19,rrr,V,S,V}, /* div.d.t */ + {5,1,rrr,V,V,V}, /* and.t */ + {6,1,rrr,V,V,V}, /* or.t */ + {7,1,rrr,V,V,V}, /* xor.t */ + {8,1,rrr,V,V,V}, /* shf.t */ + {5,1,rrr,V,S,V}, /* and.t */ + {6,1,rrr,V,S,V}, /* or.t */ + {7,1,rrr,V,S,V}, /* xor.t */ + {8,1,rrr,V,S,V}, /* shf.t */ + {9,18,rrr,V,V,V}, /* add.s.t */ + {9,19,rrr,V,V,V}, /* add.d.t */ + {10,18,rrr,V,V,V}, /* sub.s.t */ + {10,19,rrr,V,V,V}, /* sub.d.t */ + {9,18,rrr,V,S,V}, /* add.s.t */ + {9,19,rrr,V,S,V}, /* add.d.t */ + {10,18,rrr,V,S,V}, /* sub.s.t */ + {10,19,rrr,V,S,V}, /* sub.d.t */ + {9,20,rrr,V,V,V}, /* add.b.t */ + {9,21,rrr,V,V,V}, /* add.h.t */ + {9,22,rrr,V,V,V}, /* add.w.t */ + {9,23,rrr,V,V,V}, /* add.l.t */ + {9,20,rrr,V,S,V}, /* add.b.t */ + {9,21,rrr,V,S,V}, /* add.h.t */ + {9,22,rrr,V,S,V}, /* add.w.t */ + {9,23,rrr,V,S,V}, /* add.l.t */ + {10,20,rrr,V,V,V}, /* sub.b.t */ + {10,21,rrr,V,V,V}, /* sub.h.t */ + {10,22,rrr,V,V,V}, /* sub.w.t */ + {10,23,rrr,V,V,V}, /* sub.l.t */ + {10,20,rrr,V,S,V}, /* sub.b.t */ + {10,21,rrr,V,S,V}, /* sub.h.t */ + {10,22,rrr,V,S,V}, /* sub.w.t */ + {10,23,rrr,V,S,V}, /* sub.l.t */ + {3,20,rrr,V,V,V}, /* mul.b.t */ + {3,21,rrr,V,V,V}, /* mul.h.t */ + {3,22,rrr,V,V,V}, /* mul.w.t */ + {3,23,rrr,V,V,V}, /* mul.l.t */ + {3,20,rrr,V,S,V}, /* mul.b.t */ + {3,21,rrr,V,S,V}, /* mul.h.t */ + {3,22,rrr,V,S,V}, /* mul.w.t */ + {3,23,rrr,V,S,V}, /* mul.l.t */ + {4,20,rrr,V,V,V}, /* div.b.t */ + {4,21,rrr,V,V,V}, /* div.h.t */ + {4,22,rrr,V,V,V}, /* div.w.t */ + {4,23,rrr,V,V,V}, /* div.l.t */ + {4,20,rrr,V,S,V}, /* div.b.t */ + {4,21,rrr,V,S,V}, /* div.h.t */ + {4,22,rrr,V,S,V}, /* div.w.t */ + {4,23,rrr,V,S,V}, /* div.l.t */ +}; +struct formstr e1_format1[] = { + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {26,20,a2r,S,0,0}, /* ste.b.t */ + {26,21,a2r,S,0,0}, /* ste.h.t */ + {26,22,a2r,S,0,0}, /* ste.w.t */ + {26,23,a2r,S,0,0}, /* ste.l.t */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {18,20,a1r,V,0,0}, /* ld.b.t */ + {18,21,a1r,V,0,0}, /* ld.h.t */ + {18,22,a1r,V,0,0}, /* ld.w.t */ + {18,23,a1r,V,0,0}, /* ld.l.t */ + {21,20,a2r,V,0,0}, /* st.b.t */ + {21,21,a2r,V,0,0}, /* st.h.t */ + {21,22,a2r,V,0,0}, /* st.w.t */ + {21,23,a2r,V,0,0}, /* st.l.t */ +}; +struct formstr e1_format2[] = { + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {28,20,rr,V,V,0}, /* cvtw.b.t */ + {28,21,rr,V,V,0}, /* cvtw.h.t */ + {29,22,rr,V,V,0}, /* cvtb.w.t */ + {30,22,rr,V,V,0}, /* cvth.w.t */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {31,23,rr,V,V,0}, /* cvts.l.t */ + {32,22,rr,V,V,0}, /* cvtd.w.t */ + {33,18,rr,V,V,0}, /* cvtl.s.t */ + {28,19,rr,V,V,0}, /* cvtw.d.t */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {116,18,rr,V,V,0}, /* frint.s.t */ + {116,19,rr,V,V,0}, /* frint.d.t */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {81,18,rr,V,V,0}, /* sqrt.s.t */ + {81,19,rr,V,V,0}, /* sqrt.d.t */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, +}; +struct formstr e1_format3[] = { + {32,18,rr,V,V,0}, /* cvtd.s.t */ + {31,19,rr,V,V,0}, /* cvts.d.t */ + {33,19,rr,V,V,0}, /* cvtl.d.t */ + {32,23,rr,V,V,0}, /* cvtd.l.t */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {36,1,rr,V,V,0}, /* tzc.t */ + {44,1,rr,V,V,0}, /* lop.t */ + {117,1,rr,V,V,0}, /* xpnd.t */ + {42,1,rr,V,V,0}, /* not.t */ + {8,1,rr,S,V,0}, /* shf.t */ + {35,24,rr,V,V,0}, /* plc.t.t */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {37,18,rr,V,V,0}, /* eq.s.t */ + {37,19,rr,V,V,0}, /* eq.d.t */ + {43,18,rr,V,V,0}, /* neg.s.t */ + {43,19,rr,V,V,0}, /* neg.d.t */ + {37,18,rr,S,V,0}, /* eq.s.t */ + {37,19,rr,S,V,0}, /* eq.d.t */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {40,18,rr,V,V,0}, /* le.s.t */ + {40,19,rr,V,V,0}, /* le.d.t */ + {41,18,rr,V,V,0}, /* lt.s.t */ + {41,19,rr,V,V,0}, /* lt.d.t */ + {40,18,rr,S,V,0}, /* le.s.t */ + {40,19,rr,S,V,0}, /* le.d.t */ + {41,18,rr,S,V,0}, /* lt.s.t */ + {41,19,rr,S,V,0}, /* lt.d.t */ + {37,20,rr,V,V,0}, /* eq.b.t */ + {37,21,rr,V,V,0}, /* eq.h.t */ + {37,22,rr,V,V,0}, /* eq.w.t */ + {37,23,rr,V,V,0}, /* eq.l.t */ + {37,20,rr,S,V,0}, /* eq.b.t */ + {37,21,rr,S,V,0}, /* eq.h.t */ + {37,22,rr,S,V,0}, /* eq.w.t */ + {37,23,rr,S,V,0}, /* eq.l.t */ + {40,20,rr,V,V,0}, /* le.b.t */ + {40,21,rr,V,V,0}, /* le.h.t */ + {40,22,rr,V,V,0}, /* le.w.t */ + {40,23,rr,V,V,0}, /* le.l.t */ + {40,20,rr,S,V,0}, /* le.b.t */ + {40,21,rr,S,V,0}, /* le.h.t */ + {40,22,rr,S,V,0}, /* le.w.t */ + {40,23,rr,S,V,0}, /* le.l.t */ + {41,20,rr,V,V,0}, /* lt.b.t */ + {41,21,rr,V,V,0}, /* lt.h.t */ + {41,22,rr,V,V,0}, /* lt.w.t */ + {41,23,rr,V,V,0}, /* lt.l.t */ + {41,20,rr,S,V,0}, /* lt.b.t */ + {41,21,rr,S,V,0}, /* lt.h.t */ + {41,22,rr,S,V,0}, /* lt.w.t */ + {41,23,rr,S,V,0}, /* lt.l.t */ + {43,20,rr,V,V,0}, /* neg.b.t */ + {43,21,rr,V,V,0}, /* neg.h.t */ + {43,22,rr,V,V,0}, /* neg.w.t */ + {43,23,rr,V,V,0}, /* neg.l.t */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, +}; +struct formstr e1_format4[] = { + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, +}; +struct formstr e1_format5[] = { + {51,20,rr,V,V,0}, /* ldvi.b.t */ + {51,21,rr,V,V,0}, /* ldvi.h.t */ + {51,22,rr,V,V,0}, /* ldvi.w.t */ + {51,23,rr,V,V,0}, /* ldvi.l.t */ + {28,18,rr,V,V,0}, /* cvtw.s.t */ + {31,22,rr,V,V,0}, /* cvts.w.t */ + {28,23,rr,V,V,0}, /* cvtw.l.t */ + {33,22,rr,V,V,0}, /* cvtl.w.t */ + {52,20,rxr,V,V,0}, /* stvi.b.t */ + {52,21,rxr,V,V,0}, /* stvi.h.t */ + {52,22,rxr,V,V,0}, /* stvi.w.t */ + {52,23,rxr,V,V,0}, /* stvi.l.t */ + {52,20,rxr,S,V,0}, /* stvi.b.t */ + {52,21,rxr,S,V,0}, /* stvi.h.t */ + {52,22,rxr,S,V,0}, /* stvi.w.t */ + {52,23,rxr,S,V,0}, /* stvi.l.t */ +}; +struct formstr e1_format6[] = { + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, +}; +struct formstr e1_format7[] = { + {84,20,r,V,0,0}, /* sum.b.t */ + {84,21,r,V,0,0}, /* sum.h.t */ + {84,22,r,V,0,0}, /* sum.w.t */ + {84,23,r,V,0,0}, /* sum.l.t */ + {85,1,r,V,0,0}, /* all.t */ + {86,1,r,V,0,0}, /* any.t */ + {87,1,r,V,0,0}, /* parity.t */ + {0,0,0,0,0,0}, + {88,20,r,V,0,0}, /* max.b.t */ + {88,21,r,V,0,0}, /* max.h.t */ + {88,22,r,V,0,0}, /* max.w.t */ + {88,23,r,V,0,0}, /* max.l.t */ + {89,20,r,V,0,0}, /* min.b.t */ + {89,21,r,V,0,0}, /* min.h.t */ + {89,22,r,V,0,0}, /* min.w.t */ + {89,23,r,V,0,0}, /* min.l.t */ + {84,18,r,V,0,0}, /* sum.s.t */ + {84,19,r,V,0,0}, /* sum.d.t */ + {90,18,r,V,0,0}, /* prod.s.t */ + {90,19,r,V,0,0}, /* prod.d.t */ + {88,18,r,V,0,0}, /* max.s.t */ + {88,19,r,V,0,0}, /* max.d.t */ + {89,18,r,V,0,0}, /* min.s.t */ + {89,19,r,V,0,0}, /* min.d.t */ + {90,20,r,V,0,0}, /* prod.b.t */ + {90,21,r,V,0,0}, /* prod.h.t */ + {90,22,r,V,0,0}, /* prod.w.t */ + {90,23,r,V,0,0}, /* prod.l.t */ + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, + {0,0,0,0,0,0}, +}; +char *lop[] = { + "mov", /* 0 */ + "merg", /* 1 */ + "mask", /* 2 */ + "mul", /* 3 */ + "div", /* 4 */ + "and", /* 5 */ + "or", /* 6 */ + "xor", /* 7 */ + "shf", /* 8 */ + "add", /* 9 */ + "sub", /* 10 */ + "exit", /* 11 */ + "jmp", /* 12 */ + "jmpi", /* 13 */ + "jmpa", /* 14 */ + "jmps", /* 15 */ + "tac", /* 16 */ + "ldea", /* 17 */ + "ld", /* 18 */ + "tas", /* 19 */ + "pshea", /* 20 */ + "st", /* 21 */ + "call", /* 22 */ + "calls", /* 23 */ + "callq", /* 24 */ + "pfork", /* 25 */ + "ste", /* 26 */ + "incr", /* 27 */ + "cvtw", /* 28 */ + "cvtb", /* 29 */ + "cvth", /* 30 */ + "cvts", /* 31 */ + "cvtd", /* 32 */ + "cvtl", /* 33 */ + "ldpa", /* 34 */ + "plc", /* 35 */ + "tzc", /* 36 */ + "eq", /* 37 */ + "leu", /* 38 */ + "ltu", /* 39 */ + "le", /* 40 */ + "lt", /* 41 */ + "not", /* 42 */ + "neg", /* 43 */ + "lop", /* 44 */ + "cprs", /* 45 */ + "nop", /* 46 */ + "br", /* 47 */ + "bri", /* 48 */ + "bra", /* 49 */ + "brs", /* 50 */ + "ldvi", /* 51 */ + "stvi", /* 52 */ + "ldsdr", /* 53 */ + "ldkdr", /* 54 */ + "ln", /* 55 */ + "patu", /* 56 */ + "pate", /* 57 */ + "pich", /* 58 */ + "plch", /* 59 */ + "idle", /* 60 */ + "rtnq", /* 61 */ + "cfork", /* 62 */ + "rtn", /* 63 */ + "wfork", /* 64 */ + "join", /* 65 */ + "rtnc", /* 66 */ + "exp", /* 67 */ + "sin", /* 68 */ + "cos", /* 69 */ + "psh", /* 70 */ + "pop", /* 71 */ + "eni", /* 72 */ + "dsi", /* 73 */ + "bkpt", /* 74 */ + "msync", /* 75 */ + "mski", /* 76 */ + "xmti", /* 77 */ + "tstvv", /* 78 */ + "diag", /* 79 */ + "pbkpt", /* 80 */ + "sqrt", /* 81 */ + "casr", /* 82 */ + "atan", /* 83 */ + "sum", /* 84 */ + "all", /* 85 */ + "any", /* 86 */ + "parity", /* 87 */ + "max", /* 88 */ + "min", /* 89 */ + "prod", /* 90 */ + "halt", /* 91 */ + "sysc", /* 92 */ + "trap", /* 93 */ + "tst", /* 94 */ + "lck", /* 95 */ + "ulk", /* 96 */ + "spawn", /* 97 */ + "ldcmr", /* 98 */ + "stcmr", /* 99 */ + "popr", /* 100 */ + "pshr", /* 101 */ + "rcvr", /* 102 */ + "matm", /* 103 */ + "sndr", /* 104 */ + "putr", /* 105 */ + "getr", /* 106 */ + "matr", /* 107 */ + "mat", /* 108 */ + "get", /* 109 */ + "rcv", /* 110 */ + "inc", /* 111 */ + "put", /* 112 */ + "snd", /* 113 */ + "enal", /* 114 */ + "enag", /* 115 */ + "frint", /* 116 */ + "xpnd", /* 117 */ + "ctrsl", /* 118 */ + "ctrsg", /* 119 */ + "stop", /* 120 */ +}; +char *rop[] = { + "", /* 0 */ + ".t", /* 1 */ + ".f", /* 2 */ + ".s", /* 3 */ + ".d", /* 4 */ + ".b", /* 5 */ + ".h", /* 6 */ + ".w", /* 7 */ + ".l", /* 8 */ + ".x", /* 9 */ + ".u", /* 10 */ + ".s.f", /* 11 */ + ".d.f", /* 12 */ + ".b.f", /* 13 */ + ".h.f", /* 14 */ + ".w.f", /* 15 */ + ".l.f", /* 16 */ + ".t.f", /* 17 */ + ".s.t", /* 18 */ + ".d.t", /* 19 */ + ".b.t", /* 20 */ + ".h.t", /* 21 */ + ".w.t", /* 22 */ + ".l.t", /* 23 */ + ".t.t", /* 24 */ +}; diff --git a/gdb/convex-pinsn.c b/gdb/convex-pinsn.c new file mode 100644 index 0000000000..a283d29405 --- /dev/null +++ b/gdb/convex-pinsn.c @@ -0,0 +1,314 @@ +/* Print Convex instructions for GDB, the GNU debugger. + 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 + +#include "defs.h" +#include "param.h" +#include "symtab.h" + +/* reg (fmt_field, inst_field) -- + the {first,second,third} operand of instruction as fmt_field = [ijk] + gets the value of the field from the [ijk] position of the instruction */ + +#define reg(a,b) ((char (*)[3])(op[fmt->a]))[inst.f0.b] + +/* lit (fmt_field) -- field [ijk] is a literal (PSW, VL, eg) */ + +#define lit(i) op[fmt->i] + +/* aj[j] -- name for A register j */ + +#define aj ((char (*)[3])(op[A])) + +union inst { + struct { + unsigned : 7; + unsigned i : 3; + unsigned j : 3; + unsigned k : 3; + unsigned : 16; + unsigned : 32; + } f0; + struct { + unsigned : 8; + unsigned indir : 1; + unsigned len : 1; + unsigned j : 3; + unsigned k : 3; + unsigned : 16; + unsigned : 32; + } f1; + unsigned char byte[8]; + unsigned short half[4]; + char signed_byte[8]; + short signed_half[4]; +}; + +struct opform { + int mask; /* opcode mask */ + int shift; /* opcode align */ + struct formstr *formstr[3]; /* ST, E0, E1 */ +}; + +struct formstr { + unsigned lop:8, rop:5; /* opcode */ + unsigned fmt:5; /* inst format */ + unsigned i:5, j:5, k:2; /* operand formats */ +}; + +#include "convex-opcode.h" + +unsigned char formdecode [] = { + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,5,5,5,5,6,6,7,8, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +struct opform opdecode[] = { + 0x7e00, 9, format0, e0_format0, e1_format0, + 0x3f00, 8, format1, e0_format1, e1_format1, + 0x1fc0, 6, format2, e0_format2, e1_format2, + 0x0fc0, 6, format3, e0_format3, e1_format3, + 0x0700, 8, format4, e0_format4, e1_format4, + 0x03c0, 6, format5, e0_format5, e1_format5, + 0x01f8, 3, format6, e0_format6, e1_format6, + 0x00f8, 3, format7, e0_format7, e1_format7, + 0x0000, 0, formatx, formatx, formatx, + 0x0f80, 7, formatx, formatx, formatx, + 0x0f80, 7, formatx, formatx, formatx, +}; + +/* Print the instruction at address MEMADDR in debugged memory, + on STREAM. Returns length of the instruction, in bytes. */ + +int +print_insn (memaddr, stream) + CORE_ADDR memaddr; + FILE *stream; +{ + union inst inst; + struct formstr *fmt; + register int format, op1, pfx; + int l; + + read_memory (memaddr, &inst, sizeof inst); + + /* Remove and note prefix, if present */ + + pfx = inst.half[0]; + if ((pfx & 0xfff0) == 0x7ef0) + { + pfx = ((pfx >> 3) & 1) + 1; + *(long long *) &inst = *(long long *) &inst.half[1]; + } + else pfx = 0; + + /* Split opcode into format.op1 and look up in appropriate table */ + + format = formdecode[inst.byte[0]]; + op1 = (inst.half[0] & opdecode[format].mask) >> opdecode[format].shift; + if (format == 9) + { + if (pfx) + fmt = formatx; + else if (inst.f1.j == 0) + fmt = &format1a[op1]; + else if (inst.f1.j == 1) + fmt = &format1b[op1]; + else + fmt = formatx; + } + else + fmt = &opdecode[format].formstr[pfx][op1]; + + /* Print it */ + + if (fmt->fmt == xxx) + { + /* noninstruction */ + fprintf (stream, "0x%04x", pfx ? pfx : inst.half[0]); + return 2; + } + + if (pfx) + pfx = 2; + + fprintf (stream, "%s%s%s", lop[fmt->lop], rop[fmt->rop], + &" "[strlen(lop[fmt->lop]) + strlen(rop[fmt->rop])]); + + switch (fmt->fmt) + { + case rrr: /* three register */ + fprintf (stream, "%s,%s,%s", reg(i,i), reg(j,j), reg(k,k)); + return pfx + 2; + + case rr: /* two register */ + fprintf (stream, "%s,%s", reg(i,j), reg(j,k)); + return pfx + 2; + + case rxr: /* two register, reversed i and j fields */ + fprintf (stream, "%s,%s", reg(i,k), reg(j,j)); + return pfx + 2; + + case r: /* one register */ + fprintf (stream, "%s", reg(i,k)); + return pfx + 2; + + case nops: /* no operands */ + return pfx + 2; + + case nr: /* short immediate, one register */ + fprintf (stream, "#%d,%s", inst.f0.j, reg(i,k)); + return pfx + 2; + + case pcrel: /* pc relative */ + print_address (memaddr + 2 * inst.signed_byte[1], stream); + return pfx + 2; + + case lr: /* literal, one register */ + fprintf (stream, "%s,%s", lit(i), reg(j,k)); + return pfx + 2; + + case rxl: /* one register, literal */ + fprintf (stream, "%s,%s", reg(i,k), lit(j)); + return pfx + 2; + + case rlr: /* register, literal, register */ + fprintf (stream, "%s,%s,%s", reg(i,j), lit(j), reg(k,k)); + return pfx + 2; + + case rrl: /* register, register, literal */ + fprintf (stream, "%s,%s,%s", reg(i,j), reg(j,k), lit(k)); + return pfx + 2; + + case iml: /* immediate, literal */ + if (inst.f1.len) + { + fprintf (stream, "#%#x,%s", + (inst.signed_half[1] << 16) + inst.half[2], lit(i)); + return pfx + 6; + } + else + { + fprintf (stream, "#%d,%s", inst.signed_half[1], lit(i)); + return pfx + 4; + } + + case imr: /* immediate, register */ + if (inst.f1.len) + { + fprintf (stream, "#%#x,%s", + (inst.signed_half[1] << 16) + inst.half[2], reg(i,k)); + return pfx + 6; + } + else + { + fprintf (stream, "#%d,%s", inst.signed_half[1], reg(i,k)); + return pfx + 4; + } + + case a1r: /* memory, register */ + l = print_effa (inst, stream); + fprintf (stream, ",%s", reg(i,k)); + return pfx + l; + + case a1l: /* memory, literal */ + l = print_effa (inst, stream); + fprintf (stream, ",%s", lit(i)); + return pfx + l; + + case a2r: /* register, memory */ + fprintf (stream, "%s,", reg(i,k)); + return pfx + print_effa (inst, stream); + + case a2l: /* literal, memory */ + fprintf (stream, "%s,", lit(i)); + return pfx + print_effa (inst, stream); + + case a3: /* memory */ + return pfx + print_effa (inst, stream); + + case a4: /* system call */ + l = 29; goto a4a5; + case a5: /* trap */ + l = 27; + a4a5: + if (inst.f1.len) + { + unsigned int m = (inst.signed_half[1] << 16) + inst.half[2]; + fprintf (stream, "#%d,#%d", m >> l, m & (-1 >> (32-l))); + return pfx + 6; + } + else + { + unsigned int m = inst.signed_half[1]; + fprintf (stream, "#%d,#%d", m >> l, m & (-1 >> (32-l))); + return pfx + 4; + } + } +} + + +/* print effective address @nnn(aj), return instruction length */ + +int print_effa (inst, stream) + union inst inst; + FILE *stream; +{ + int n, l; + + if (inst.f1.len) + { + n = (inst.signed_half[1] << 16) + inst.half[2]; + l = 6; + } + else + { + n = inst.signed_half[1]; + l = 4; + } + + if (inst.f1.indir) + printf ("@"); + + if (!inst.f1.j) + { + print_address (n, stream); + return l; + } + + fprintf (stream, (n & 0xf0000000) == 0x80000000 ? "%#x(%s)" : "%d(%s)", + n, aj[inst.f1.j]); + + return l; +} diff --git a/gdb/copying.awk b/gdb/copying.awk new file mode 100644 index 0000000000..a936318462 --- /dev/null +++ b/gdb/copying.awk @@ -0,0 +1,53 @@ +BEGIN { + FS="\""; + print "/* Do not modify this file; it is created automatically"; + print " by copying.awk. */"; + print "extern int immediate_quit;"; + print "static void"; + print "copying_info ()"; + print "{"; + print " immediate_quit++;"; + } +NR == 1,/^[ ]*NO WARRANTY[ ]*$/ { + if (! ($0 ~ /^[ ]*NO WARRANTY[ ]*$/)) + { + printf " printf_filtered (\""; + for (i = 1; i < NF; i++) + printf "%s\\\"", $i; + printf "%s\\n\");\n", $NF; + } + } +/^[ ]*NO WARRANTY[ ]*$/ { + print " immediate_quit--;"; + print "}"; + print ""; + print "static void"; + print "warranty_info ()"; + print "{"; + print " immediate_quit++;"; + } +/^[ ]*NO WARRANTY[ ]*$/, /^[ ]*END OF TERMS AND CONDITIONS[ ]*$/{ + if (! ($0 ~ /^[ ]*END OF TERMS AND CONDITIONS[ ]*$/)) + { + printf " printf_filtered (\""; + for (i = 1; i < NF; i++) + printf "%s\\\"", $i; + printf "%s\\n\");\n", $NF; + } + } +END { + print " immediate_quit--;"; + print "}"; + print ""; + print "void" + print "_initialize_copying ()"; + print "{"; + print " add_info (\"copying\", copying_info,"; + print " \"Conditions for redistributing copies of GDB.\");"; + print " add_info (\"warranty\", warranty_info,"; + print " \"Various kinds of warranty you do not have.\");"; + print "}"; + } + + + diff --git a/gdb/copying.c b/gdb/copying.c new file mode 100644 index 0000000000..b3d7519807 --- /dev/null +++ b/gdb/copying.c @@ -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."); +} diff --git a/gdb/core.c b/gdb/core.c index 03f4a682d8..d6a9a22dbe 100644 --- a/gdb/core.c +++ b/gdb/core.c @@ -1,26 +1,26 @@ /* Work with core dump and executable files, for GDB. Copyright (C) 1986, 1987, 1989 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! -*/ +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 "gdbcore.h" +#include "frame.h" /* required by inferior.h */ +#include "inferior.h" #ifdef USG #include @@ -32,7 +32,6 @@ anyone else from sharing it farther. Help stamp out software hoarding! #else #include #endif - #ifndef N_MAGIC #ifdef COFF_FORMAT #define N_MAGIC(exec) ((exec).magic) @@ -40,7 +39,6 @@ anyone else from sharing it farther. Help stamp out software hoarding! #define N_MAGIC(exec) ((exec).a_magic) #endif #endif - #include #include #include @@ -48,16 +46,6 @@ anyone else from sharing it farther. Help stamp out software hoarding! #include #include -#ifdef UNISOFT_ASSHOLES -#define PMMU -#define NEW_PMMU -#include /* Required for user.ps */ -#include /* '' */ -#include /* '' */ -#include -#define mc68881 /* Required to get float in user.ps */ -#endif - #ifdef UMAX_CORE #include #else @@ -73,8 +61,10 @@ anyone else from sharing it farther. Help stamp out software hoarding! #endif /* no N_DATADDR */ #ifndef COFF_FORMAT +#ifndef AOUTHDR #define AOUTHDR struct exec #endif +#endif extern char *sys_siglist[]; @@ -238,18 +228,22 @@ files_info () printf ("Executable file \"%s\".\n", execfile); else printf ("No executable file\n"); - - if (corefile) - printf ("Core dump file \"%s\".\n", corefile); - else + 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); + printf ("Symbols from \"%s\".\n", symfile); + +#ifdef FILES_INFO_HOOK + if (FILES_INFO_HOOK ()) + return; +#endif if (! have_inferior_p ()) { @@ -260,11 +254,11 @@ files_info () 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"); + 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", + 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); @@ -282,8 +276,16 @@ read_memory (memaddr, myaddr, len) char *myaddr; int len; { + if (len == 0) + return 0; + if (have_inferior_p ()) - return read_inferior_memory (memaddr, myaddr, len); + { + 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); } @@ -299,11 +301,17 @@ write_memory (memaddr, myaddr, len) int len; { if (have_inferior_p ()) - return write_inferior_memory (memaddr, myaddr, len); + { + 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 /* 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. @@ -384,21 +392,29 @@ xfer_core_file (memaddr, myaddr, len) { i = min (len, data_start - memaddr); } - else if (memaddr >= (corechan >= 0 ? data_end : exec_data_end) - && memaddr < stack_start) + 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; + } else if (memaddr >= stack_end && stack_end != 0) { - i = min (len, - memaddr); + /* 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 could be because data_start != exec_data_start - or data_end similarly. */ - abort(); + This shouldn't happen; we catch the endpoints. */ + fatal ("Internal: Bad case logic in xfer_core_file."); } /* Now we know which file to use. @@ -419,7 +435,7 @@ xfer_core_file (memaddr, myaddr, len) } /* If this address is for nonexistent memory, read zeros if reading, or do nothing if writing. - (FIXME we never write.) */ + Actually, we never right. */ else { bzero (myaddr, i); @@ -432,6 +448,7 @@ xfer_core_file (memaddr, myaddr, len) } return returnval; } +#endif /* XFER_CORE_FILE */ /* My replacement for the read system call. Used like `read' but keeps going if `read' returns too soon. */ diff --git a/gdb/createtags b/gdb/createtags index 491694c3de..aa2797f524 100755 --- a/gdb/createtags +++ b/gdb/createtags @@ -5,14 +5,13 @@ # we setup the TAGS entries to point to the actual source directory. # filelist="" -if test -h main.c ; then +if test "`find main.c -type l -print `" != "" ; then prefix=`ls -l main.c | awk '{print $11}' | sed 's;main.c$;;'` - echo path 1 else prefix="" fi for i in $@ ; do - filelist="$prefix$i $filelist" + filelist="$filelist $prefix$i" done # # Here we simply make sure that the actual machine dependent files being used diff --git a/gdb/dbxread.c b/gdb/dbxread.c index 9908aa177d..cbb4e0c719 100644 --- a/gdb/dbxread.c +++ b/gdb/dbxread.c @@ -1,22 +1,21 @@ /* Read dbx symbol tables and convert to internal format, for GDB. Copyright (C) 1986, 1987, 1988, 1989 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! -*/ +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 "param.h" @@ -36,7 +35,9 @@ anyone else from sharing it farther. Help stamp out software hoarding! #include #include #endif +#include +#ifndef NO_GNU_STABS /* * Define specifically gnu symbols here. */ @@ -107,6 +108,7 @@ anyone else from sharing it farther. Help stamp out software hoarding! #endif #endif /* not __GNU_STAB__ */ +#endif /* NO_GNU_STABS */ #include #include @@ -117,8 +119,10 @@ anyone else from sharing it farther. Help stamp out software hoarding! #include "symtab.h" #ifndef COFF_FORMAT +#ifndef AOUTHDR #define AOUTHDR struct exec #endif +#endif static void add_symbol_to_list (); static void read_dbx_symtab (); @@ -136,6 +140,13 @@ static struct symbol *define_symbol (); static void start_subfile (); static int hashname (); static void hash_symsegs (); +static struct pending *copy_pending (); +static void fix_common_block (); + +static void add_undefined_type (); +static void cleanup_undefined_types (); + +extern char *index(); extern struct symtab *read_symsegs (); extern void free_all_symtabs (); @@ -143,7 +154,7 @@ extern void free_all_psymtabs (); extern void free_inclink_symtabs (); /* C++ */ -static struct type **read_args(); +static struct type **read_args (); /* Macro to determine which symbols to ignore when reading the first symbol of a file. Some machines override this definition. */ @@ -212,16 +223,59 @@ static struct type **read_args(); #endif #endif +/* Non-zero if this is an object (.o) file, rather than an executable. + Distinguishing between the two is rarely necessary (and seems like + a hack, but there is no other way to do ADDR_OF_TEXT_SEGMENT + right for SunOS). */ +#if !defined (IS_OBJECT_FILE) +/* This will not work + if someone decides to make ld preserve relocation info. */ +#define IS_OBJECT_FILE (hdr.a_trsize != 0) +#endif + /* Macro for size of text segment */ #ifndef SIZE_OF_TEXT_SEGMENT #define SIZE_OF_TEXT_SEGMENT hdr.a_text #endif +/* Get the address in debugged memory of the start + of the text segment. */ +#if !defined (ADDR_OF_TEXT_SEGMENT) +#if defined (N_TXTADDR) +#define ADDR_OF_TEXT_SEGMENT (IS_OBJECT_FILE ? 0 : N_TXTADDR (hdr)) +#else /* no N_TXTADDR */ +#define ADDR_OF_TEXT_SEGMENT 0 +#endif /* no N_TXTADDR */ +#endif /* no ADDR_OF_TEXT_SEGMENT */ + +/* Macro to get entry point from headers. */ +#ifndef ENTRY_POINT +#define ENTRY_POINT hdr.a_entry +#endif + /* Macro for name of symbol to indicate a file compiled with gcc. */ #ifndef GCC_COMPILED_FLAG_SYMBOL #define GCC_COMPILED_FLAG_SYMBOL "gcc_compiled." #endif + +/* Convert stab register number (from `r' declaration) to a gdb REGNUM. */ + +#ifndef STAB_REG_TO_REGNUM +#define STAB_REG_TO_REGNUM(VALUE) (VALUE) +#endif + +/* Define this as 1 if a pcc declaration of a char or short argument + gives the correct address. Otherwise assume pcc gives the + address of the corresponding int, which is not the same on a + big-endian machine. */ + +#ifndef BELIEVE_PCC_PROMOTION +#define BELIEVE_PCC_PROMOTION 0 +#endif +/* Nonzero means give verbose info on gdb action. From main.c. */ +extern int info_verbose; + /* Chain of symtabs made from reading the file's symsegs. These symtabs do not go into symtab_list themselves, but the information is copied from them when appropriate @@ -303,6 +357,8 @@ static int line_vector_length; /* Hash table of global symbols whose values are not known yet. They are chained thru the SYMBOL_VALUE, since we don't have the correct data for that slot yet. */ +/* The use of the LOC_BLOCK code in this chain is nonstandard-- + it refers to a FORTRAN common block rather than the usual meaning. */ #define HASHSIZE 127 static struct symbol *global_sym_chain[HASHSIZE]; @@ -331,6 +387,15 @@ struct pending *global_symbols; /* global functions and variables */ struct pending *local_symbols; /* everything local to lexical context */ +/* List of symbols declared since the last BCOMM. This list is a tail + of local_symbols. When ECOMM is seen, the symbols on the list + are noted so their proper addresses can be filled in later, + using the common block base address gotten from the assembler + stabs. */ + +struct pending *common_block; +int common_block_i; + /* Stack representing unclosed lexical contexts (that will become blocks, eventually). */ @@ -368,7 +433,8 @@ struct pending_block struct pending_block *pending_blocks; -extern CORE_ADDR first_object_file_end; /* From blockframe.c */ +extern CORE_ADDR startup_file_start; /* From blockframe.c */ +extern CORE_ADDR startup_file_end; /* From blockframe.c */ /* File name symbols were loaded from. */ @@ -379,27 +445,36 @@ static char *symfile; static int first_global_sym, last_global_sym; -/* Partial symbol list for all of the global and static symbols found - in a file */ - -struct partial_symbol *global_psymbols, *static_psymbols; -int global_psymbols_allocated, static_psymbols_allocated; +/* Structures with which to manage partial symbol allocation. */ -/* Position for next psymbol to be added */ - -struct partial_symbol *next_ps_global, *next_ps_static; +struct psymbol_allocation_list global_psymbols, static_psymbols; /* Global variable which, when set, indicates that we are processing a .o file compiled with gcc */ static unsigned char processing_gcc_compilation; +/* Make a list of forward references which haven't been defined. */ +static struct type **undef_types; +static int undef_types_allocated, undef_types_length; + + /* Setup a define to deal cleanly with the underscore problem */ + +#ifdef NAMES_HAVE_UNDERSCORE +#define HASH_OFFSET 1 +#else +#define HASH_OFFSET 0 +#endif + static int xxmalloc (n) { int v = malloc (n); if (v == 0) - abort (); + { + fprintf (stderr, "Virtual memory exhausted.\n"); + abort (); + } return v; } @@ -482,7 +557,7 @@ static int n_allocated_header_files; track of which psymtabs have which bincls in them. This structure is used during readin to setup the list of dependencies within each partial symbol table. */ - + struct header_file_location { char *name; /* Name of header file */ @@ -494,7 +569,7 @@ struct header_file_location /* The actual list and controling variables */ static struct header_file_location *bincl_list, *next_bincl; static int bincls_allocated; - + /* Within each object file, various header files are assigned numbers. A type is defined or referred to with a pair of numbers (FILENUM,TYPENUM) where FILENUM is the number of the header file @@ -715,28 +790,54 @@ dbx_lookup_type (typenums) } } +/* Create a type object. Occaisionally used when you need a type + which isn't going to be given a type number. */ + +static struct type * +dbx_create_type () +{ + register struct type *type = + (struct type *) obstack_alloc (symbol_obstack, sizeof (struct type)); + + bzero (type, sizeof (struct type)); + TYPE_VPTR_FIELDNO (type) = -1; + return type; +} + /* Make sure there is a type allocated for type numbers TYPENUMS and return the type object. - This can create an empty (zeroed) type object. */ + This can create an empty (zeroed) type object. + TYPENUMS may be (-1, -1) to return a new type object that is not + put into the type vector, and so may not be referred to by number. */ static struct type * dbx_alloc_type (typenums) int typenums[2]; { - register struct type **type_addr = dbx_lookup_type (typenums); - register struct type *type = *type_addr; + register struct type **type_addr; + register struct type *type; + + if (typenums[1] != -1) + { + type_addr = dbx_lookup_type (typenums); + type = *type_addr; + } + else + { + type_addr = 0; + type = 0; + } /* If we are referring to a type not known at all yet, allocate an empty type for it. We will fill it in later if we find out how. */ if (type == 0) { - type = (struct type *) obstack_alloc (symbol_obstack, - sizeof (struct type)); - bzero (type, sizeof (struct type)); - TYPE_VPTR_FIELDNO (type) = -1; - *type_addr = type; + type = dbx_create_type (); + if (type_addr) + *type_addr = type; } + return type; } @@ -1032,10 +1133,12 @@ start_symtab (name, start_addr) current_subfile = 0; start_subfile (name); +#if 0 /* This is now set at the beginning of read_ofile_symtab */ /* Set default for compiler to pcc; assume that we aren't processing a gcc compiled file until proved otherwise. */ processing_gcc_compilation = 0; +#endif } /* Handle an N_SOL symbol, which indicates the start of @@ -1130,6 +1233,11 @@ end_symtab (end_addr) cstk->start_addr, end_addr); } + /* Cleanup any undefined types that have been left hanging around + (this needs to be done before the finish_blocks so that + file_symbols is still good). */ + cleanup_undefined_types (); + /* Finish defining all the blocks of this symtab. */ finish_block (0, &file_symbols, 0, last_source_start_addr, end_addr); finish_block (0, &global_symbols, 0, last_source_start_addr, end_addr); @@ -1258,9 +1366,10 @@ init_misc_functions () } static void -record_misc_function (name, address) +record_misc_function (name, address, type) char *name; CORE_ADDR address; + int type; { register struct misc_bunch *new; @@ -1273,6 +1382,15 @@ record_misc_function (name, address) } misc_bunch->contents[misc_bunch_index].name = name; misc_bunch->contents[misc_bunch_index].address = address; + misc_bunch->contents[misc_bunch_index].type = (unsigned char) + (type == (N_TEXT | N_EXT) ? mf_text : + (type == (N_DATA | N_EXT) +#ifdef N_SETV + || type == (N_SETV | N_EXT) +#endif + ) ? mf_data : + type == (N_BSS | N_EXT) ? mf_bss : + type == (N_ABS | N_EXT) ? mf_abs : mf_unknown); misc_bunch_index++; misc_count++; } @@ -1333,7 +1451,7 @@ condense_misc_bunches (inclink) xxmalloc (misc_count * sizeof (struct misc_function)); j = 0; } - + bunch = misc_bunch; while (bunch) { @@ -1357,7 +1475,7 @@ condense_misc_bunches (inclink) /* Sort the misc functions by address. */ - qsort (misc_function_vector, misc_function_count, + qsort (misc_function_vector, misc_function_count, sizeof (struct misc_function), compare_misc_functions); } @@ -1425,22 +1543,31 @@ sort_symtab_syms (s) sizeof (struct symbol *), compare_symbols); } } - + extern struct symtab *psymtab_to_symtab (); +/* The entry point. */ +static CORE_ADDR entry_point; + /* This is the symbol-file command. Read the file, analyze its symbols, and add a struct symtab to symtab_list. */ void -symbol_file_command (name) +symbol_file_command (name, from_tty) char *name; + int from_tty; { register int desc; DECLARE_FILE_HEADERS; struct nlist *nlist; + + /* The string table. */ char *stringtab; + + /* The size of the string table (buffer is a bizarre name...). */ long buffer; + register int val; extern void close (); struct cleanup *old_chain; @@ -1452,6 +1579,7 @@ symbol_file_command (name) if (name == 0) { if ((symtab_list || partial_symtab_list) + && from_tty && !query ("Discard symbol table? ", 0)) error ("Not confirmed."); if (symfile) @@ -1462,6 +1590,9 @@ symbol_file_command (name) return; } + name = tilde_expand (name); + make_cleanup (free, name); + if ((symtab_list || partial_symtab_list) && !query ("Load new symbol table from \"%s\"? ", name)) error ("Not confirmed."); @@ -1480,6 +1611,8 @@ symbol_file_command (name) READ_FILE_HEADERS (desc, name); + entry_point = ENTRY_POINT; + if (NUMBER_OF_SYMBOLS == 0) { if (symfile) @@ -1500,20 +1633,32 @@ symbol_file_command (name) val = lseek (desc, STRING_TABLE_OFFSET, 0); if (val < 0) perror_with_name (name); - stat (name, &statbuf); + if (stat (name, &statbuf) == -1) + error ("internal: error in stat of already open file."); READ_STRING_TABLE_SIZE (buffer); if (buffer >= 0 && buffer < statbuf.st_size) - stringtab = (char *) alloca (buffer); + { +#ifdef BROKEN_LARGE_ALLOCA + stringtab = (char *) xmalloc (buffer); + make_cleanup (free, stringtab); +#else + stringtab = (char *) alloca (buffer); +#endif + } else stringtab = NULL; if (stringtab == NULL) - error ("ridiculous string table size: %d bytes", name, buffer); + error ("ridiculous string table size: %d bytes", buffer); - bcopy (&buffer, stringtab, sizeof buffer); - val = myread (desc, stringtab + sizeof buffer, buffer - sizeof buffer); + /* Usually READ_STRING_TABLE_SIZE will have shifted the file pointer. + Occaisionally, it won't. */ + val = lseek (desc, STRING_TABLE_OFFSET, L_SET); if (val < 0) perror_with_name (name); - + val = myread (desc, stringtab, buffer); + if (val < 0) + perror_with_name (name); + /* Throw away the old symbol table. */ if (symfile) @@ -1525,41 +1670,9 @@ symbol_file_command (name) /* Empty the hash table of global syms looking for values. */ bzero (global_sym_chain, sizeof global_sym_chain); -#ifdef READ_GDB_SYMSEGS - /* That puts us at the symsegs. Read them. */ - symseg_chain = read_symsegs (desc, name); - hash_symsegs (); - - /* Free the symtabs made by read_symsegs, but not their contents, - which have been copied into symtabs on symtab_list. */ - for (symseg = symseg_chain; symseg; symseg = symseg->next) - { - int i; - struct sourcevector *sv = (struct sourcevector *) symseg->linetable; - - for (i = 0; i < sv->length; i++) - { - int j; - struct source *source = sv->source[i]; - struct symtab *sp1 - = (struct symtab *) xxmalloc (sizeof (struct symtab)); - - bcopy (symseg, sp1, sizeof (struct symtab)); - sp1->filename = savestring (source->name, strlen (source->name)); - sp1->linetable = &source->contents; - sp1->free_code = free_nothing; - sp1->free_ptr = (i == 0) ? (char *) symseg : 0; - - sp1->next = symtab_list; - symtab_list = sp1; - } - } -#else - /* Where people are using the 4.2 ld program, must not check for - symsegs, because that ld puts randonm garbage at the end of - the output file and that would trigger an error message. */ + /* Symsegs are no longer supported by GDB. Setting symseg_chain to + 0 is easier than finding all the symseg code and eliminating it. */ symseg_chain = 0; -#endif /* Position to read the symbol table. Do not read it all at once. */ val = lseek (desc, SYMBOL_TABLE_OFFSET, 0); @@ -1584,7 +1697,8 @@ symbol_file_command (name) /* Now that the symbol table data of the executable file are all in core, process them and define symbols accordingly. Closes desc. */ - read_dbx_symtab (desc, stringtab, NUMBER_OF_SYMBOLS, 0, 0, 0); + read_dbx_symtab (desc, stringtab, buffer, NUMBER_OF_SYMBOLS, 0, + ADDR_OF_TEXT_SEGMENT, SIZE_OF_TEXT_SEGMENT); /* Go over the misc functions and install them in vector. */ @@ -1675,19 +1789,19 @@ next_symbol_text () * Initializes storage for all of the partial symbols that will be * created by read_dbx_symtab and subsidiaries. */ -void +void init_psymbol_list (total_symbols) int total_symbols; { /* Current best guess is that there are approximately a twentieth of the total symbols (in a debugging file) are global or static oriented symbols */ - global_psymbols_allocated = total_symbols / 10; - static_psymbols_allocated = total_symbols / 10; - next_ps_global = global_psymbols = (struct partial_symbol *) - xmalloc (global_psymbols_allocated * sizeof (struct partial_symbol)); - next_ps_static = static_psymbols = (struct partial_symbol *) - xmalloc (static_psymbols_allocated * sizeof (struct partial_symbol)); + global_psymbols.size = total_symbols / 10; + static_psymbols.size = total_symbols / 10; + global_psymbols.next = global_psymbols.list = (struct partial_symbol *) + xmalloc (global_psymbols.size * sizeof (struct partial_symbol)); + static_psymbols.next = static_psymbols.list = (struct partial_symbol *) + xmalloc (static_psymbols.size * sizeof (struct partial_symbol)); } /* @@ -1764,7 +1878,8 @@ static void end_psymtab(); style data, setup partial_symtab's describing each source file for which debugging information is available. NLISTLEN is the number of symbols in the symbol table. All symbol names are given as - offsets relative to STRINGTAB. + offsets relative to STRINGTAB. STRINGTAB_SIZE is the size of + STRINGTAB. I have no idea whether or not this routine should be setup to deal with inclinks. It seems reasonable to me that they be dealt with @@ -1772,26 +1887,37 @@ static void end_psymtab(); them here. */ -static void process_symbol_for_psymtab (); - static void -read_dbx_symtab (desc, stringtab, nlistlen, inclink, text_addr, text_size) +read_dbx_symtab (desc, stringtab, stringtab_size, nlistlen, inclink, + text_addr, text_size) int desc; register char *stringtab; + register long stringtab_size; register int nlistlen; int inclink; unsigned text_addr; int text_size; { + register struct nlist *bufp; register char *namestring; - register struct symbol *sym, *prev; - int hash; - int num_object_files = 0; + register struct partial_symbol *psym; + register struct psymbol_allocation_list *psymbol_struct; + + int nsl; int past_first_source_file = 0; + CORE_ADDR last_o_file_start = 0; struct cleanup *old_chain; - int current_text_start, current_file_symbol_start; - struct pending *global_symbols, *static_symbols; - int nsl; /* Length of namestring, when needed */ + char *p; + enum namespace ns; + enum address_class class; + +#ifdef PROFILE_TYPES + int i; + int profile_types [256]; + int strcmp_called = 0; + int autovars = 0; + int global_funs = 0; +#endif /* Current partial symtab */ struct partial_symtab *pst; @@ -1805,16 +1931,11 @@ read_dbx_symtab (desc, stringtab, nlistlen, inclink, text_addr, text_size) struct partial_symtab **dependency_list; int dependencies_used, dependencies_allocated; - /* Setup a define to deal cleanly with the underscore problem */ - -#ifdef NAMES_HAVE_UNDERSCORE -#define HASH_OFFSET 1 -#else -#define HASH_OFFSET 0 +#ifdef PROFILE_TYPES + for (i = 0; i < 256; i++) + profile_types[i] = 0; #endif - global_symbols = static_symbols = - (struct pending *) 0; pst = (struct partial_symtab *) 0; includes_allocated = 30; @@ -1838,34 +1959,80 @@ read_dbx_symtab (desc, stringtab, nlistlen, inclink, text_addr, text_size) init_psymbol_list (nlistlen); last_source_file = 0; - + #ifdef END_OF_TEXT_DEFAULT end_of_text_addr = END_OF_TEXT_DEFAULT; +#else + end_of_text_addr = text_addr + text_size; #endif - + symtab_input_desc = desc; /* This is needed for fill_symbuf below */ symbuf_end = symbuf_idx = 0; - + for (symnum = 0; symnum < nlistlen; symnum++) { - struct nlist *bufp; - unsigned char type; - /* Get the symbol for this run and pull out some info */ QUIT; /* allow this to be interruptable */ if (symbuf_idx == symbuf_end) fill_symbuf (); bufp = &symbuf[symbuf_idx++]; - type = bufp->n_type; + +#ifdef PROFILE_TYPES + profile_types[bufp->n_type]++; +#endif /* - * Special cases to speed up readin. + * Special case to speed up readin. */ - if (type == N_SLINE) continue; + if (bufp->n_type == N_SLINE) continue; + + /* Ok. There is a lot of code duplicated in the rest of this + switch statiement (for efficiency reasons). Since I don't + like duplicating code, I will do my penance here, and + describe the code which is duplicated: + + *) The assignment to namestring. + *) The call to index. + *) The addition of a partial symbol the the two partial + symbol lists. This last is a large section of code, so + I've imbedded it in the following macro. + */ - namestring = bufp->n_un.n_strx ? bufp->n_un.n_strx + stringtab : ""; - - switch (type) +/* Set namestring based on bufp. */ +#define SET_NAMESTRING()\ + if (bufp->n_un.n_strx < 0 || bufp->n_un.n_strx >= stringtab_size) \ + error ("Invalid symbol data: bad string table offset: %d", \ + bufp->n_un.n_strx); \ + namestring = bufp->n_un.n_strx + stringtab + +#define ADD_PSYMBOL_TO_LIST(NAME, NAMELENGTH, NAMESPACE, CLASS, LIST, VALUE)\ + do { \ + if ((LIST).next >= \ + (LIST).list + (LIST).size) \ + { \ + (LIST).list = (struct partial_symbol *) \ + xrealloc ((LIST).list, \ + ((LIST).size * 2 \ + * sizeof (struct partial_symbol))); \ + /* Next assumes we only went one over. Should be good if \ + program works correctly */ \ + (LIST).next = \ + (LIST).list + (LIST).size; \ + (LIST).size *= 2; \ + } \ + psym = (LIST).next++; \ + \ + SYMBOL_NAME (psym) = (char *) obstack_alloc (psymbol_obstack, \ + (NAMELENGTH) + 1); \ + strncpy (SYMBOL_NAME (psym), (NAME), (NAMELENGTH)); \ + SYMBOL_NAME (psym)[(NAMELENGTH)] = '\0'; \ + SYMBOL_NAMESPACE (psym) = (NAMESPACE); \ + SYMBOL_CLASS (psym) = (CLASS); \ + SYMBOL_VALUE (psym) = (VALUE); \ + } while (0); + + + switch (bufp->n_type) { /* * Standard, non-debugger, symbols @@ -1874,9 +2041,25 @@ read_dbx_symtab (desc, stringtab, nlistlen, inclink, text_addr, text_size) case N_TEXT | N_EXT: /* Catch etext */ - if (!strcmp (namestring, "_etext")) + SET_NAMESTRING(); + + if (namestring[6] == '\0' && namestring[5] == 't' + && namestring[4] == 'x' && namestring[3] == 'e' + && namestring[2] == 't' && namestring[1] == 'e' + && namestring[0] == '_') end_of_text_addr = bufp->n_value; - /* Fall through */ + + /* Figure out beginning and end of global linker symbol + section and put non-debugger specified symbols on + tmp_symchain */ + + last_global_sym = symnum; + if (!first_global_sym) first_global_sym = symnum; + + record_misc_function (namestring, bufp->n_value, + bufp->n_type); /* Always */ + + continue; #ifdef N_NBTEXT case N_NBTEXT | N_EXT: @@ -1886,6 +2069,9 @@ read_dbx_symtab (desc, stringtab, nlistlen, inclink, text_addr, text_size) #endif #ifdef N_NBBSS case N_NBBSS | N_EXT: +#endif +#ifdef N_SETV + case N_SETV | N_EXT: #endif case N_ABS | N_EXT: case N_DATA | N_EXT: @@ -1893,38 +2079,64 @@ read_dbx_symtab (desc, stringtab, nlistlen, inclink, text_addr, text_size) /* Figure out beginning and end of global linker symbol section and put non-debugger specified symbols on tmp_symchain */ - + + SET_NAMESTRING(); + last_global_sym = symnum; if (!first_global_sym) first_global_sym = symnum; - - record_misc_function (namestring, bufp->n_value); /* Always */ + + /* Not really a function here, but... */ + record_misc_function (namestring, bufp->n_value, + bufp->n_type); /* Always */ continue; #ifdef N_NBTEXT case N_NBTEXT: #endif +#ifdef OFILE_FN_FLAGGED +#if ! (N_FN & N_EXT) + case N_FN: +#endif + case N_FN | N_EXT: +#else case N_TEXT: - if (!strcmp (namestring + strlen (namestring) - 2, ".o") - || !strncmp (namestring, "-l", 2)) +#endif + SET_NAMESTRING(); + if ((namestring[0] == '-' && namestring[1] == 'l') + || (namestring [(nsl = strlen (namestring)) - 1] == 'o' + && namestring [nsl - 2] == '.')) { - if (num_object_files++ == 1) - first_object_file_end = bufp->n_value; + if (entry_point < bufp->n_value + && entry_point >= last_o_file_start) + { + startup_file_start = last_o_file_start; + startup_file_end = bufp->n_value; + } if (past_first_source_file && pst) { end_psymtab (pst, psymtab_include_list, includes_used, symnum * sizeof (struct nlist), bufp->n_value, dependency_list, dependencies_used, - next_ps_global, next_ps_static); + global_psymbols.next, static_psymbols.next); pst = (struct partial_symtab *) 0; includes_used = 0; dependencies_used = 0; } else past_first_source_file = 1; + last_o_file_start = bufp->n_value; } continue; - + +#ifdef OFILE_FN_FLAGGED + case N_TEXT: +#else +#if ! (N_FN & N_EXT) + case N_FN: +#endif + case N_FN | N_EXT: +#endif case N_UNDF: case N_UNDF | N_EXT: case N_ABS: @@ -1936,9 +2148,9 @@ read_dbx_symtab (desc, stringtab, nlistlen, inclink, text_addr, text_size) #ifdef N_NBBSS case N_NBBSS: #endif - case N_FN: + /* Keep going . . .*/ - + /* * Special symbol types for GNU */ @@ -1956,10 +2168,9 @@ read_dbx_symtab (desc, stringtab, nlistlen, inclink, text_addr, text_size) case N_SETB: case N_SETB | N_EXT: case N_SETV: - case N_SETV | N_EXT: #endif continue; - + /* * Debugger symbols */ @@ -1967,23 +2178,25 @@ read_dbx_symtab (desc, stringtab, nlistlen, inclink, text_addr, text_size) case N_SO: /* End the current partial symtab and start a new one */ - if (past_first_source_file && pst) + SET_NAMESTRING(); + + if (pst && past_first_source_file) { end_psymtab (pst, psymtab_include_list, includes_used, symnum * sizeof (struct nlist), bufp->n_value, dependency_list, dependencies_used, - next_ps_global, next_ps_static); + global_psymbols.next, static_psymbols.next); pst = (struct partial_symtab *) 0; includes_used = 0; dependencies_used = 0; } else past_first_source_file = 1; - + pst = start_psymtab (namestring, bufp->n_value, symnum * sizeof (struct nlist), - next_ps_global, next_ps_static); - + global_psymbols.next, static_psymbols.next); + continue; #ifdef N_BINCL @@ -1991,14 +2204,54 @@ read_dbx_symtab (desc, stringtab, nlistlen, inclink, text_addr, text_size) /* Add this bincl to the bincl_list for future EXCLs. No need to save the string; it'll be around until read_dbx_symtab function return */ + + SET_NAMESTRING(); + add_bincl_to_list (pst, namestring, bufp->n_value); - /* Fall through */ + /* Mark down an include file in the current psymtab */ + + psymtab_include_list[includes_used++] = namestring; + if (includes_used >= includes_allocated) + { + char **orig = psymtab_include_list; + + psymtab_include_list = (char **) + alloca ((includes_allocated *= 2) * + sizeof (char *)); + bcopy (orig, psymtab_include_list, + includes_used * sizeof (char *)); + } + + continue; #endif case N_SOL: /* Mark down an include file in the current psymtab */ + SET_NAMESTRING(); + + /* In C++, one may expect the same filename to come round many + times, when code is coming alternately from the main file + and from inline functions in other files. So I check to see + if this is a file we've seen before. + + This seems to be a lot of time to be spending on N_SOL, but + things like "break expread.y:435" need to work (I + suppose the psymtab_include_list could be hashed or put + in a binary tree, if profiling shows this is a major hog). */ + { + register int i; + for (i = 0; i < includes_used; i++) + if (!strcmp (namestring, psymtab_include_list[i])) + { + i = -1; + break; + } + if (i == -1) + continue; + } + psymtab_include_list[includes_used++] = namestring; if (includes_used >= includes_allocated) { @@ -2009,44 +2262,131 @@ read_dbx_symtab (desc, stringtab, nlistlen, inclink, text_addr, text_size) sizeof (char *)); bcopy (orig, psymtab_include_list, includes_used * sizeof (char *)); -#ifdef DEBUG_INFO - fprintf (stderr, "Had to realloc includes. New size: %d\n", - includes_allocated); -#endif } continue; - case N_FUN: - case N_SSYM: - case N_GSYM: - case N_LSYM: - case N_STSYM: - case N_LCSYM: - case N_ENTRY: -#ifdef N_MAIN - case N_MAIN: + case N_LSYM: /* Typedef or automatic variable. */ + SET_NAMESTRING(); + + p = (char *) index (namestring, ':'); + + /* Skip if there is no : or if the thing following the : is + not a letter (which indicates declaration of a local + variable, which we aren't interested in). */ + if (!p) continue; + + switch (p[1]) + { + case 'T': + ADD_PSYMBOL_TO_LIST (namestring, p - namestring, + STRUCT_NAMESPACE, LOC_TYPEDEF, + static_psymbols, bufp->n_value); + continue; + case 't': + ADD_PSYMBOL_TO_LIST (namestring, p - namestring, + VAR_NAMESPACE, LOC_TYPEDEF, + static_psymbols, bufp->n_value); + continue; + default: +#ifdef PROFILE_TYPES + if (isalpha(p[1])) + printf ("Funny...LSYM with a letter that isn't a type\n"); + autovars++; #endif -#ifdef N_BSLINE - case N_BSLINE: + continue; + } + + case N_FUN: + SET_NAMESTRING(); + + p = (char *) index (namestring, ':'); + + if (!p || p[1] == 'F') continue; + +#ifdef PROFILE_TYPES + if (p[1] != 'f') + printf ("Funny...FUN with a letter that isn't 'F' or 'f'.\n"); + global_funs++; #endif - case N_PC: + + ADD_PSYMBOL_TO_LIST (namestring, p - namestring, + VAR_NAMESPACE, LOC_BLOCK, + static_psymbols, bufp->n_value); + + continue; + + case N_GSYM: /* Global (extern) variable; can be + data or bss (sigh). */ + case N_STSYM: /* Data seg var -- static */ + case N_LCSYM: /* BSS " */ + + /* Following may probably be ignored; I'll leave them here + for now (until I do Pascal and Modula 2 extensions). */ + + case N_PC: /* I may or may not need this; I + suspect not. */ #ifdef N_M2C - case N_M2C: - case N_SCOPE: + case N_M2C: /* I suspect that I can ignore this here. */ + case N_SCOPE: /* Same. */ #endif - /* Process a symbol as appropriate for the type (this - information is contained in the name of the symbol) */ - if (namestring[0] != '\0') -#if 1 - process_symbol_for_psymtab (namestring); -#else - process_symbol_for_psymtab (namestring, tmp_symchain); -#endif - continue; + SET_NAMESTRING(); + + p = (char *) index (namestring, ':'); + if (!p) + continue; /* Not a debugging symbol. */ + + process_symbol_for_psymtab: + + /* Main processing section for debugging symbols which + the initial read through the symbol tables needs to worry + about. If we reach this point, the symbol which we are + considering is definitely one we are interested in. + p must also contain the (valid) index into the namestring + which indicates the debugging type symbol. */ + + switch (p[1]) + { + case 'c': + ADD_PSYMBOL_TO_LIST (namestring, p - namestring, + VAR_NAMESPACE, LOC_CONST, + static_psymbols, bufp->n_value); + continue; + case 'S': + ADD_PSYMBOL_TO_LIST (namestring, p - namestring, + VAR_NAMESPACE, LOC_STATIC, + static_psymbols, bufp->n_value); + continue; + case 'G': + ADD_PSYMBOL_TO_LIST (namestring, p - namestring, + VAR_NAMESPACE, LOC_EXTERNAL, + global_psymbols, bufp->n_value); + continue; + + case 't': + ADD_PSYMBOL_TO_LIST (namestring, p - namestring, + VAR_NAMESPACE, LOC_TYPEDEF, + global_psymbols, bufp->n_value); + continue; + + /* I don't think the default case should happen. A breakpoint + here to check would probably be good. */ + default: + /* Two things show up here (hopefully); static symbols of + local scope (static used inside braces) or extensions + of structure symbols. We can ignore both. */ + if (p[1] != 'V' && p[1] != '(' + && (p[1] < '0' || p[1] > '9')) + fatal ("Internal error: Unexpected debugging symbol type '%c' at symnum %d.\n", + p[1], symnum); + continue; + } #ifdef N_BINCL case N_EXCL: + + SET_NAMESTRING(); + /* Find the corresponding bincl and mark that psymtab on the psymtab dependency list */ { @@ -2061,7 +2401,7 @@ read_dbx_symtab (desc, stringtab, nlistlen, inclink, text_addr, text_size) { int i; int found = 0; - + for (i = 0; i < dependencies_used; i++) if (dependency_list[i] == needed_pst) { @@ -2071,7 +2411,7 @@ read_dbx_symtab (desc, stringtab, nlistlen, inclink, text_addr, text_size) /* If it's already in the list, skip the rest. */ if (found) continue; - + dependency_list[dependencies_used++] = needed_pst; if (dependencies_used >= dependencies_allocated) { @@ -2095,11 +2435,20 @@ read_dbx_symtab (desc, stringtab, nlistlen, inclink, text_addr, text_size) symnum); } continue; - + case N_EINCL: #endif #ifdef N_DSLINE case N_DSLINE: +#endif +#ifdef N_BSLINE + case N_BSLINE: +#endif + case N_SSYM: /* Claim: Structure or union element. + Hopefully, I can ignore this. */ + case N_ENTRY: /* Alternate entry point; can ignore. */ +#ifdef N_MAIN + case N_MAIN: /* Can definitely ignore this. */ #endif case N_LENG: case N_BCOMM: @@ -2118,171 +2467,99 @@ read_dbx_symtab (desc, stringtab, nlistlen, inclink, text_addr, text_size) default: /* If we haven't found it yet, we've got problems */ - if (IGNORE_SYMBOL (type)) + if (IGNORE_SYMBOL (bufp->n_type)) continue; - fatal ("Bad symbol type 0x%x encountered in gdb scan", type); + fatal ("Bad symbol type 0x%x encountered in gdb scan", bufp->n_type); } } - - if (last_source_file) + + /* If there's stuff to be cleaned up, clean it up. */ + if (entry_point < bufp->n_value + && entry_point >= last_o_file_start) + { + startup_file_start = last_o_file_start; + startup_file_end = bufp->n_value; + } + + if (pst) { end_psymtab (pst, psymtab_include_list, includes_used, symnum * sizeof (struct nlist), end_of_text_addr, dependency_list, dependencies_used, - next_ps_global, next_ps_static); + global_psymbols.next, static_psymbols.next); includes_used = 0; dependencies_used = 0; pst = (struct partial_symtab *) 0; } - + free_bincl_list (); discard_cleanups (old_chain); +#ifdef PROFILE_TYPES + { + int i, j; +#define __define_stab(SYM, NUMBER, NAME) {NUMBER, NAME}, + static struct xyzzy { + unsigned char symnum; + char *name; + } tmp_list[] = { +#include "stab.def" + {0x1, "eREF"}, + {0x2, "ABS"}, + {0x3, "eABS"}, + {0x4, "TEXT"}, + {0x5, "eTEXT"}, + {0x6, "DATA"}, + {0x7, "eDATA"}, + {0x8, "BSS"}, + {0x9, "eBSS"}, + {0x12, "COMM"}, + {0x13, "eCOMM"}, + {0x1f, "FN"}, + {0, "Unknown"}, +}; + for (i = 0; i < 256; i++) + { + for (j = 0; j < (sizeof (tmp_list) / sizeof (struct xyzzy)) - 1; j++) + if (tmp_list[j].symnum == i) + break; + printf ("Symbol \"%s\" (0x%x) occured %d times.\n", + tmp_list[j].name, i, profile_types[i]); + } + printf ("Auto vars (under LSYM): %d\n", autovars); + printf ("Global funs (under FUN): %d\n", global_funs); + } +#endif } /* - * Take a single symbol (name: NAME) and process it (add it to the - * app psymbol list or not). + * Allocate and partially fill a partial symtab. It will be + * completely filled at the end of the symbol list. */ -static void -process_symbol_for_psymtab (name) - char *name; +static struct partial_symtab * +start_psymtab (filename, textlow, ldsymoff, global_syms, static_syms) + char *filename; + int textlow; + int ldsymoff; + struct partial_symbol *global_syms; + struct partial_symbol *static_syms; { - char *p = (char *) index(name, ':') + 1; - int deftype; - struct partial_symbol *sym; - enum { T_IGNORE, T_STATIC, T_GLOBAL } symbol_type; - enum namespace ns = UNDEF_NAMESPACE; - enum address_class class; - int hash; - - if (p == (char *) 0x1) - /* No ":" ; I guess it's not a debuggging symbol */ - return; + struct partial_symtab *result = + (struct partial_symtab *) obstack_alloc (psymbol_obstack, + sizeof (struct partial_symtab)); - if ((*p >= '0' && *p <= '9') || *p == '(') - deftype = 'l'; - else - deftype = *p; - - /* Figure out how to handle this symbol */ - switch (deftype) - { - /* T is a struct/union/enum, t is a typedef */ - case 'T': - symbol_type = T_STATIC; - ns = STRUCT_NAMESPACE; - class = LOC_TYPEDEF; - break; - case 't': - symbol_type = T_STATIC; - ns = VAR_NAMESPACE; - class = LOC_TYPEDEF; - break; - case 'c': - symbol_type = T_STATIC; - ns = VAR_NAMESPACE; - class = LOC_CONST; - break; - case 'S': - symbol_type = T_STATIC; - ns = VAR_NAMESPACE; - class = LOC_STATIC; - break; - case 'f': - symbol_type = T_STATIC; - ns = VAR_NAMESPACE; - class = LOC_BLOCK; - break; - case 'F': - symbol_type = T_GLOBAL; - ns = VAR_NAMESPACE; - class = LOC_BLOCK; - break; - case 'G': - symbol_type = T_GLOBAL; - ns = VAR_NAMESPACE; - class = LOC_STATIC; - break; - default: - return; - } - - /* Create the symbol and store it on the list */ - /* There's a better algorithm possible for the allocation; figure - out how far through the symbol table we are and do a reestimate */ - if (symbol_type == T_STATIC) - { - if (next_ps_static >= static_psymbols + static_psymbols_allocated) - { - static_psymbols = (struct partial_symbol *) - xrealloc (static_psymbols, - (static_psymbols_allocated * 2 - * sizeof (struct partial_symbol))); - /* Next assumes we only went one over. Should be good if - program works correctly */ - next_ps_static = static_psymbols + static_psymbols_allocated; - static_psymbols_allocated *= 2; -#ifdef DEBUGINFO - fprintf(stderr, "debuginfo: Had to realloc statics\n"); -#endif - } - sym = next_ps_static++; - } - else - { - if (next_ps_global >= global_psymbols + global_psymbols_allocated) - { - global_psymbols = (struct partial_symbol *) - xrealloc (global_psymbols, - (global_psymbols_allocated * 2 - * sizeof (struct partial_symbol))); - next_ps_global = global_psymbols + global_psymbols_allocated; - global_psymbols_allocated *= 2; -#ifdef DEBUGINFO - fprintf(stderr, "debuginfo: Had to realloc globals\n"); -#endif - } - sym = next_ps_global++; - } - - SYMBOL_NAME(sym) = (char *) obstack_alloc (psymbol_obstack, - p - name); - strncpy(SYMBOL_NAME(sym), name, p - name - 1); - SYMBOL_NAME(sym)[p - name - 1] = '\0'; - SYMBOL_NAMESPACE(sym) = ns; - SYMBOL_CLASS(sym) = class; -} -#undef HASH_OFFSET - -/* - * Allocate and partially fill a partial symtab. It will be - * completely filled at the end of the symbol list. - */ -static struct partial_symtab * -start_psymtab (filename, textlow, ldsymoff, global_syms, static_syms) - char *filename; - int textlow; - int ldsymoff; - struct partial_symbol *global_syms; - struct partial_symbol *static_syms; -{ - struct partial_symtab *result = - (struct partial_symtab *) obstack_alloc (psymbol_obstack, - sizeof (struct partial_symtab)); - result->filename = (char *) obstack_alloc (psymbol_obstack, strlen (filename) + 1); strcpy (result->filename, filename); - + result->textlow = textlow; result->ldsymoff = ldsymoff; result->readin = 0; - result->globals_offset = global_syms - global_psymbols; - result->statics_offset = static_syms - static_psymbols; + result->globals_offset = global_syms - global_psymbols.list; + result->statics_offset = static_syms - static_psymbols.list; result->n_global_syms = 0; result->n_static_syms = 0; @@ -2302,7 +2579,7 @@ compare_psymbols (s1, s2) strcmp (st1 + 1, st2 + 1)); } - + /* Close off the current usage of a partial_symbol table entry. This involves setting the correct number of includes (with a realloc), setting the high text mark, setting the symbol length in the @@ -2333,9 +2610,9 @@ end_psymtab (pst, include_list, num_includes, capping_symbol_offset, pst->texthigh = capping_text; pst->n_global_syms = - capping_global - (global_psymbols + pst->globals_offset); + capping_global - (global_psymbols.list + pst->globals_offset); pst->n_static_syms = - capping_static - (static_psymbols + pst->statics_offset); + capping_static - (static_psymbols.list + pst->statics_offset); pst->dependencies = (struct partial_symtab **) obstack_alloc (psymbol_obstack, @@ -2377,9 +2654,9 @@ end_psymtab (pst, include_list, num_includes, capping_symbol_offset, subpst->next = partial_symtab_list; partial_symtab_list = subpst; } - + /* Sort the global list; don't sort the static list */ - qsort (global_psymbols + pst->globals_offset, pst->n_global_syms, + qsort (global_psymbols.list + pst->globals_offset, pst->n_global_syms, sizeof (struct partial_symbol), compare_psymbols); /* Put the psymtab on the psymtab list */ @@ -2387,14 +2664,74 @@ end_psymtab (pst, include_list, num_includes, capping_symbol_offset, partial_symtab_list = pst; } + +/* Helper routines for psymtab_to_symtab. */ +static void scan_file_globals (); +static void read_ofile_symtab (); + +static void +psymtab_to_symtab_1 (pst, desc, stringtab, stringtab_size, sym_offset) + struct partial_symtab *pst; + int desc; + char *stringtab; + int stringtab_size; + int sym_offset; +{ + struct cleanup *old_chain; + int i; + + if (!pst) + return; + + if (pst->readin) + { + fprintf (stderr, "Psymtab for %s already read in. Shouldn't happen.\n", + pst->filename); + return; + } + + /* Read in all partial symbtabs on which this one is dependent */ + for (i = 0; i < pst->number_of_dependencies; i++) + if (!pst->dependencies[i]->readin) + { + /* Inform about additional files that need to be read in. */ + if (info_verbose) + { + printf_filtered (" and %s...", pst->dependencies[i]->filename); + fflush (stdout); + } + psymtab_to_symtab_1 (pst->dependencies[i], desc, + stringtab, stringtab_size, sym_offset); + } + + if (pst->ldsymlen) /* Otherwise it's a dummy */ + { + /* Init stuff necessary for reading in symbols */ + free_pendings = 0; + pending_blocks = 0; + file_symbols = 0; + global_symbols = 0; + old_chain = make_cleanup (really_free_pendings, 0); + + /* Read in this files symbols */ + lseek (desc, sym_offset, L_SET); + read_ofile_symtab (desc, stringtab, stringtab_size, + pst->ldsymoff, + pst->ldsymlen, pst->textlow, + pst->texthigh - pst->textlow, 0); + sort_symtab_syms (symtab_list); /* At beginning since just added */ + + do_cleanups (old_chain); + } + + pst->readin = 1; +} + /* * Read in all of the symbols for a given psymtab for real. Return * the value of the symtab you create. Do not free the storage * allocated to the psymtab; it may have pointers to it. */ -static void scan_file_globals (); -static void read_ofile_symtab (); - struct symtab * psymtab_to_symtab(pst) struct partial_symtab *pst; @@ -2423,90 +2760,78 @@ psymtab_to_symtab(pst) pst->filename); return 0; } - + if (!name) error("No symbol file currently specified; use command symbol-file"); - /* Read in all partial symbtabs on which this one is dependent */ - for (i = 0; i < pst->number_of_dependencies; i++) - if (!pst->dependencies[i]->readin) - psymtab_to_symtab (pst->dependencies[i]); - - if (pst->ldsymlen) /* Otherwise it's a dummy */ + if (pst->ldsymlen || pst->number_of_dependencies) { + /* Print the message now, before reading the string table, + to avoid disconcerting pauses. */ + if (info_verbose) + { + printf_filtered ("Reading in symbols for %s...", pst->filename); + fflush (stdout); + } + /* Open symbol file and read in string table */ stat (name, &statbuf); desc = open(name, O_RDONLY, 0); /* symbol_file_command guarrantees that the symbol file name will be absolute, so there is no need for openp */ - + old_chain = make_cleanup (close, desc); - + if (desc < 0) error("Symbol file not readable"); - + READ_FILE_HEADERS (desc, name); - + /* Read in the string table */ lseek (desc, STRING_TABLE_OFFSET, L_SET); READ_STRING_TABLE_SIZE (stsize); if (stsize >= 0 && stsize < statbuf.st_size) - stringtab = (char *) alloca (stsize); + { +#ifdef BROKEN_LARGE_ALLOCA + stringtab = (char *) xmalloc (stsize); + make_cleanup (free, stringtab); +#else + stringtab = (char *) alloca (stsize); +#endif + } else stringtab = NULL; if (stringtab == NULL) - error ("ridiculous string table size: %d bytes", name, stsize); - - bcopy (&stsize, stringtab, sizeof stsize); - val = myread (desc, stringtab + sizeof stsize, stsize - sizeof stsize); + error ("ridiculous string table size: %d bytes", stsize); + + /* Usually READ_STRING_TABLE_SIZE will have shifted the file pointer. + Occaisionally, it won't. */ + val = lseek (desc, STRING_TABLE_OFFSET, L_SET); + if (val < 0) + perror_with_name (name); + val = myread (desc, stringtab, stsize); if (val < 0) perror_with_name (name); - - /* Init stuff necessary for reading in symbols */ - free_pendings = 0; - pending_blocks = 0; - file_symbols = 0; - global_symbols = 0; - make_cleanup (really_free_pendings, 0); - - /* Read in this files symbols */ - lseek (desc, SYMBOL_TABLE_OFFSET, L_SET); - read_ofile_symtab (desc, stringtab, pst->ldsymoff, - pst->ldsymlen, pst->textlow, - pst->texthigh - pst->textlow, 0); - sort_symtab_syms (symtab_list); /* At beginning since just added */ - - /* Match with global symbols */ - lseek (desc, SYMBOL_TABLE_OFFSET, L_SET); - scan_file_globals (desc, stringtab, - first_global_sym * sizeof(struct nlist), - last_global_sym - first_global_sym + 1); - - do_cleanups (old_chain); - } - /* Find pst in list, prune it, and free it's storage */ - for (list_patch = &partial_symtab_list; - *list_patch && *list_patch != pst; - list_patch = &((*list_patch)->next)) - ; + psymtab_to_symtab_1 (pst, desc, stringtab, stsize, + SYMBOL_TABLE_OFFSET); - if (!(*list_patch)) /* pst not in list. Don't worry about it? */ - fatal ("internal: psymtab_to_symtab called with non-listed pst"); + /* Match with global symbols. This only needs to be done once, + after all of the symtabs and dependencies have been read in. */ + scan_file_globals (); - *list_patch = (*list_patch)->next; /* Prune */ + do_cleanups (old_chain); - pst->readin = 1; /* Mark as read in */ + /* Finish up the debug error message. */ + if (info_verbose) + printf_filtered ("done.\n"); + } - /* It's the last one if we actually read something in */ - if (pst->ldsymlen) - return symtab_list; - else - /* Search through list for correct name. */ - for (result = symtab_list; result; result = result->next) - if (!strcmp (result->filename, pst->filename)) - return result; + /* Search through list for correct name. */ + for (result = symtab_list; result; result = result->next) + if (!strcmp (result->filename, pst->filename)) + return result; return 0; } @@ -2514,101 +2839,63 @@ psymtab_to_symtab(pst) /* * Scan through all of the global symbols defined in the object file, * assigning values to the debugging symbols that need to be assigned - * to. - * - * DESC is the file descriptor of the symbol file, with the seek - * pointer pointing at the beginning of the symbol table. - * STRINGTAB is the file's string table, already read in. - * OFFSET is the offset (in bytes) of the beginning of the global - * symbols from the beginning of the symbol table. - * NUMSYMS is the number of symbols that have to be checked. + * to. Get these symbols from the misc function list. */ static void -scan_file_globals (desc, stringtab, offset, numsyms) - int desc; - char *stringtab; - int offset; - int numsyms; +scan_file_globals () { int hash; + int mf; - lseek(desc, offset, L_INCR); - symtab_input_desc = desc; - symbuf_end = symbuf_idx = 0; - - for (symnum = 0; symnum < numsyms; symnum++) + for (mf = 0; mf < misc_function_count; mf++) { - struct nlist *bufp; - unsigned char type; - char *namestring; + char *namestring = misc_function_vector[mf].name; + struct symbol *sym, *prev; QUIT; - if (symbuf_idx == symbuf_end) - fill_symbuf (); - bufp = &symbuf[symbuf_idx++]; - type = bufp->n_type; + prev = (struct symbol *) 0; - if (type & N_EXT && type != N_EXT) - { - struct symbol *sym, *prev; - - namestring = bufp->n_un.n_strx ? - bufp->n_un.n_strx + stringtab : ""; - prev = (struct symbol *) 0; + /* Get the hash index and check all the symbols + under that hash index. */ - /* Get the hash index and check all the symbols - under that hash index. */ - -#ifdef NAMES_HAVE_UNDERSCORE - hash = hashname (namestring + 1); -#else /* ! NAMES_HAVE_UNDERSCORE */ - hash = hashname (namestring); -#endif /* ! NAMES_HAVE_UNDERSCORE */ - for (sym = global_sym_chain[hash]; sym;) + hash = hashname (namestring); + + for (sym = global_sym_chain[hash]; sym;) + { + if (*namestring == SYMBOL_NAME (sym)[0] + && !strcmp(namestring + 1, SYMBOL_NAME (sym) + 1)) { - if ( -#ifdef NAMES_HAVE_UNDERSCORE - *namestring == '_' - && namestring[1] == SYMBOL_NAME (sym)[0] - && !strcmp(namestring + 2, SYMBOL_NAME (sym) + 1) -#else /* ! NAMES_HAVE_UNDERSCORE */ - namestring[0] == SYMBOL_NAME (sym) [0] - && !strcmp(namestring + 1, SYMBOL_NAME(sym) + 1) -#endif /* ! NAMES_HAVE_UNDERSCORE */ - ) - { - /* Splice this symbol out of the hash chain and - assign the value we have to it. */ - if (prev) - SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym); - else - global_sym_chain[hash] - = (struct symbol *) SYMBOL_VALUE (sym); - SYMBOL_VALUE (sym) = bufp->n_value; - if (prev) - sym = (struct symbol *) SYMBOL_VALUE (prev); - else - sym = global_sym_chain[hash]; - break; /* Only one reference per file */ - } + /* Splice this symbol out of the hash chain and + assign the value we have to it. */ + if (prev) + SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym); else - { - prev = sym; - sym = (struct symbol *) SYMBOL_VALUE (sym); - } + global_sym_chain[hash] + = (struct symbol *) SYMBOL_VALUE (sym); + + /* Check to see whether we need to fix up a common block. */ + /* Note: this code might be executed several times for + the same symbol if there are multiple references. */ + if (SYMBOL_CLASS (sym) == LOC_BLOCK) + fix_common_block (sym, misc_function_vector[mf].address); + else + SYMBOL_VALUE (sym) = misc_function_vector[mf].address; + + if (prev) + sym = (struct symbol *) SYMBOL_VALUE (prev); + else + sym = global_sym_chain[hash]; + } + else + { + prev = sym; + sym = (struct symbol *) SYMBOL_VALUE (sym); } } } - /* There shouldn't be anything left on the hash list at this point. - If there is, we have done something wrong. For right now it's - worth checking, until I get the bugs out. */ - /* Sigh. Unfortunately, the above is not true. If an extern - variable is mentioned in an include file (or a program) and the - variable is never either referenced or defined, there will be a - debugger symbol with no "real" symbol. Oh well. */ } - + /* * Read in a defined section of a specific object file's symbols. * @@ -2624,11 +2911,11 @@ scan_file_globals (desc, stringtab, offset, numsyms) * TEXT_SIZE is the size of the text segment read in. * OFFSET is a flag which indicates that the value of all of the * symbols should be offset by TEXT_OFFSET (for the purposes of - * incremental linking). + * incremental linking). */ - + static void -read_ofile_symtab (desc, stringtab, sym_offset, +read_ofile_symtab (desc, stringtab, stringtab_size, sym_offset, sym_size, text_offset, text_size, offset) int desc; register char *stringtab; @@ -2653,9 +2940,39 @@ read_ofile_symtab (desc, stringtab, sym_offset, symtab_input_desc = desc; symbuf_end = symbuf_idx = 0; - lseek(desc, sym_offset, L_INCR); - fill_symbuf(); + /* It is necessary to actually read one symbol *before* the start + of this symtab's symbols, because the GCC_COMPILED_FLAG_SYMBOL + occurs before the N_SO symbol. + + Detecting this in read_dbx_symtab + would slow down initial readin, so we look for it here instead. */ + if (sym_offset >= sizeof (struct nlist)) + { + lseek (desc, sym_offset - sizeof (struct nlist), L_INCR); + fill_symbuf (); + bufp = &symbuf[symbuf_idx++]; + + if (bufp->n_un.n_strx < 0 || bufp->n_un.n_strx >= stringtab_size) + error ("Invalid symbol data: bad string table offset: %d", + bufp->n_un.n_strx); + namestring = bufp->n_un.n_strx + stringtab; + + processing_gcc_compilation = + (bufp->n_type == N_TEXT + && !strcmp (namestring, GCC_COMPILED_FLAG_SYMBOL)); + } + else + { + /* The N_SO starting this symtab is the first symbol, so we + better not check the symbol before it. I'm not this can + happen, but it doesn't hurt to check for it. */ + lseek(desc, sym_offset, L_INCR); + processing_gcc_compilation = 0; + } + + if (symbuf_idx == symbuf_end) + fill_symbuf(); bufp = &symbuf[symbuf_idx]; if ((unsigned char) bufp->n_type != N_SO) fatal("First symbol in segment of executable not a source symbol"); @@ -2674,7 +2991,10 @@ read_ofile_symtab (desc, stringtab, sym_offset, (type == N_TEXT || type == N_DATA || type == N_BSS)) bufp->n_value += text_offset; - namestring = bufp->n_un.n_strx ? bufp->n_un.n_strx + stringtab : ""; + if (bufp->n_un.n_strx < 0 || bufp->n_un.n_strx >= stringtab_size) + error ("Invalid symbol data: bad string table offset: %d", + bufp->n_un.n_strx); + namestring = bufp->n_un.n_strx + stringtab; if (type & N_STAB) process_one_symbol(type, bufp->n_desc, @@ -2683,6 +3003,11 @@ read_ofile_symtab (desc, stringtab, sym_offset, happen in this routine. */ else if (type == N_TEXT && !strcmp (namestring, GCC_COMPILED_FLAG_SYMBOL)) + /* I don't think this code will ever be executed, because + the GCC_COMPILED_FLAG_SYMBOL usually is right before + the N_SO symbol which starts this source file. + However, there is no reason not to accept + the GCC_COMPILED_FLAG_SYMBOL anywhere. */ processing_gcc_compilation = 1; else if (type & N_EXT || type == N_TEXT #ifdef N_NBTEXT @@ -2768,6 +3093,7 @@ process_one_symbol (type, desc, value, name) char *name; { register struct context_stack *new; + char *colon_pos; /* Something is wrong if we see real data before seeing a source file name. */ @@ -2775,7 +3101,7 @@ process_one_symbol (type, desc, value, name) if (last_source_file == 0 && type != N_SO) { /* Currently this ignores N_ENTRY on Gould machines, N_NSYM on machines - where that code is defined, and all symbols on the Convex. */ + where that code is defined. */ if (IGNORE_SYMBOL (type)) return; @@ -2790,7 +3116,17 @@ process_one_symbol (type, desc, value, name) a new function. We must process its "name" normally for dbx, but also record the start of a new lexical context, and possibly also the end of the lexical context for the previous function. */ - + /* This is not always true. This type of symbol may indicate a + text segment variable. */ + + colon_pos = index (name, ':'); + if (!colon_pos++ + || (*colon_pos != 'f' && *colon_pos != 'F')) + { + define_symbol (value, name, desc); + break; + } + within_function = 1; if (context_stack_depth > 0) { @@ -2835,11 +3171,19 @@ process_one_symbol (type, desc, value, name) case N_RBRAC: /* This "symbol" just indicates the end of an inner lexical - context that was started with N_RBRAC. */ + context that was started with N_LBRAC. */ new = &context_stack[--context_stack_depth]; if (desc != new->depth) error ("Invalid symbol data: N_LBRAC/N_RBRAC symbol mismatch, symtab pos %d.", symnum); - local_symbols = new->locals; + + /* Can only use new->locals as local symbols here if we're in + gcc or on a machine that puts them before the lbrack. */ + /* Some native compilers put the variable decls inside of an + LBRAC/RBRAC block. */ +#ifdef VARIABLES_INSIDE_BLOCK + if (processing_gcc_compilation) +#endif + local_symbols = new->locals; /* If this is not the outermost LBRAC...RBRAC pair in the function, its local symbols preceded it, and are the ones @@ -2847,10 +3191,16 @@ process_one_symbol (type, desc, value, name) If this is the outermost LBRAC...RBRAC pair, there is no need to do anything; leave the symbols that preceded it - to be attached to the function's own block. */ + to be attached to the function's own block. However, if + it is so, we need to indicate that we just moved outside + of the function. */ +#ifdef VARIABLES_INSIDE_BLOCK + if (local_symbols && context_stack_depth > processing_gcc_compilation) +#else if (local_symbols && context_stack_depth > 1) +#endif { - /* Muzzle a compiler bug that makes end > start. */ + /* Muzzle a compiler bug that makes end < start. */ if (new->start_addr > value) new->start_addr = value; /* Make a block for the local symbols within. */ @@ -2858,9 +3208,18 @@ process_one_symbol (type, desc, value, name) new->start_addr + last_source_start_addr, value + last_source_start_addr); } + else + { + within_function = 0; + } +#ifdef VARIABLES_INSIDE_BLOCK + /* gcc: normal. pcc: now pop locals of block just finished. */ + if (!processing_gcc_compilation) + local_symbols = new->locals; +#endif break; - case N_FN: + case N_FN | N_EXT: /* This kind of symbol supposedly indicates the start of an object file. In fact this type does not appear. */ break; @@ -2870,6 +3229,14 @@ process_one_symbol (type, desc, value, name) for one source file. Finish the symbol table of the previous source file (if any) and start accumulating a new symbol table. */ +#ifdef PCC_SOL_BROKEN + /* pcc bug, occasionally puts out SO for SOL. */ + if (context_stack_depth > 0) + { + start_subfile (name); + break; + } +#endif if (last_source_file) end_symtab (value); start_symtab (name, value); @@ -2907,7 +3274,36 @@ process_one_symbol (type, desc, value, name) break; case N_BCOMM: + if (common_block) + error ("Invalid symbol data: common within common at symtab pos %d", + symnum); + common_block = local_symbols; + common_block_i = local_symbols ? local_symbols->nsyms : 0; + break; + case N_ECOMM: + /* Symbols declared since the BCOMM are to have the common block + start address added in when we know it. common_block points to + the first symbol after the BCOMM in the local_symbols list; + copy the list and hang it off the symbol for the common block name + for later fixup. */ + { + int i; + struct pending *link = local_symbols; + struct symbol *sym = + (struct symbol *) xmalloc (sizeof (struct symbol)); + bzero (sym, sizeof *sym); + SYMBOL_NAME (sym) = savestring (name, strlen (name)); + SYMBOL_CLASS (sym) = LOC_BLOCK; + SYMBOL_NAMESPACE (sym) = (enum namespace) + copy_pending (local_symbols, common_block_i, common_block); + i = hashname (SYMBOL_NAME (sym)); + SYMBOL_VALUE (sym) = (int) global_sym_chain[i]; + global_sym_chain[i] = sym; + common_block = 0; + break; + } + case N_ECOML: case N_LENG: break; @@ -2924,7 +3320,7 @@ process_one_symbol (type, desc, value, name) static void condense_addl_misc_bunches () -{ +{ register int i, j; register struct misc_bunch *bunch; #ifdef NAMES_HAVE_UNDERSCORE @@ -2964,7 +3360,7 @@ condense_addl_misc_bunches () /* Read in another .o file and create a symtab entry for it.*/ - + static void read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size) int desc; @@ -2977,7 +3373,6 @@ read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size) register char *namestring; register struct symbol *sym, *prev; int hash; - int num_object_files = 0; #ifdef N_BINCL subfile_stack = 0; @@ -2999,13 +3394,13 @@ read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size) fill_symbuf (); bufp = &symbuf[symbuf_idx++]; type = bufp->n_type & N_TYPE; - namestring = bufp->n_un.n_strx ? bufp->n_un.n_strx + stringtab : ""; + namestring = bufp->n_un.n_strx + stringtab; if( (type == N_TEXT) || (type == N_DATA) || (type == N_BSS) ) { /* Relocate this file's symbol table information to the address it has been loaded into. */ - bufp->n_value += text_addr; + bufp->n_value += text_addr; } type = bufp->n_type; @@ -3025,10 +3420,8 @@ read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size) #endif ) && (!strcmp (namestring + strlen (namestring) - 2, ".o")) - || ! strcmp (namestring, "-l", 2)) + || ! strncmp (namestring, "-l", 2)) { - if (num_object_files++ == 1) - first_object_file_end = bufp->n_value; if (last_source_file) end_symtab (bufp->n_value); } @@ -3045,6 +3438,13 @@ read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size) && !strcmp (namestring, "_etext")) end_of_text_addr = bufp->n_value; +#if 0 + /* 25 Sep 89: The following seems to be stolen from + read_ofile_symtab, and is wrong here (i.e. there was no + first pass for add-file symbols). */ + /* This shouldn't be necessary, as we now do all of this work + in scan_global syms and all misc functions should have been + recorded on the first pass. */ /* Global symbol: see if we came across a dbx definition for a corresponding symbol. If so, store the value. Remove syms from the chain when their values are stored, @@ -3079,7 +3479,10 @@ read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size) else global_sym_chain[hash] = (struct symbol *) SYMBOL_VALUE (sym); - SYMBOL_VALUE (sym) = bufp->n_value; + if (SYMBOL_CLASS (sym) == LOC_BLOCK) + fix_common_block (sym, bufp->n_value); + else + SYMBOL_VALUE (sym) = bufp->n_value; if (prev) sym = (struct symbol *) SYMBOL_VALUE (prev); else @@ -3100,7 +3503,9 @@ read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size) if (type <= (N_TYPE | N_EXT) && type != N_EXT && ! used_up) - record_misc_function (namestring, bufp->n_value); + record_misc_function (namestring, bufp->n_value, + bufp->n_type); +#endif /* 0 */ } } @@ -3113,13 +3518,13 @@ read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size) /* C++: This function allows the addition of incrementally linked object files. Since this has a fair amount of code in common with symbol_file_command, - it might be worthwhile to consolidate things, as was done with + it might be worthwhile to consolidate things, as was done with read_dbx_symtab and condense_misc_bunches. */ void add_file_command (arg_string) char* arg_string; -{ +{ register int desc; DECLARE_FILE_HEADERS; struct nlist *nlist; @@ -3132,10 +3537,13 @@ add_file_command (arg_string) struct stat statbuf; char *name; unsigned text_addr; - + if (arg_string == 0) error ("add-file takes a file name and an address"); + arg_string = tilde_expand (arg_string); + make_cleanup (free, arg_string); + for( ; *arg_string == ' '; arg_string++ ); name = arg_string; for( ; *arg_string && *arg_string != ' ' ; arg_string++ ); @@ -3148,29 +3556,28 @@ add_file_command (arg_string) dont_repeat (); - if (!query ("add symbol table from filename \"%s\" at text_addr = 0x%x\n", + if (!query ("add symbol table from filename \"%s\" at text_addr = 0x%x\n", name, text_addr)) error ("Not confirmed."); desc = open (name, O_RDONLY); if (desc < 0) perror_with_name (name); - + old_chain = make_cleanup (close, desc); - make_cleanup (free_current_contents, &name); - + READ_FILE_HEADERS (desc, name); - + if (NUMBER_OF_SYMBOLS == 0) { printf ("%s does not have a symbol-table.\n", name); fflush (stdout); return; } - + printf ("Reading symbol data from %s...", name); fflush (stdout); - + /* Now read the string table, all at once. */ val = lseek (desc, STRING_TABLE_OFFSET, 0); if (val < 0) @@ -3178,58 +3585,37 @@ add_file_command (arg_string) stat (name, &statbuf); READ_STRING_TABLE_SIZE (buffer); if (buffer >= 0 && buffer < statbuf.st_size) - stringtab = (char *) alloca (buffer); + { +#ifdef BROKEN_LARGE_ALLOCA + stringtab = (char *) xmalloc (buffer); + make_cleanup (free, stringtab); +#else + stringtab = (char *) alloca (buffer); +#endif + } else stringtab = NULL; if (stringtab == NULL) - error ("ridiculous string table size: %d bytes", name, buffer); - - bcopy (&buffer, stringtab, sizeof buffer); - val = myread (desc, stringtab + sizeof buffer, buffer - sizeof buffer); + error ("ridiculous string table size: %d bytes", buffer); + + /* Usually READ_STRING_TABLE_SIZE will have shifted the file pointer. + Occaisionally, it won't. */ + val = lseek (desc, STRING_TABLE_OFFSET, 0); + if (val < 0) + perror_with_name (name); + val = myread (desc, stringtab, buffer); if (val < 0) perror_with_name (name); - -#ifdef READ_GDB_SYMSEGS - /* That puts us at the symsegs. Read them. */ - symseg_chain = read_symsegs (desc, name); - hash_symsegs (); - - /* Free the symtabs made by read_symsegs, but not their contents, - which have been copied into symtabs on symtab_list. */ - for (symseg = symseg_chain; symseg; symseg = symseg->next) - { - int i; - struct sourcevector *sv = (struct sourcevector *) symseg->linetable; - for (i = 0; i < sv->length; i++) - { - int j; - struct source *source = sv->source[i]; - struct symtab *sp1 - = (struct symtab *) xxmalloc (sizeof (struct symtab)); - - bcopy (symseg, sp1, sizeof (struct symtab)); - sp1->filename = savestring (source->name, strlen (source->name)); - sp1->linetable = &source->contents; - sp1->free_code = free_nothing; - sp1->free_ptr = (i == 0) ? (char *) symseg : 0; - - sp1->next = symtab_list; - symtab_list = sp1; - } - } -#else - /* Where people are using the 4.2 ld program, must not check for - symsegs, because that ld puts randonm garbage at the end of - the output file and that would trigger an error message. */ + /* Symsegs are no longer supported by GDB. Setting symseg_chain to + 0 is easier than finding all the symseg code and eliminating it. */ symseg_chain = 0; -#endif - + /* Position to read the symbol table. Do not read it all at once. */ val = lseek (desc, SYMBOL_TABLE_OFFSET, 0); if (val < 0) perror_with_name (name); - + init_misc_functions (); make_cleanup (discard_misc_bunches, 0); init_header_files (); @@ -3242,27 +3628,22 @@ add_file_command (arg_string) read_addl_syms (desc, stringtab, NUMBER_OF_SYMBOLS, text_addr, SIZE_OF_TEXT_SEGMENT); - - + + /* Sort symbols alphabetically within each block. */ - + sort_syms (); - + /* Go over the misc functions and install them in vector. */ - + condense_addl_misc_bunches (1); - + /* Don't allow char * to have a typename (else would get caddr_t.) */ - + TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0; - - /* Make a default for file to list. */ - /* Hmmm. I'd say we don't want this in add_file_command, but . . . */ - - select_source_symtab (symtab_list); - + do_cleanups (old_chain); - + /* Free the symtabs made by read_symsegs, but not their contents, which have been copied into symtabs on symtab_list. */ while (symseg_chain) @@ -3271,7 +3652,7 @@ add_file_command (arg_string) free (symseg_chain); symseg_chain = s; } - + printf ("done.\n"); fflush (stdout); } @@ -3292,6 +3673,10 @@ define_symbol (value, string, desc) if (string[0] == 0) return 0; + /* Ignore old-style symbols from cc -go */ + if (p == 0) + return 0; + SYMBOL_NAME (sym) = (char *) obstack_alloc (symbol_obstack, ((p - string) + 1)); /* Open-coded bcopy--saves function call time. */ @@ -3327,14 +3712,14 @@ define_symbol (value, string, desc) value = (char *) obstack_alloc (symbol_obstack, sizeof (double)); bcopy (&d, value, sizeof (double)); SYMBOL_VALUE_BYTES (sym) = value; - SYMBOL_CLASS (sym) = LOC_CONST; + SYMBOL_CLASS (sym) = LOC_CONST_BYTES; } break; case 'i': { SYMBOL_TYPE (sym) = builtin_type_int; SYMBOL_VALUE (sym) = atoi (p); - SYMBOL_CLASS (sym) = LOC_CONST_BYTES; + SYMBOL_CLASS (sym) = LOC_CONST; } break; default: @@ -3358,11 +3743,11 @@ define_symbol (value, string, desc) SYMBOL_TYPE (sym) = lookup_pointer_type (lookup_function_type (read_type (&p))); } - else + else { struct type *type = read_type (&p); - - if ((deftype == 'F' || deftype == 'f') + + if ((deftype == 'F' || deftype == 'f') && TYPE_CODE (type) != TYPE_CODE_FUNC) SYMBOL_TYPE (sym) = lookup_function_type (type); else @@ -3411,9 +3796,8 @@ define_symbol (value, string, desc) SYMBOL_VALUE (sym) = value; SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; add_symbol_to_list (sym, &local_symbols); - /* DESC == 0 implies compiled with GCC. - In this case, if it says `short', believe it. */ - if (desc == 0) + /* If it's compiled, if it says `short', believe it. */ + if (processing_gcc_compilation || BELIEVE_PCC_PROMOTION) break; /* If PCC says a parameter is a short or a char, it is really an int. */ @@ -3427,14 +3811,14 @@ define_symbol (value, string, desc) case 'P': SYMBOL_CLASS (sym) = LOC_REGPARM; - SYMBOL_VALUE (sym) = value; + SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (value); SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; add_symbol_to_list (sym, &local_symbols); break; case 'r': SYMBOL_CLASS (sym) = LOC_REGISTER; - SYMBOL_VALUE (sym) = value; + SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (value); SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; add_symbol_to_list (sym, &local_symbols); break; @@ -3470,7 +3854,7 @@ define_symbol (value, string, desc) TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i - 1) = TYPE_NAME (TYPE_BASECLASS (SYMBOL_TYPE (sym), i)); } - + add_symbol_to_list (sym, &file_symbols); break; @@ -3491,7 +3875,6 @@ define_symbol (value, string, desc) break; case 'V': - case 'v': /* Static symbol of local scope */ SYMBOL_CLASS (sym) = LOC_STATIC; SYMBOL_VALUE (sym) = value; @@ -3499,11 +3882,83 @@ define_symbol (value, string, desc) add_symbol_to_list (sym, &local_symbols); break; + case 'v': + /* Reference parameter */ + SYMBOL_CLASS (sym) = LOC_REF_ARG; + SYMBOL_VALUE (sym) = value; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + add_symbol_to_list (sym, &local_symbols); + break; + default: error ("Invalid symbol data: unknown symbol-type code `%c' at symtab pos %d.", deftype, symnum); } return sym; } + +/* What about types defined as forward references inside of a small lexical + scope? */ +/* Add a type to the list of undefined types to be checked through + once this file has been read in. */ +static void +add_undefined_type (type) + struct type *type; +{ + if (undef_types_length == undef_types_allocated) + { + undef_types_allocated *= 2; + undef_types = (struct type **) + xrealloc (undef_types, + undef_types_allocated * sizeof (struct type *)); + } + undef_types[undef_types_length++] = type; +} + +/* Add here something to go through each undefined type, see if it's + still undefined, and do a full lookup if so. */ +static void +cleanup_undefined_types () +{ + struct type **type, *ntype; + struct symbol *sym; + + for (type = undef_types; type < undef_types + undef_types_length; type++) + { + struct type *ntype = 0; + /* Reasonable test to see if it's been defined since. */ + if (TYPE_NFIELDS (*type) == 0) + { + struct pending *ppt; + int i; + /* Name of the type, without "struct" or "union" */ + char *typename = TYPE_NAME (*type); + + if (!strncmp (typename, "struct ", 7)) + typename += 7; + if (!strncmp (typename, "union ", 6)) + typename += 6; + + for (ppt = file_symbols; ppt; ppt = ppt->next) + for (i = 0; i < ppt->nsyms; i++) + { + struct symbol *sym = ppt->symbol[i]; + + if (SYMBOL_CLASS (sym) == LOC_TYPEDEF + && SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE + && (TYPE_CODE (SYMBOL_TYPE (sym)) == + TYPE_CODE (*type)) + && !strcmp (SYMBOL_NAME (sym), typename)) + bcopy (SYMBOL_TYPE (sym), *type, sizeof (struct type)); + } + } + else + /* It has been defined; don't mark it as a stub. */ + TYPE_FLAGS (*type) &= ~TYPE_FLAG_STUB; + } + undef_types_length = 0; +} + + /* Read a number by which a type is referred to in dbx data, or perhaps read a pair (FILENUM, TYPENUM) in parentheses. @@ -3547,40 +4002,140 @@ read_type (pp) struct type *type1; int typenums[2]; int xtypenums[2]; + char *tmpc; - read_type_number (pp, typenums); - - /* Detect random reference to type not yet defined. - Allocate a type object but leave it zeroed. */ - if (**pp != '=') - return dbx_alloc_type (typenums); + /* Read type number if present. The type number may be omitted. + for instance in a two-dimensional array declared with type + "ar1;1;10;ar1;1;10;4". */ + if ((**pp >= '0' && **pp <= '9') + || **pp == '(') + { + read_type_number (pp, typenums); + + /* Detect random reference to type not yet defined. + Allocate a type object but leave it zeroed. */ + if (**pp != '=') + return dbx_alloc_type (typenums); - *pp += 2; + *pp += 2; + } + else + { + /* 'typenums=' not present, type is anonymous. Read and return + the definition, but don't put it in the type vector. */ + typenums[0] = typenums[1] = -1; + *pp += 1; + } + switch ((*pp)[-1]) { case 'x': - type = dbx_alloc_type (typenums); - /* Set the type code according to the following letter. */ - switch ((*pp)[0]) + { + enum type_code code; + + /* Used to index through file_symbols. */ + struct pending *ppt; + int i; + + /* Name including "struct", etc. */ + char *type_name; + + /* Name without "struct", etc. */ + char *type_name_only; + { - case 's': - TYPE_CODE (type) = TYPE_CODE_STRUCT; - break; - case 'u': - TYPE_CODE (type) = TYPE_CODE_UNION; - break; - case 'e': - TYPE_CODE (type) = TYPE_CODE_ENUM; - break; + char *prefix; + char *from, *to; + + /* Set the type code according to the following letter. */ + switch ((*pp)[0]) + { + case 's': + code = TYPE_CODE_STRUCT; + prefix = "struct "; + break; + case 'u': + code = TYPE_CODE_UNION; + prefix = "union "; + break; + case 'e': + code = TYPE_CODE_ENUM; + prefix = "enum "; + break; + default: + error ("Bad type cross reference at symnum: %d.", symnum); + } + + to = type_name = (char *) + obstack_alloc (symbol_obstack, + (strlen (prefix) + + ((char *) index (*pp, ':') - (*pp)) + 1)); + + /* Copy the prefix. */ + from = prefix; + while (*to++ = *from++) + ; + to--; + + type_name_only = to; + + /* Copy the name. */ + from = *pp + 1; + while ((*to++ = *from++) != ':') + ; + *--to = '\0'; + + /* Set the pointer ahead of the name which we just read. */ + *pp = from; + + /* Note: for C++, the cross reference may be to a base type which + has not yet been seen. In this case, we skip to the comma, + which will mark the end of the base class name. (The ':' + at the end of the base class name will be skipped as well.) + But sometimes (ie. when the cross ref is the last thing on + the line) there will be no ','. */ + from = (char *) index (*pp, ','); + if (from) + *pp = from; } - /* Skip the name the cross-ref points to. */ - /* Note: for C++, the cross reference may be to a base type which - has not yet been seen. In this case, we skip to the comma, - which will mark the end of the base class name. (The ':' - at the end of the base class name will be skipped as well.) */ - *pp = (char *) index (*pp, ','); - /* Just allocate the type and leave it zero if nothing known */ - return dbx_alloc_type (typenums); + + /* Now check to see whether the type has already been declared. */ + /* This is necessary at least in the case where the + program says something like + struct foo bar[5]; + The compiler puts out a cross-reference; we better find + set the length of the structure correctly so we can + set the length of the array. */ + for (ppt = file_symbols; ppt; ppt = ppt->next) + for (i = 0; i < ppt->nsyms; i++) + { + struct symbol *sym = ppt->symbol[i]; + + if (SYMBOL_CLASS (sym) == LOC_TYPEDEF + && SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE + && (TYPE_CODE (SYMBOL_TYPE (sym)) == code) + && !strcmp (SYMBOL_NAME (sym), type_name_only)) + { + obstack_free (symbol_obstack, type_name); + type = SYMBOL_TYPE (sym); + return type; + } + } + + /* Didn't find the type to which this refers, so we must + be dealing with a forward reference. Allocate a type + structure for it, and keep track of it so we can + fill in the rest of the fields when we get the full + type. */ + type = dbx_alloc_type (typenums); + TYPE_CODE (type) = code; + TYPE_NAME (type) = type_name; + + TYPE_FLAGS (type) |= TYPE_FLAG_STUB; + + add_undefined_type (type); + return type; + } case '0': case '1': @@ -3598,15 +4153,17 @@ read_type (pp) type = *dbx_lookup_type (xtypenums); if (type == 0) type = builtin_type_void; - *dbx_lookup_type (typenums) = type; + if (typenums[0] != -1) + *dbx_lookup_type (typenums) = type; break; - + case '*': type1 = read_type (pp); if (TYPE_POINTER_TYPE (type1)) { type = TYPE_POINTER_TYPE (type1); - *dbx_lookup_type (typenums) = type; + if (typenums[0] != -1) + *dbx_lookup_type (typenums) = type; } else { @@ -3631,12 +4188,31 @@ read_type (pp) } break; + case '#': + { + struct type *domain = read_type (pp); + char c; + struct type *return_type; + struct type **args; + + if (*(*pp)++ != ',') + error ("invalid member type data format, at symtab pos %d.", + symnum); + + return_type = read_type (pp); + args = read_args (pp, ';'); + type = dbx_alloc_type (typenums); + smash_to_method_type (type, domain, return_type, args); + } + break; + case '&': type1 = read_type (pp); if (TYPE_REFERENCE_TYPE (type1)) { type = TYPE_REFERENCE_TYPE (type1); - *dbx_lookup_type (typenums) = type; + if (typenums[0] != -1) + *dbx_lookup_type (typenums) = type; } else { @@ -3650,7 +4226,8 @@ read_type (pp) if (TYPE_FUNCTION_TYPE (type1)) { type = TYPE_FUNCTION_TYPE (type1); - *dbx_lookup_type (typenums) = type; + if (typenums[0] != -1) + *dbx_lookup_type (typenums) = type; } else { @@ -3661,7 +4238,8 @@ read_type (pp) case 'r': type = read_range_type (pp, typenums); - *dbx_lookup_type (typenums) = type; + if (typenums[0] != -1) + *dbx_lookup_type (typenums) = type; break; case 'e': @@ -3685,43 +4263,11 @@ read_type (pp) if (*(*pp)++ != 'r') error ("Invalid symbol data: unrecognized type-code `a%c' %s %d.", (*pp)[-1], "at symtab position", symnum); - + type = dbx_alloc_type (typenums); type = read_array_type (pp, type); break; -#if 0 - /* Format of an array type: - "ar;lower;upper;". Put code - in to handle this. */ - - /* dbx expresses array types in terms of a range type for the index, - and that range type is specified right inside the array type spec - making ar1;MIN;MAX;VALTYPE */ - if (!strncmp (*pp, "r1;0;", 5)) - (*pp) += 5; - else if (!strncmp (*pp, "r(0,1);0;", 9)) - (*pp) += 9; - else break; - - TYPE_CODE (type) = TYPE_CODE_ARRAY; - /* In Fortran, an upper bound may be T... meaning a parameter specifies - the length of the data. In this case, just pretend the bound is 1. - This happens only for array parameters, which are really passed - as pointers anyway, and we will translate them into such. */ - if (**pp == 'T') - { - n = 1; - while (**pp != ';') - (*pp)++; - } - else - n = read_number (pp, ';') + 1; - TYPE_TARGET_TYPE (type) = read_type (pp); - TYPE_LENGTH (type) = TYPE_LENGTH (TYPE_TARGET_TYPE (type)) * n; - break; -#endif - default: error ("Invalid symbol data: unrecognized type-code `%c' at symtab pos %d.", (*pp)[-1], symnum); @@ -3788,6 +4334,11 @@ read_struct_type (pp, type) struct type *baseclass = NULL; int read_possible_virtual_info = 0; + if (TYPE_MAIN_VARIANT (type) == 0) + { + TYPE_MAIN_VARIANT (type) = type; + } + TYPE_CODE (type) = TYPE_CODE_STRUCT; /* First comes the total size in bytes. */ @@ -3804,8 +4355,18 @@ read_struct_type (pp, type) int i, n_baseclasses, offset; struct type **baseclass_vec; struct type *baseclass; - int via_public, via_virtual; - + int via_public; + + /* Nonzero if it is a virtual baseclass, i.e., + + struct A{}; + struct B{}; + struct C : public B, public virtual A {}; + + B is a baseclass of C; A is a virtual baseclass for C. This is a C++ + 2.0 language feature. */ + int via_virtual; + *pp += 1; n_baseclasses = read_number (pp, ','); @@ -3848,6 +4409,15 @@ read_struct_type (pp, type) *pp += 1; /* skip trailing ';' */ baseclass_vec[i] = lookup_basetype_type (baseclass, offset, via_virtual, via_public); + /* Since lookup_basetype_type can copy the type, + it might copy a stub type (complete with stub flag). + If so, we need to add it to the list of undefined types + to clean up later. Even if lookup_basetype_type + didn't copy the type, adding it to the undefined list + will not do any harm. */ + if (TYPE_FLAGS(baseclass_vec[i]) & TYPE_FLAG_STUB) + add_undefined_type (baseclass_vec[i]); + /* Make this baseclass visible for structure-printing purposes. */ new = (struct nextfield *) alloca (sizeof (struct nextfield)); new->next = list; @@ -3871,6 +4441,9 @@ read_struct_type (pp, type) The `?' is a placeholder for one of '+' (public visibility), '0' (protected visibility), and '-' (private visibility). */ + /* We better set p right now, in case there are no fields at all... */ + p = *pp; + while (**pp != ';') { int visibility; @@ -3908,7 +4481,7 @@ read_struct_type (pp, type) visibility = 1; *pp += 1; break; - + case '2': visibility = 2; *pp += 1; @@ -3934,20 +4507,54 @@ read_struct_type (pp, type) (*pp)++; /* Skip the comma. */ list->field.bitpos = read_number (pp, ','); list->field.bitsize = read_number (pp, ';'); - /* Detect an unpacked field and mark it as such. - dbx gives a bit size for all fields. - Note that forward refs cannot be packed, - and treat enums as if they had the width of ints. */ - if (TYPE_CODE (list->field.type) != TYPE_CODE_INT - && TYPE_CODE (list->field.type) != TYPE_CODE_ENUM) - list->field.bitsize = 0; - if ((list->field.bitsize == 8 * TYPE_LENGTH (list->field.type) - || (TYPE_CODE (list->field.type) == TYPE_CODE_ENUM - && list->field.bitsize == 8 * TYPE_LENGTH (builtin_type_int))) - && - list->field.bitpos % 8 == 0) - list->field.bitsize = 0; - nfields++; + + /* g++ -g0 can put out bitpos & bitsize zero for a static + field. This does not give us any way of getting its + class, so we can't know its name. But we can just + ignore the field so we don't dump core and other nasty + stuff. */ + if (list->field.bitpos == 0 + && list->field.bitsize == 0) + { + /* Have we given the warning yet? */ + static int warning_given = 0; + + /* Only give the warning once, no matter how many class + variables there are. */ + if (!warning_given) + { + warning_given = 1; + fprintf_filtered (stderr, "\n\ +Warning: DBX-style class variable debugging information encountered.\n\ +You seem to have compiled your program with \ +\"g++ -g0\" instead of \"g++ -g\".\n\ +Therefore GDB will not know about your class variables.\n\ +"); + } + + /* Ignore this field. */ + list = list->next; + } + else + { + /* Detect an unpacked field and mark it as such. + dbx gives a bit size for all fields. + Note that forward refs cannot be packed, + and treat enums as if they had the width of ints. */ + if (TYPE_CODE (list->field.type) != TYPE_CODE_INT + && TYPE_CODE (list->field.type) != TYPE_CODE_ENUM) + list->field.bitsize = 0; + if ((list->field.bitsize == 8 * TYPE_LENGTH (list->field.type) + || (TYPE_CODE (list->field.type) == TYPE_CODE_ENUM + && (list->field.bitsize + == 8 * TYPE_LENGTH (builtin_type_int)) + ) + ) + && + list->field.bitpos % 8 == 0) + list->field.bitsize = 0; + nfields++; + } } /* Now come the method fields, as NAME::methods @@ -4012,7 +4619,12 @@ read_struct_type (pp, type) if (**pp == '\\') *pp = next_symbol_text (); new_sublist->fn_field.type = read_type (pp); - new_sublist->fn_field.args = read_args (pp, ':'); + if (**pp != ':') + error ("invalid symtab info for method at symbol number %d.", + symnum); + *pp += 1; + new_sublist->fn_field.args = + TYPE_ARG_TYPES (new_sublist->fn_field.type); p = *pp; while (*p != ';') p++; new_sublist->fn_field.physname = savestring (*pp, p - *pp); @@ -4020,10 +4632,22 @@ read_struct_type (pp, type) new_sublist->visibility = *(*pp)++ - '0'; if (**pp == '\\') *pp = next_symbol_text (); - if (*(*pp)++ == '*') - new_sublist->fn_field.voffset = read_number (pp, ';') + 1; - else - new_sublist->fn_field.voffset = 0; + switch (*(*pp)++) + { + case '*': + /* virtual member function, followed by index. */ + new_sublist->fn_field.voffset = read_number (pp, ';') + 1; + break; + case '?': + /* static member function. */ + new_sublist->fn_field.voffset = 1; + break; + default: + /* **pp == '.'. */ + /* normal member function. */ + new_sublist->fn_field.voffset = 0; + break; + } new_sublist->next = sublist; sublist = new_sublist; @@ -4165,7 +4789,7 @@ read_struct_type (pp, type) return type; } -/* Read a definition of an enumberation type, +/* Read a definition of an array type, and create and return a suitable type object. Also creates a range type which represents the bounds of that array. */ @@ -4176,18 +4800,41 @@ read_array_type (pp, type) { struct type *index_type, *element_type, *range_type; int lower, upper; - + int adjustable = 0; + /* Format of an array type: "ar;lower;upper;". Put code in - to handle this. */ + to handle this. + + Fortran adjustable arrays use Adigits or Tdigits for lower or upper; + for these, produce a type like float[][]. */ index_type = read_type (pp); if (*(*pp)++ != ';') error ("Invalid symbol data; improper format of array type decl."); + + if (!(**pp >= '0' && **pp <= '9')) + { + *pp += 1; + adjustable = 1; + } lower = read_number (pp, ';'); + + if (!(**pp >= '0' && **pp <= '9')) + { + *pp += 1; + adjustable = 1; + } upper = read_number (pp, ';'); + element_type = read_type (pp); + if (adjustable) + { + lower = 0; + upper = -1; + } + { /* Create range type. */ range_type = (struct type *) obstack_alloc (symbol_obstack, @@ -4246,8 +4893,8 @@ read_enum_type (pp, type) /* Read the value-names and their values. The input syntax is NAME:VALUE,NAME:VALUE, and so on. - A semicolon instead of a NAME means the end. */ - while (**pp && **pp != ';') + A semicolon or comman instead of a NAME means the end. */ + while (**pp && **pp != ';' && **pp != ',') { /* Check for and handle cretinous dbx symbol name continuation! */ if (**pp == '\\') *pp = next_symbol_text (); @@ -4257,7 +4904,7 @@ read_enum_type (pp, type) name = obsavestring (*pp, p - *pp); *pp = p + 1; n = read_number (pp, ','); - + sym = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol)); bzero (sym, sizeof (struct symbol)); SYMBOL_NAME (sym) = name; @@ -4268,7 +4915,8 @@ read_enum_type (pp, type) nsyms++; } - (*pp)++; /* Skip the semicolon. */ + if (**pp == ';') + (*pp)++; /* Skip the semicolon. */ /* Now fill in the fields of the type-structure. */ @@ -4281,8 +4929,11 @@ read_enum_type (pp, type) The symbols can be found in the symlist that we put them on to cause them to be defined. osyms contains the old value of that symlist; everything up to there was defined by us. */ + /* Note that we preserve the order of the enum constants, so + that in something like "enum {FOO, LAST_THING=FOO}" we print + FOO, not LAST_THING. */ - for (syms = *symlist, n = nsyms; syms; syms = syms->next) + for (syms = *symlist, n = 0; syms; syms = syms->next) { int j = 0; if (syms == osyms) @@ -4291,10 +4942,10 @@ read_enum_type (pp, type) { struct symbol *sym = syms->symbol[j]; SYMBOL_TYPE (sym) = type; - TYPE_FIELD_NAME (type, --n) = SYMBOL_NAME (sym); + TYPE_FIELD_NAME (type, n) = SYMBOL_NAME (sym); TYPE_FIELD_VALUE (type, n) = 0; TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (sym); - TYPE_FIELD_BITSIZE (type, n) = 0; + TYPE_FIELD_BITSIZE (type, n++) = 0; } if (syms == osyms) break; @@ -4302,7 +4953,7 @@ read_enum_type (pp, type) return type; } - + #define MAX_OF_TYPE(t) ((1 << (sizeof (t) - 1)) - 1) #define MIN_OF_TYPE(t) (-(1 << (sizeof (t) - 1))) @@ -4374,6 +5025,10 @@ read_range_type (pp, typenums) *dbx_lookup_type (rangenums) == builtin_type_int)) { /* an unsigned type */ +#ifdef LONG_LONG + if (n3 == - sizeof (long long)) + return builtin_type_unsigned_long_long; +#endif if (n3 == (1 << (8 * sizeof (int))) - 1) return builtin_type_unsigned_int; if (n3 == (1 << (8 * sizeof (short))) - 1) @@ -4381,6 +5036,10 @@ read_range_type (pp, typenums) if (n3 == (1 << (8 * sizeof (char))) - 1) return builtin_type_unsigned_char; } +#ifdef LONG_LONG + else if (n3 == 0 && n2 == -sizeof (long long)) + return builtin_type_long_long; +#endif else if (n2 == -n3 -1) { /* a signed type */ @@ -4402,7 +5061,7 @@ read_range_type (pp, typenums) as an idiom, and that all of them are special cases. So . . . */ if (self_subrange) error ("Type defined as subrange of itself."); - + result_type = (struct type *) obstack_alloc (symbol_obstack, sizeof (struct type)); bzero (result_type, sizeof (struct type)); @@ -4434,7 +5093,7 @@ read_range_type (pp, typenums) bzero (TYPE_FIELDS (result_type), 2 * sizeof (struct field)); TYPE_FIELD_BITPOS (result_type, 0) = n2; TYPE_FIELD_BITPOS (result_type, 1) = n3; - + return result_type; } @@ -4501,7 +5160,7 @@ read_args (pp, end) /* Check for and handle cretinous dbx symbol name continuation! */ if (**pp == '\\') *pp = next_symbol_text (); - + types[n++] = read_type (pp); } *pp += 1; /* get past `end' (the ':' character) */ @@ -4524,7 +5183,7 @@ read_args (pp, end) } /* This function is really horrible, but to avoid it, there would need - to be more filling in of forward references. THIS SHOULD BE MOVED OUT + to be more filling in of forward references. THIS SHOULD BE MOVED OUT OF COFFREAD.C AND DBXREAD.C TO SOME PLACE WHERE IT CAN BE SHARED */ int fill_in_vptr_fieldno (type) @@ -4535,7 +5194,45 @@ fill_in_vptr_fieldno (type) fill_in_vptr_fieldno (TYPE_BASECLASS (type, 1)); return TYPE_VPTR_FIELDNO (type); } + +/* Copy a pending list, used to record the contents of a common + block for later fixup. */ +static struct pending * +copy_pending (beg, begi, end) + struct pending *beg, *end; + int begi; +{ + struct pending *new = 0; + struct pending *next; + for (next = beg; next != 0 && (next != end || begi < end->nsyms); + next = next->next, begi = 0) + { + register int j; + for (j = begi; j < next->nsyms; j++) + add_symbol_to_list (next->symbol[j], &new); + } + return new; +} + +/* Add a common block's start address to the offset of each symbol + declared to be in it (by being between a BCOMM/ECOMM pair that uses + the common block name). */ + +static void +fix_common_block (sym, value) + struct symbol *sym; + int value; +{ + struct pending *next = (struct pending *) SYMBOL_NAMESPACE (sym); + for ( ; next; next = next->next) + { + register int j; + for (j = next->nsyms - 1; j >= 0; j--) + SYMBOL_VALUE (next->symbol[j]) += value; + } +} + void _initialize_dbxread () { @@ -4543,6 +5240,11 @@ _initialize_dbxread () header_files = (struct header_file *) 0; this_object_header_files = (int *) 0; + undef_types_allocated = 20; + undef_types_length = 0; + undef_types = (struct type **) xmalloc (undef_types_allocated * + sizeof (struct type *)); + add_com ("symbol-file", class_files, symbol_file_command, "Load symbol table (in dbx format) from executable file FILE."); diff --git a/gdb/default-dep.c b/gdb/default-dep.c index 59bd739ae8..a859418411 100644 --- a/gdb/default-dep.c +++ b/gdb/default-dep.c @@ -1,22 +1,21 @@ /* Low level interface to ptrace, for GDB when running under Unix. - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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" @@ -27,25 +26,12 @@ anyone else from sharing it farther. Help stamp out software hoarding! #include #endif -#ifdef UNISOFT_ASSHOLES -#define PMMU -#define NEW_PMMU -#define mc68881 /* Needed to get float in user.h!!! */ -#include /* For user.h */ -#include -#include -/* Things Unisoft defined differently from every other Unix system */ -#define NBPG PAGESIZE -#define UPAGES USIZE -#define KERNEL_U_ADDR UDOT -#endif - #include #include #include #include #include -#include +/* #include Can we live without this? */ #ifdef COFF_ENCAPSULATE #include "a.out.encap.h" @@ -56,7 +42,7 @@ anyone else from sharing it farther. Help stamp out software hoarding! #define N_SET_MAGIC(exec, val) ((exec).a_magic = (val)) #endif -#include /* After a.out.h */ +#include /* After a.out.h */ #include #include @@ -64,28 +50,12 @@ 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. - - If you are having trouble debugging ptrace calls, turn on DEBUG - and every call to ptrace, in this module or elsewhere, will be - logged to stderr. */ + machine-dependent file. */ int call_ptrace (request, pid, arg3, arg4) int request, pid, arg3, arg4; { -#ifdef DEBUG - int result; - - fprintf(stderr, "ptrace(%x,,%x, %x) = ", request, arg3, arg4); - result=ptrace (request, pid, arg3, arg4); - fprintf(stderr, "%x\n", result); - return result; - -#define ptrace call_ptrace - -#else return ptrace (request, pid, arg3, arg4); -#endif } kill_inferior () @@ -173,13 +143,7 @@ store_inferior_registers (regno) { regaddr = register_addr (regno, offset); errno = 0; -#ifdef UNISOFT_ASSHOLES - /* You can't write the PC with ptrace 6, only with ptrace 11! */ - if (regno == PC_REGNUM) - ptrace(11, inferior_pid, 16, read_register(regno)); - else -#endif - ptrace (6, inferior_pid, regaddr, read_register (regno)); + ptrace (6, inferior_pid, regaddr, read_register (regno)); if (errno != 0) { sprintf (buf, "writing register number %d", regno); @@ -190,12 +154,7 @@ store_inferior_registers (regno) { regaddr = register_addr (regno, offset); errno = 0; -#ifdef UNISOFT_ASSHOLES - if (regno == PC_REGNUM) - ptrace(11, inferior_pid, 16, read_register(regno)); - else -#endif - ptrace (6, inferior_pid, regaddr, read_register (regno)); + ptrace (6, inferior_pid, regaddr, read_register (regno)); if (errno != 0) { sprintf (buf, "writing all regs, number %d", regno); @@ -229,8 +188,16 @@ read_inferior_memory (memaddr, myaddr, len) 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); +#endif else buffer[i] = ptrace (1, inferior_pid, addr, 0); if (errno) @@ -304,11 +271,6 @@ write_inferior_memory (memaddr, myaddr, len) /* Work with core dump and executable files, for GDB. This code would be in core.c if it weren't machine-dependent. */ -/* Recognize COFF format systems because a.out.h defines AOUTHDR. */ -#ifdef AOUTHDR -#define COFF_FORMAT -#endif - #ifndef N_TXTADDR #define N_TXTADDR(hdr) 0 #endif /* no N_TXTADDR */ @@ -325,8 +287,10 @@ write_inferior_memory (memaddr, myaddr, len) #endif #ifndef COFF_FORMAT +#ifndef AOUTHDR #define AOUTHDR struct exec #endif +#endif extern char *sys_siglist[]; @@ -430,6 +394,9 @@ core_file_command (filename, from_tty) 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); @@ -439,12 +406,12 @@ core_file_command (filename, from_tty) { struct user u; - int reg_offset; + 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) + if (val != sizeof u) error ("Not a core file: could only read %d bytes", val); data_start = exec_data_start; @@ -453,8 +420,8 @@ core_file_command (filename, from_tty) data_offset = NBPG * UPAGES; stack_offset = NBPG * (UPAGES + u.u_dsize); - /* Some machines put an absolute address in here; Unisoft - seems to put the offset in the upage of the regs. Sigh. */ + /* 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; @@ -474,12 +441,17 @@ core_file_command (filename, from_tty) char buf[MAX_REGISTER_RAW_SIZE]; val = lseek (corechan, register_addr (regno, reg_offset), 0); - if (val < 0) - perror_with_name (reg_names[regno]); + 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); + } - val = myread (corechan, buf, sizeof buf); - if (val < 0) - perror_with_name (reg_names[regno]); supply_register (regno, buf); } } @@ -526,6 +498,9 @@ exec_file_command (filename, from_tty) if (filename) { + filename = tilde_expand (filename); + make_cleanup (free, filename); + execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, &execfile); if (execchan < 0) diff --git a/gdb/defs.h b/gdb/defs.h index cbc4f5ea74..7f52530431 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -1,22 +1,21 @@ /* Basic definitions for GDB, the GNU debugger. - Copyright (C) 1986 Free Software Foundation, Inc. + Copyright (C) 1986, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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 @@ -26,16 +25,29 @@ anyone else from sharing it farther. Help stamp out software hoarding! extern char *savestring (); extern char *concat (); extern char *xmalloc (), *xrealloc (); -extern char *alloca (); extern int parse_escape (); extern char *reg_names[]; +/* Various possibilities for alloca. */ +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else +#ifdef sparc +#include +#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, @@ -66,6 +78,12 @@ 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). */ @@ -82,7 +100,3 @@ struct command_line *read_command_lines (); char *current_directory; -#ifdef sparc -#include -#endif - diff --git a/gdb/dep.c b/gdb/dep.c deleted file mode 120000 index 26ce8293f8..0000000000 --- a/gdb/dep.c +++ /dev/null @@ -1 +0,0 @@ -sparc-dep.c \ No newline at end of file diff --git a/gdb/environ.c b/gdb/environ.c index 3dab98c68e..27aa3aedb8 100644 --- a/gdb/environ.c +++ b/gdb/environ.c @@ -1,104 +1,19 @@ /* environ.c -- library for manipulating environments for GNU. - Copyright (C) 1986 Free Software Foundation, Inc. + Copyright (C) 1986, 1989 Free Software Foundation, Inc. - NO WARRANTY + 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. - BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY -NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT -WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, -RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS 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. + 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. - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. -STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY -WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE -LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR -OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR -DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR -A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS -PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. - - GENERAL PUBLIC LICENSE TO COPY - - 1. You may copy and distribute verbatim copies of this source file -as you receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy a valid copyright notice "Copyright -(C) 1986 Free Software Foundation, Inc."; and include following the -copyright notice a verbatim copy of the above disclaimer of warranty -and of this License. You may charge a distribution fee for the -physical act of transferring a copy. - - 2. You may modify your copy or copies of this source file 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 or is a derivative of this - program or any part thereof, to be licensed at no charge to all - third parties on terms identical to those contained in this - License Agreement (except that you may choose to grant more extensive - warranty protection to some or all third parties, at your option). - - c) You may charge a distribution 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 unrelated program with this program (or its -derivative) on a volume of a storage or distribution medium does not bring -the other program under the scope of these terms. - - 3. You may copy and distribute this 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 - shipping charge) 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.) - -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. - - 4. You may not copy, sublicense, distribute or transfer this program -except as expressly provided under this License Agreement. Any attempt -otherwise to copy, sublicense, distribute or transfer this program is void and -your rights to use the program under this License agreement shall be -automatically terminated. However, parties who have received computer -software programs from you with this License Agreement will not have -their licenses terminated so long as such parties remain in full compliance. - - 5. If you wish to incorporate parts of this program into other free -programs whose distribution conditions are different, write to the Free -Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet -worked out a simple rule that can be stated here, but we will often permit -this. We 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. - -In other words, feel free to share this program, but don't try to -stop anyone else from sharing it. */ + 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)) diff --git a/gdb/environ.h b/gdb/environ.h index 5ebeaa2665..13f31f470a 100644 --- a/gdb/environ.h +++ b/gdb/environ.h @@ -1,3 +1,19 @@ +/* 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. */ diff --git a/gdb/eval.c b/gdb/eval.c index ae9720bfb9..1806e5218d 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -1,22 +1,21 @@ /* Evaluate expressions for GDB. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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" @@ -106,8 +105,14 @@ enum noside { EVAL_NORMAL, EVAL_SKIP, /* Only effect is to increment pos. */ EVAL_AVOID_SIDE_EFFECTS, /* Don't modify any variables or - call any functions. Correct type - is returned. */ + call any functions. The value + returned will have the correct + type, and will have an + approximately correct lvalue + type (inaccuracy: anything that is + listed as being in a register in + the function in which it was + declared will be lval_register). */ }; value @@ -150,7 +155,8 @@ evaluate_subexp (expect_type, exp, pos, noside) { case OP_SCOPE: tem = strlen (&exp->elts[pc + 2].string); - (*pos) += 3 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); + (*pos) += 3 + ((tem + sizeof (union exp_element)) + / sizeof (union exp_element)); return value_static_field (exp->elts[pc + 1].type, &exp->elts[pc + 2].string, -1); @@ -168,7 +174,28 @@ evaluate_subexp (expect_type, exp, pos, noside) (*pos) += 2; if (noside == EVAL_SKIP) goto nosideret; - return value_of_variable (exp->elts[pc + 1].symbol); + if (noside == EVAL_AVOID_SIDE_EFFECTS) + { + struct symbol * sym = exp->elts[pc + 1].symbol; + enum lval_type lv; + + switch (SYMBOL_CLASS (sym)) + { + case LOC_CONST: + case LOC_LABEL: + case LOC_CONST_BYTES: + lv = not_lval; + case LOC_REGISTER: + case LOC_REGPARM: + lv = lval_register; + default: + lv = lval_memory; + } + + return value_zero (SYMBOL_TYPE (sym), lv); + } + else + return value_of_variable (exp->elts[pc + 1].symbol); case OP_LAST: (*pos) += 2; @@ -184,7 +211,8 @@ evaluate_subexp (expect_type, exp, pos, noside) case OP_STRING: tem = strlen (&exp->elts[pc + 1].string); - (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); + (*pos) += 2 + ((tem + sizeof (union exp_element)) + / sizeof (union exp_element)); if (noside == EVAL_SKIP) goto nosideret; return value_string (&exp->elts[pc + 1].string, tem); @@ -319,11 +347,20 @@ evaluate_subexp (expect_type, exp, pos, noside) if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR) { + int static_memfuncp; + argvec[1] = arg2; argvec[0] = value_struct_elt (arg2, argvec+1, &exp->elts[pc2 + 1].string, + &static_memfuncp, op == STRUCTOP_STRUCT ? "structure" : "structure pointer"); + if (static_memfuncp) + { + argvec[1] = argvec[0]; + nargs--; + argvec++; + } } else if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR) { @@ -354,12 +391,18 @@ evaluate_subexp (expect_type, exp, pos, noside) case STRUCTOP_STRUCT: tem = strlen (&exp->elts[pc + 1].string); - (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); + (*pos) += 2 + ((tem + sizeof (union exp_element)) + / sizeof (union exp_element)); arg1 = evaluate_subexp (0, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string, - "structure"); + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return value_zero (lookup_struct_elt_type (VALUE_TYPE (arg1), + &exp->elts[pc + 1].string), + lval_memory); + else + return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string, 0, + "structure"); case STRUCTOP_PTR: tem = strlen (&exp->elts[pc + 1].string); @@ -367,8 +410,14 @@ evaluate_subexp (expect_type, exp, pos, noside) arg1 = evaluate_subexp (0, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string, - "structure pointer"); + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return value_zero (lookup_struct_elt_type (TYPE_TARGET_TYPE + (VALUE_TYPE (arg1)), + &exp->elts[pc + 1].string), + lval_memory); + else + return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string, 0, + "structure pointer"); case STRUCTOP_MEMBER: arg1 = evaluate_subexp_for_address (exp, pos, noside); @@ -376,9 +425,16 @@ evaluate_subexp (expect_type, exp, pos, noside) if (noside == EVAL_SKIP) goto nosideret; /* Now, convert these values to an address. */ + if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_PTR + || ((TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) + != TYPE_CODE_MEMBER) + && (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) + != TYPE_CODE_METHOD))) + error ("non-pointer-to-member value used in pointer-to-member construct"); arg3 = value_from_long (builtin_type_long, value_as_long (arg1) + value_as_long (arg2)); - VALUE_TYPE (arg3) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))); + VALUE_TYPE (arg3) = + lookup_pointer_type (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)))); return value_ind (arg3); case STRUCTOP_MPTR: @@ -387,9 +443,14 @@ evaluate_subexp (expect_type, exp, pos, noside) if (noside == EVAL_SKIP) goto nosideret; /* Now, convert these values to an address. */ + if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_PTR + || (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) != TYPE_CODE_MEMBER + && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) != TYPE_CODE_METHOD)) + error ("non-pointer-to-member value used in pointer-to-member construct"); arg3 = value_from_long (builtin_type_long, value_as_long (arg1) + value_as_long (arg2)); - VALUE_TYPE (arg3) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))); + VALUE_TYPE (arg3) = + lookup_pointer_type (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)))); return value_ind (arg3); case BINOP_ASSIGN: @@ -453,6 +514,10 @@ evaluate_subexp (expect_type, exp, pos, noside) goto nosideret; if (binop_user_defined_p (op, arg1, arg2)) return value_x_binop (arg1, arg2, op, 0); + else + if (noside == EVAL_AVOID_SIDE_EFFECTS + && op == BINOP_DIV) + return value_zero (VALUE_TYPE (arg1), not_lval); else return value_binop (arg1, arg2, op); @@ -461,10 +526,14 @@ evaluate_subexp (expect_type, exp, pos, noside) arg2 = evaluate_subexp_with_coercion (exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return value_zero (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)), + VALUE_LVAL (arg1)); + if (binop_user_defined_p (op, arg1, arg2)) return value_x_binop (arg1, arg2, op, 0); else - return value_subscript (arg1, arg2, op); + return value_subscript (arg1, arg2); case BINOP_AND: arg1 = evaluate_subexp (0, exp, pos, noside); @@ -613,7 +682,13 @@ evaluate_subexp (expect_type, exp, pos, noside) arg2 = evaluate_subexp (0, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - return value_repeat (arg1, (int) value_as_long (arg2)); + if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_INT) + error ("Non-integral right operand for \"@\" operator."); + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return allocate_repeat_value (VALUE_TYPE (arg1), + (int) value_as_long (arg2)); + else + return value_repeat (arg1, (int) value_as_long (arg2)); case BINOP_COMMA: evaluate_subexp (0, exp, pos, noside); @@ -624,7 +699,7 @@ evaluate_subexp (expect_type, exp, pos, noside) if (noside == EVAL_SKIP) goto nosideret; if (unop_user_defined_p (op, arg1)) - return value_x_unop (arg1, op, 0); + return value_x_unop (arg1, op); else return value_neg (arg1); @@ -633,7 +708,7 @@ evaluate_subexp (expect_type, exp, pos, noside) if (noside == EVAL_SKIP) goto nosideret; if (unop_user_defined_p (op, arg1)) - return value_x_unop (arg1, op, 0); + return value_x_unop (arg1, op); else return value_lognot (arg1); @@ -642,7 +717,7 @@ evaluate_subexp (expect_type, exp, pos, noside) if (noside == EVAL_SKIP) goto nosideret; if (unop_user_defined_p (op, arg1)) - return value_x_unop (arg1, op, 0); + return value_x_unop (arg1, op); else return value_from_long (builtin_type_int, (LONGEST) value_zerop (arg1)); @@ -653,6 +728,21 @@ evaluate_subexp (expect_type, exp, pos, noside) arg1 = evaluate_subexp (expect_type, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; + if (noside == EVAL_AVOID_SIDE_EFFECTS) + { + if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR + || TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF + /* In C you can dereference an array to get the 1st elt. */ + || TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_ARRAY + ) + return value_zero (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)), + lval_memory); + else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT) + /* GDB allows dereferencing an int. */ + return value_zero (BUILTIN_TYPE_LONGEST, lval_memory); + else + error ("Attempt to take contents of a non-pointer value."); + } return value_ind (arg1); case UNOP_ADDR: @@ -707,8 +797,11 @@ evaluate_subexp (expect_type, exp, pos, noside) arg1 = evaluate_subexp (expect_type, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - return value_at (exp->elts[pc + 1].type, - (CORE_ADDR) value_as_long (arg1)); + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return value_zero (exp->elts[pc + 1].type, lval_memory); + else + return value_at (exp->elts[pc + 1].type, + (CORE_ADDR) value_as_long (arg1)); case UNOP_PREINCREMENT: arg1 = evaluate_subexp (expect_type, exp, pos, noside); @@ -716,7 +809,7 @@ evaluate_subexp (expect_type, exp, pos, noside) return arg1; else if (unop_user_defined_p (op, arg1)) { - return value_x_unop (arg1, op, 0); + return value_x_unop (arg1, op); } else { @@ -731,7 +824,7 @@ evaluate_subexp (expect_type, exp, pos, noside) return arg1; else if (unop_user_defined_p (op, arg1)) { - return value_x_unop (arg1, op, 0); + return value_x_unop (arg1, op); } else { @@ -746,7 +839,7 @@ evaluate_subexp (expect_type, exp, pos, noside) return arg1; else if (unop_user_defined_p (op, arg1)) { - return value_x_unop (arg1, op, 0); + return value_x_unop (arg1, op); } else { @@ -762,7 +855,7 @@ evaluate_subexp (expect_type, exp, pos, noside) return arg1; else if (unop_user_defined_p (op, arg1)) { - return value_x_unop (arg1, op, 0); + return value_x_unop (arg1, op); } else { @@ -816,9 +909,35 @@ evaluate_subexp_for_address (exp, pos, noside) case OP_VAR_VALUE: (*pos) += 3; - return locate_var_value (exp->elts[pc + 1].symbol, (CORE_ADDR) 0); + if (noside == EVAL_AVOID_SIDE_EFFECTS) + { + struct type *type = + lookup_pointer_type (SYMBOL_TYPE (exp->elts[pc + 1].symbol)); + enum address_class sym_class = + SYMBOL_CLASS (exp->elts[pc + 1].symbol); + + if (sym_class == LOC_CONST + || sym_class == LOC_CONST_BYTES + || sym_class == LOC_REGISTER + || sym_class == LOC_REGPARM) + error ("Attempt to take address of register or constant."); + + return + value_zero (type, not_lval); + } + else + return locate_var_value (exp->elts[pc + 1].symbol, (CORE_ADDR) 0); default: + if (noside == EVAL_AVOID_SIDE_EFFECTS) + { + value x = evaluate_subexp (0, exp, pos, noside); + if (VALUE_LVAL (x) == lval_memory) + return value_zero (TYPE_POINTER_TYPE (VALUE_TYPE (x)), + not_lval); + else + error ("Attempt to take address of non-lval"); + } return value_addr (evaluate_subexp (0, exp, pos, noside)); } } diff --git a/gdb/expprint.c b/gdb/expprint.c index 966f770dd9..adbcec704b 100644 --- a/gdb/expprint.c +++ b/gdb/expprint.c @@ -1,27 +1,27 @@ /* Print in infix form a struct expression. - Copyright (C) 1986 Free Software Foundation, Inc. + Copyright (C) 1986, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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 "param.h" #include "expression.h" +#include "value.h" #include @@ -138,14 +138,14 @@ print_subexp (exp, pos, stream, prec) (*pos) += 3; value_print (value_from_long (exp->elts[pc + 1].type, exp->elts[pc + 2].longconst), - stream, 0); + 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); + stream, 0, Val_no_prettyprint); return; case OP_VAR_VALUE: @@ -155,7 +155,7 @@ print_subexp (exp, pos, stream, prec) case OP_LAST: (*pos) += 2; - fprintf (stream, "$%d", exp->elts[pc + 1].longconst); + fprintf (stream, "$%d", (int) exp->elts[pc + 1].longconst); return; case OP_REGISTER: @@ -276,6 +276,11 @@ print_subexp (exp, pos, stream, prec) 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) diff --git a/gdb/expread.tab.c b/gdb/expread.tab.c index 99a855eac2..87de8f6fe1 100644 --- a/gdb/expread.tab.c +++ b/gdb/expread.tab.c @@ -1,5 +1,45 @@ -# line 31 "expread.y" +/* A Bison parser, made from expread.y */ + +#define INT 258 +#define CHAR 259 +#define UINT 260 +#define FLOAT 261 +#define NAME 262 +#define TYPENAME 263 +#define BLOCKNAME 264 +#define STRING 265 +#define STRUCT 266 +#define UNION 267 +#define ENUM 268 +#define SIZEOF 269 +#define UNSIGNED 270 +#define COLONCOLON 271 +#define SIGNED 272 +#define LONG 273 +#define SHORT 274 +#define INT_KEYWORD 275 +#define LAST 276 +#define REGNAME 277 +#define VARIABLE 278 +#define ASSIGN_MODIFY 279 +#define THIS 280 +#define ABOVE_COMMA 281 +#define OR 282 +#define AND 283 +#define EQUAL 284 +#define NOTEQUAL 285 +#define LEQ 286 +#define GEQ 287 +#define LSH 288 +#define RSH 289 +#define UNARY 290 +#define INCREMENT 291 +#define DECREMENT 292 +#define ARROW 293 + +#line 29 "expread.y" + #include "defs.h" #include "param.h" #include "symtab.h" @@ -7,6 +47,7 @@ #include "expression.h" #include +#include static struct expression *expout; static int expout_size; @@ -15,6 +56,12 @@ static int expout_ptr; static int yylex (); static void yyerror (); static void write_exp_elt (); +static void write_exp_elt_opcode (); +static void write_exp_elt_sym (); +static void write_exp_elt_longcst (); +static void write_exp_elt_dblcst (); +static void write_exp_elt_type (); +static void write_exp_elt_intern (); static void write_exp_string (); static void start_arglist (); static int end_arglist (); @@ -56,10 +103,24 @@ struct stoken int length; }; -# line 92 "expread.y" -typedef union +/* For parsing of complicated types. + An array should be preceded in the list by the size of the array. */ +enum type_pieces + {tp_end = -1, tp_pointer, tp_reference, tp_array, tp_function}; +static enum type_pieces *type_stack; +static int type_stack_depth, type_stack_size; + +static void push_type (); +static enum type_pieces pop_type (); + +/* Allow debugging of parsing. */ +#define YYDEBUG 1 + +#line 111 "expread.y" +typedef union { - long lval; + LONGEST lval; + unsigned LONGEST ulval; double dval; struct symbol *sym; struct type *tval; @@ -72,47 +133,1427 @@ typedef union struct type **tvec; int *ivec; } YYSTYPE; -# define INT 257 -# define CHAR 258 -# define FLOAT 259 -# define NAME 260 -# define TYPENAME 261 -# define STRING 262 -# define STRUCT 263 -# define UNION 264 -# define ENUM 265 -# define SIZEOF 266 -# define UNSIGNED 267 -# define COLONCOLON 268 -# define LAST 269 -# define REGNAME 270 -# define VARIABLE 271 -# define ASSIGN_MODIFY 272 -# define THIS 273 -# define ABOVE_COMMA 274 -# define OR 275 -# define AND 276 -# define EQUAL 277 -# define NOTEQUAL 278 -# define LEQ 279 -# define GEQ 280 -# define LSH 281 -# define RSH 282 -# define UNARY 283 -# define INCREMENT 284 -# define DECREMENT 285 -# define ARROW 286 -#define yyclearin yychar = -1 -#define yyerrok yyerrflag = 0 -extern int yychar; -extern short yyerrflag; -#ifndef YYMAXDEPTH -#define YYMAXDEPTH 150 + +#ifndef YYLTYPE +typedef + struct yyltype + { + int timestamp; + int first_line; + int first_column; + int last_line; + int last_column; + char *text; + } + yyltype; + +#define YYLTYPE yyltype +#endif + +#include + +#ifndef __STDC__ +#define const +#endif + + + +#define YYFINAL 185 +#define YYFLAG -32768 +#define YYNTBASE 63 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 293 ? yytranslate[x] : 81) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 56, 2, 2, 2, 48, 34, 2, 55, + 59, 46, 44, 26, 45, 53, 47, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 62, 2, 37, + 28, 38, 29, 43, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 54, 2, 58, 33, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 60, 32, 61, 57, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 27, 30, 31, 35, 36, 39, 40, 41, 42, 49, + 50, 51, 52 +}; + +static const short yyrline[] = { 0, + 190, 194, 195, 200, 203, 206, 210, 214, 218, 222, + 226, 230, 234, 238, 244, 248, 254, 258, 262, 266, + 272, 275, 279, 283, 289, 295, 301, 305, 309, 313, + 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, + 357, 361, 365, 369, 373, 377, 381, 385, 391, 401, + 413, 420, 427, 430, 436, 442, 448, 455, 462, 469, + 490, 499, 510, 523, 569, 646, 647, 682, 684, 686, + 689, 691, 696, 702, 704, 708, 710, 714, 718, 719, + 721, 723, 726, 733, 736, 738, 740, 742, 744, 746, + 748, 750, 753, 756, 759, 761, 763, 766, 770, 771, + 776, 781, 789, 794, 801, 802, 803, 806, 807 +}; + +static const char * const yytname[] = { 0, +"error","$illegal.","INT","CHAR","UINT","FLOAT","NAME","TYPENAME","BLOCKNAME","STRING", +"STRUCT","UNION","ENUM","SIZEOF","UNSIGNED","COLONCOLON","SIGNED","LONG","SHORT","INT_KEYWORD", +"LAST","REGNAME","VARIABLE","ASSIGN_MODIFY","THIS","','","ABOVE_COMMA","'='","'?'","OR", +"AND","'|'","'^'","'&'","EQUAL","NOTEQUAL","'<'","'>'","LEQ","GEQ", +"LSH","RSH","'@'","'+'","'-'","'*'","'/'","'%'","UNARY","INCREMENT", +"DECREMENT","ARROW","'.'","'['","'('","'!'","'~'","']'","')'","'{'", +"'}'","':'","start" +}; + +static const short yyr1[] = { 0, + 63, 64, 64, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 66, 65, + 67, 67, 67, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 68, + 68, 69, 69, 69, 69, 70, 70, 71, 71, 71, + 72, 72, 72, 72, 72, 73, 73, 74, 75, 75, + 75, 75, 75, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 77, 77, + 77, 77, 78, 78, 79, 79, 79, 80, 80 +}; + +static const short yyr2[] = { 0, + 1, 1, 3, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 4, 3, 4, 4, 0, 5, + 0, 1, 3, 4, 4, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 5, 3, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, + 3, 3, 3, 2, 1, 1, 2, 1, 2, 1, + 3, 2, 1, 2, 1, 2, 3, 2, 1, 3, + 6, 8, 9, 1, 1, 1, 1, 2, 3, 2, + 3, 2, 2, 2, 2, 1, 2, 1, 1, 1, + 1, 1, 1, 3, 1, 1, 1, 1, 1 +}; + +static const short yydefact[] = { 0, + 49, 51, 50, 52, 108, 84, 109, 58, 0, 0, + 0, 0, 96, 0, 98, 86, 87, 85, 54, 55, + 56, 59, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 0, 53, 0, 65, 105, 107, 106, + 92, 93, 94, 0, 13, 99, 101, 102, 100, 95, + 64, 101, 102, 97, 88, 90, 5, 6, 4, 9, + 10, 0, 79, 0, 66, 7, 8, 0, 66, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 11, 12, 0, 0, 0, 19, 0, 0, + 0, 89, 91, 26, 0, 0, 0, 68, 0, 0, + 67, 70, 73, 75, 0, 0, 3, 48, 47, 0, + 45, 44, 43, 42, 41, 35, 36, 39, 40, 37, + 38, 33, 34, 27, 31, 32, 28, 29, 30, 0, + 14, 0, 16, 0, 21, 62, 63, 57, 0, 25, + 80, 69, 0, 76, 78, 0, 0, 72, 74, 24, + 0, 15, 17, 18, 22, 0, 0, 77, 71, 46, + 0, 20, 0, 23, 81, 0, 82, 103, 0, 0, + 83, 104, 0, 0, 0 +}; + +static const short yydefgoto[] = { 183, + 62, 33, 145, 166, 34, 35, 63, 111, 112, 113, + 114, 64, 36, 50, 179, 147, 37 +}; + +static const short yypact[] = { 157, +-32768,-32768,-32768,-32768,-32768,-32768, -13,-32768, 105, 105, + 105, 215, 82, 105, 178, -10, -4,-32768,-32768,-32768, +-32768,-32768, 157, 157, 157, 157, 157, 157, 157, 157, + 239, 6, 284, 75,-32768, 79,-32768,-32768,-32768,-32768, +-32768,-32768,-32768, 157, 501,-32768, 66, 84,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768, 501, 501, 501, 501, + 501, 67,-32768, -50, 69, 501, 501, -53, 138, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157,-32768,-32768, 111, 197, 157,-32768, 105, 105, + -28,-32768,-32768,-32768, 239, 157, 202, -21, 26, 51, +-32768, 62,-32768,-32768, 157, 63, 284, 284, 284, 249, + 336, 360, 383, 405, 426, 445, 445, 460, 460, 460, + 460, 473, 473, 485, 495, 495, 501, 501, 501, 157, +-32768, 157,-32768, -2, 157, 106,-32768, 32, 109, 501, +-32768,-32768, 77,-32768,-32768, 68, 72,-32768,-32768, 501, + 157, 501, 501,-32768, 284, 70, 94,-32768,-32768, 311, + 157,-32768, 83, 284, 92, 126,-32768, 93, 73, 239, +-32768, 93, 121, 150,-32768 +}; + +static const short yypgoto[] = {-32768, + 1, -12,-32768,-32768,-32768,-32768,-32768, -80,-32768, 41, + 46, -25, -24, 166,-32768, 12,-32768 +}; + + +#define YYLAST 556 + + +static const short yytable[] = { 45, + 32, 105, -60, 65, 105, 68, 69, 115, 106, 55, + 57, 58, 59, 60, 61, 56, 66, 67, 101, 65, + 41, 42, 43, 70, 108, 51, 105, 152, 153, 156, + 148, 70, 109, 110, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 164, 22, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 149, 26, 27, 154, 107, 102, 28, 29, 30, 46, + 99, 31, 70, 150, 100, 171, 108, 144, 180, 47, + 48, 49, 160, 103, 109, 110, 141, 143, 151, 155, + 146, 38, 39, 40, 108, 109, 157, 38, 39, 40, + 184, -61, 109, 110, 167, 104, 169, 162, 172, 163, + 155, 181, 165, 6, 168, 150, 9, 10, 11, 173, + 13, 175, 15, 16, 17, 18, 176, 105, 170, 185, + 178, 69, 158, 116, 182, 69, 140, 159, 174, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 54, 22, 0, 108, 177, 46, 0, 0, 0, 0, + 23, 109, 110, 0, 0, 52, 53, 49, 0, 0, + 0, 24, 25, 38, 39, 40, 26, 27, 38, 39, + 40, 28, 29, 30, 0, 0, 31, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 0, 22, + 0, 0, 142, 0, 0, 0, 6, 151, 23, 9, + 10, 11, 0, 13, 0, 15, 16, 17, 18, 24, + 25, 0, 0, 0, 26, 27, 0, 0, 0, 44, + 29, 30, 71, 0, 31, 0, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, 0, 93, 94, + 95, 96, 97, 98, 0, 0, 0, 71, 0, 0, + 161, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 0, 93, 94, 95, 96, 97, 98, 73, + 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 0, + 93, 94, 95, 96, 97, 98, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 0, 93, 94, 95, 96, 97, + 98, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 0, 93, + 94, 95, 96, 97, 98, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 0, 93, 94, 95, 96, 97, 98, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 0, 93, 94, 95, 96, 97, 98, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 0, 93, 94, 95, 96, 97, + 98, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 0, 93, 94, 95, 96, 97, 98, + 85, 86, 87, 88, 89, 90, 91, 92, 0, 93, + 94, 95, 96, 97, 98, 87, 88, 89, 90, 91, + 92, 0, 93, 94, 95, 96, 97, 98, 88, 89, + 90, 91, 92, 0, 93, 94, 95, 96, 97, 98, + 90, 91, 92, 0, 93, 94, 95, 96, 97, 98, + 93, 94, 95, 96, 97, 98 +}; + +static const short yycheck[] = { 12, + 0, 55, 16, 28, 55, 31, 31, 61, 59, 20, + 23, 24, 25, 26, 27, 20, 29, 30, 44, 44, + 9, 10, 11, 26, 46, 14, 55, 108, 3, 110, + 59, 26, 54, 55, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 58, 25, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 105, 50, 51, 58, 16, 20, 55, 56, 57, 8, + 16, 60, 26, 106, 16, 26, 46, 97, 26, 18, + 19, 20, 115, 20, 54, 55, 95, 96, 46, 59, + 99, 7, 8, 9, 46, 54, 55, 7, 8, 9, + 0, 16, 54, 55, 16, 59, 59, 140, 59, 142, + 59, 59, 145, 8, 58, 148, 11, 12, 13, 46, + 15, 59, 17, 18, 19, 20, 55, 55, 161, 0, + 176, 176, 112, 16, 180, 180, 46, 112, 171, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 15, 25, -1, 46, 59, 8, -1, -1, -1, -1, + 34, 54, 55, -1, -1, 18, 19, 20, -1, -1, + -1, 45, 46, 7, 8, 9, 50, 51, 7, 8, + 9, 55, 56, 57, -1, -1, 60, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, -1, 25, + -1, -1, 46, -1, -1, -1, 8, 46, 34, 11, + 12, 13, -1, 15, -1, 17, 18, 19, 20, 45, + 46, -1, -1, -1, 50, 51, -1, -1, -1, 55, + 56, 57, 24, -1, 60, -1, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, -1, 50, 51, + 52, 53, 54, 55, -1, -1, -1, 24, -1, -1, + 62, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 48, -1, 50, 51, 52, 53, 54, 55, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, -1, + 50, 51, 52, 53, 54, 55, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, -1, 50, 51, 52, 53, 54, + 55, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, -1, 50, + 51, 52, 53, 54, 55, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, -1, 50, 51, 52, 53, 54, 55, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, -1, 50, 51, 52, 53, 54, 55, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, -1, 50, 51, 52, 53, 54, + 55, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, -1, 50, 51, 52, 53, 54, 55, + 41, 42, 43, 44, 45, 46, 47, 48, -1, 50, + 51, 52, 53, 54, 55, 43, 44, 45, 46, 47, + 48, -1, 50, 51, 52, 53, 54, 55, 44, 45, + 46, 47, 48, -1, 50, 51, 52, 53, 54, 55, + 46, 47, 48, -1, 50, 51, 52, 53, 54, 55, + 50, 51, 52, 53, 54, 55 +}; +#define YYPURE 1 + +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "bison.simple" + +/* Skeleton output parser for bison, + Copyright (C) 1984 Bob Corbett and Richard Stallman + + 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. */ + + +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) +#include +#endif + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYFAIL goto yyerrlab; +#define YYACCEPT return(0) +#define YYABORT return(1) +#define YYERROR goto yyerrlab + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYIMPURE +#define YYLEX yylex() +#endif + +#ifndef YYPURE +#define YYLEX yylex(&yylval, &yylloc) +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYIMPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ + +int yynerrs; /* number of parse errors so far */ +#endif /* YYIMPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYMAXDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 200 +#endif + +/* YYMAXLIMIT is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#ifndef YYMAXLIMIT +#define YYMAXLIMIT 10000 +#endif + + +#line 90 "bison.simple" +int +yyparse() +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + YYLTYPE *yylsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYMAXDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYMAXDEPTH]; /* the semantic value stack */ + YYLTYPE yylsa[YYMAXDEPTH]; /* the location stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + YYLTYPE *yyls = yylsa; + + int yymaxdepth = YYMAXDEPTH; + +#ifndef YYPURE + int yychar; + YYSTYPE yylval; + YYLTYPE yylloc; + int yynerrs; +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + void yyerror(); + void bcopy(); + int yylex(); + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. */ + + yyssp = yyss - 1; + yyvsp = yyvs; + yylsp = yyls; + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yymaxdepth - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; +#if defined(yyoverflow) || defined(YYLSP_NEEDED) + YYLTYPE *yyls1 = yyls; +#endif + short *yyss1 = yyss; + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yymaxdepth); + + yyss = yyss1; yyvs = yyvs1; yyls = yyls1; +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yymaxdepth >= YYMAXLIMIT) + yyerror("parser stack overflow"); + yymaxdepth *= 2; + if (yymaxdepth > YYMAXLIMIT) + yymaxdepth = YYMAXLIMIT; + yyss = (short *) alloca (yymaxdepth * sizeof (*yyssp)); + bcopy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp)); + yyvs = (YYSTYPE *) alloca (yymaxdepth * sizeof (*yyvsp)); + bcopy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) alloca (yymaxdepth * sizeof (*yylsp)); + bcopy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yymaxdepth); +#endif + + if (yyssp >= yyss + yymaxdepth - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Next token is %d (%s)\n", yychar, yytname[yychar1]); +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + if (yylen == 1) + fprintf (stderr, "Reducing 1 value via line %d, ", + yyrline[yyn]); + else + fprintf (stderr, "Reducing %d values via line %d, ", + yylen, yyrline[yyn]); + } +#endif + + + switch (yyn) { + +case 3: +#line 196 "expread.y" +{ write_exp_elt_opcode (BINOP_COMMA); ; + break;} +case 4: +#line 201 "expread.y" +{ write_exp_elt_opcode (UNOP_IND); ; + break;} +case 5: +#line 204 "expread.y" +{ write_exp_elt_opcode (UNOP_ADDR); ; + break;} +case 6: +#line 207 "expread.y" +{ write_exp_elt_opcode (UNOP_NEG); ; + break;} +case 7: +#line 211 "expread.y" +{ write_exp_elt_opcode (UNOP_ZEROP); ; + break;} +case 8: +#line 215 "expread.y" +{ write_exp_elt_opcode (UNOP_LOGNOT); ; + break;} +case 9: +#line 219 "expread.y" +{ write_exp_elt_opcode (UNOP_PREINCREMENT); ; + break;} +case 10: +#line 223 "expread.y" +{ write_exp_elt_opcode (UNOP_PREDECREMENT); ; + break;} +case 11: +#line 227 "expread.y" +{ write_exp_elt_opcode (UNOP_POSTINCREMENT); ; + break;} +case 12: +#line 231 "expread.y" +{ write_exp_elt_opcode (UNOP_POSTDECREMENT); ; + break;} +case 13: +#line 235 "expread.y" +{ write_exp_elt_opcode (UNOP_SIZEOF); ; + break;} +case 14: +#line 239 "expread.y" +{ write_exp_elt_opcode (STRUCTOP_PTR); + write_exp_string (yyvsp[0].sval); + write_exp_elt_opcode (STRUCTOP_PTR); ; + break;} +case 15: +#line 245 "expread.y" +{ write_exp_elt_opcode (STRUCTOP_MPTR); ; + break;} +case 16: +#line 249 "expread.y" +{ write_exp_elt_opcode (STRUCTOP_STRUCT); + write_exp_string (yyvsp[0].sval); + write_exp_elt_opcode (STRUCTOP_STRUCT); ; + break;} +case 17: +#line 255 "expread.y" +{ write_exp_elt_opcode (STRUCTOP_MEMBER); ; + break;} +case 18: +#line 259 "expread.y" +{ write_exp_elt_opcode (BINOP_SUBSCRIPT); ; + break;} +case 19: +#line 265 "expread.y" +{ start_arglist (); ; + break;} +case 20: +#line 267 "expread.y" +{ write_exp_elt_opcode (OP_FUNCALL); + write_exp_elt_longcst ((LONGEST) end_arglist ()); + write_exp_elt_opcode (OP_FUNCALL); ; + break;} +case 22: +#line 276 "expread.y" +{ arglist_len = 1; ; + break;} +case 23: +#line 280 "expread.y" +{ arglist_len++; ; + break;} +case 24: +#line 284 "expread.y" +{ write_exp_elt_opcode (UNOP_MEMVAL); + write_exp_elt_type (yyvsp[-2].tval); + write_exp_elt_opcode (UNOP_MEMVAL); ; + break;} +case 25: +#line 290 "expread.y" +{ write_exp_elt_opcode (UNOP_CAST); + write_exp_elt_type (yyvsp[-2].tval); + write_exp_elt_opcode (UNOP_CAST); ; + break;} +case 26: +#line 296 "expread.y" +{ ; + break;} +case 27: +#line 302 "expread.y" +{ write_exp_elt_opcode (BINOP_REPEAT); ; + break;} +case 28: +#line 306 "expread.y" +{ write_exp_elt_opcode (BINOP_MUL); ; + break;} +case 29: +#line 310 "expread.y" +{ write_exp_elt_opcode (BINOP_DIV); ; + break;} +case 30: +#line 314 "expread.y" +{ write_exp_elt_opcode (BINOP_REM); ; + break;} +case 31: +#line 318 "expread.y" +{ write_exp_elt_opcode (BINOP_ADD); ; + break;} +case 32: +#line 322 "expread.y" +{ write_exp_elt_opcode (BINOP_SUB); ; + break;} +case 33: +#line 326 "expread.y" +{ write_exp_elt_opcode (BINOP_LSH); ; + break;} +case 34: +#line 330 "expread.y" +{ write_exp_elt_opcode (BINOP_RSH); ; + break;} +case 35: +#line 334 "expread.y" +{ write_exp_elt_opcode (BINOP_EQUAL); ; + break;} +case 36: +#line 338 "expread.y" +{ write_exp_elt_opcode (BINOP_NOTEQUAL); ; + break;} +case 37: +#line 342 "expread.y" +{ write_exp_elt_opcode (BINOP_LEQ); ; + break;} +case 38: +#line 346 "expread.y" +{ write_exp_elt_opcode (BINOP_GEQ); ; + break;} +case 39: +#line 350 "expread.y" +{ write_exp_elt_opcode (BINOP_LESS); ; + break;} +case 40: +#line 354 "expread.y" +{ write_exp_elt_opcode (BINOP_GTR); ; + break;} +case 41: +#line 358 "expread.y" +{ write_exp_elt_opcode (BINOP_LOGAND); ; + break;} +case 42: +#line 362 "expread.y" +{ write_exp_elt_opcode (BINOP_LOGXOR); ; + break;} +case 43: +#line 366 "expread.y" +{ write_exp_elt_opcode (BINOP_LOGIOR); ; + break;} +case 44: +#line 370 "expread.y" +{ write_exp_elt_opcode (BINOP_AND); ; + break;} +case 45: +#line 374 "expread.y" +{ write_exp_elt_opcode (BINOP_OR); ; + break;} +case 46: +#line 378 "expread.y" +{ write_exp_elt_opcode (TERNOP_COND); ; + break;} +case 47: +#line 382 "expread.y" +{ write_exp_elt_opcode (BINOP_ASSIGN); ; + break;} +case 48: +#line 386 "expread.y" +{ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); + write_exp_elt_opcode (yyvsp[-1].opcode); + write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); ; + break;} +case 49: +#line 392 "expread.y" +{ write_exp_elt_opcode (OP_LONG); + if (yyvsp[0].lval == (int) yyvsp[0].lval || yyvsp[0].lval == (unsigned int) yyvsp[0].lval) + write_exp_elt_type (builtin_type_int); + else + write_exp_elt_type (BUILTIN_TYPE_LONGEST); + write_exp_elt_longcst ((LONGEST) yyvsp[0].lval); + write_exp_elt_opcode (OP_LONG); ; + break;} +case 50: +#line 402 "expread.y" +{ + write_exp_elt_opcode (OP_LONG); + if (yyvsp[0].ulval == (unsigned int) yyvsp[0].ulval) + write_exp_elt_type (builtin_type_unsigned_int); + else + write_exp_elt_type (BUILTIN_TYPE_UNSIGNED_LONGEST); + write_exp_elt_longcst ((LONGEST) yyvsp[0].ulval); + write_exp_elt_opcode (OP_LONG); + ; + break;} +case 51: +#line 414 "expread.y" +{ write_exp_elt_opcode (OP_LONG); + write_exp_elt_type (builtin_type_char); + write_exp_elt_longcst ((LONGEST) yyvsp[0].lval); + write_exp_elt_opcode (OP_LONG); ; + break;} +case 52: +#line 421 "expread.y" +{ write_exp_elt_opcode (OP_DOUBLE); + write_exp_elt_type (builtin_type_double); + write_exp_elt_dblcst (yyvsp[0].dval); + write_exp_elt_opcode (OP_DOUBLE); ; + break;} +case 54: +#line 431 "expread.y" +{ write_exp_elt_opcode (OP_LAST); + write_exp_elt_longcst ((LONGEST) yyvsp[0].lval); + write_exp_elt_opcode (OP_LAST); ; + break;} +case 55: +#line 437 "expread.y" +{ write_exp_elt_opcode (OP_REGISTER); + write_exp_elt_longcst ((LONGEST) yyvsp[0].lval); + write_exp_elt_opcode (OP_REGISTER); ; + break;} +case 56: +#line 443 "expread.y" +{ write_exp_elt_opcode (OP_INTERNALVAR); + write_exp_elt_intern (yyvsp[0].ivar); + write_exp_elt_opcode (OP_INTERNALVAR); ; + break;} +case 57: +#line 449 "expread.y" +{ write_exp_elt_opcode (OP_LONG); + write_exp_elt_type (builtin_type_int); + write_exp_elt_longcst ((LONGEST) TYPE_LENGTH (yyvsp[-1].tval)); + write_exp_elt_opcode (OP_LONG); ; + break;} +case 58: +#line 456 "expread.y" +{ write_exp_elt_opcode (OP_STRING); + write_exp_string (yyvsp[0].sval); + write_exp_elt_opcode (OP_STRING); ; + break;} +case 59: +#line 463 "expread.y" +{ write_exp_elt_opcode (OP_THIS); + write_exp_elt_opcode (OP_THIS); ; + break;} +case 60: +#line 470 "expread.y" +{ + struct symtab *tem = lookup_symtab (copy_name (yyvsp[0].sval)); + struct symbol *sym; + + if (tem) + yyval.bval = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), 1); + else + { + sym = lookup_symbol (copy_name (yyvsp[0].sval), + expression_context_block, + VAR_NAMESPACE, 0); + if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK) + yyval.bval = SYMBOL_BLOCK_VALUE (sym); + else + error ("No file or function \"%s\".", + copy_name (yyvsp[0].sval)); + } + ; + break;} +case 61: +#line 491 "expread.y" +{ struct symbol *tem + = lookup_symbol (copy_name (yyvsp[0].sval), yyvsp[-2].bval, VAR_NAMESPACE, 0); + if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK) + error ("No function \"%s\" in specified context.", + copy_name (yyvsp[0].sval)); + yyval.bval = SYMBOL_BLOCK_VALUE (tem); ; + break;} +case 62: +#line 500 "expread.y" +{ struct symbol *sym; + sym = lookup_symbol (copy_name (yyvsp[0].sval), yyvsp[-2].bval, VAR_NAMESPACE, 0); + if (sym == 0) + error ("No symbol \"%s\" in specified context.", + copy_name (yyvsp[0].sval)); + write_exp_elt_opcode (OP_VAR_VALUE); + write_exp_elt_sym (sym); + write_exp_elt_opcode (OP_VAR_VALUE); ; + break;} +case 63: +#line 511 "expread.y" +{ + struct type *type = yyvsp[-2].tval; + if (TYPE_CODE (type) != TYPE_CODE_STRUCT + && TYPE_CODE (type) != TYPE_CODE_UNION) + error ("`%s' is not defined as an aggregate type.", + TYPE_NAME (type)); + + write_exp_elt_opcode (OP_SCOPE); + write_exp_elt_type (type); + write_exp_string (yyvsp[0].sval); + write_exp_elt_opcode (OP_SCOPE); + ; + break;} +case 64: +#line 524 "expread.y" +{ + char *name = copy_name (yyvsp[0].sval); + struct symbol *sym; + int i; + + sym = lookup_symbol (name, 0, VAR_NAMESPACE, 0); + if (sym) + { + write_exp_elt_opcode (OP_VAR_VALUE); + write_exp_elt_sym (sym); + write_exp_elt_opcode (OP_VAR_VALUE); + break; + } + for (i = 0; i < misc_function_count; i++) + if (!strcmp (misc_function_vector[i].name, name)) + break; + + if (i < misc_function_count) + { + enum misc_function_type mft = + (enum misc_function_type) + misc_function_vector[i].type; + + write_exp_elt_opcode (OP_LONG); + write_exp_elt_type (builtin_type_int); + write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address); + write_exp_elt_opcode (OP_LONG); + write_exp_elt_opcode (UNOP_MEMVAL); + if (mft == mf_data || mft == mf_bss) + write_exp_elt_type (builtin_type_int); + else if (mft == mf_text) + write_exp_elt_type (lookup_function_type (builtin_type_int)); + else + write_exp_elt_type (builtin_type_char); + write_exp_elt_opcode (UNOP_MEMVAL); + } + else + if (symtab_list == 0 + && partial_symtab_list == 0) + error ("No symbol table is loaded. Use the \"symbol-file\" command."); + else + error ("No symbol \"%s\" in current context.", name); + ; + break;} +case 65: +#line 570 "expread.y" +{ struct symbol *sym; + int is_a_field_of_this; + + sym = lookup_symbol (copy_name (yyvsp[0].sval), + expression_context_block, + VAR_NAMESPACE, + &is_a_field_of_this); + if (sym) + { + switch (sym->class) + { + case LOC_REGISTER: + case LOC_ARG: + case LOC_LOCAL: + if (innermost_block == 0 || + contained_in (block_found, + innermost_block)) + innermost_block = block_found; + } + write_exp_elt_opcode (OP_VAR_VALUE); + write_exp_elt_sym (sym); + write_exp_elt_opcode (OP_VAR_VALUE); + } + else if (is_a_field_of_this) + { + /* C++: it hangs off of `this'. Must + not inadvertently convert from a method call + to data ref. */ + if (innermost_block == 0 || + contained_in (block_found, innermost_block)) + innermost_block = block_found; + write_exp_elt_opcode (OP_THIS); + write_exp_elt_opcode (OP_THIS); + write_exp_elt_opcode (STRUCTOP_PTR); + write_exp_string (yyvsp[0].sval); + write_exp_elt_opcode (STRUCTOP_PTR); + } + else + { + register int i; + register char *arg = copy_name (yyvsp[0].sval); + + for (i = 0; i < misc_function_count; i++) + if (!strcmp (misc_function_vector[i].name, arg)) + break; + + if (i < misc_function_count) + { + enum misc_function_type mft = + (enum misc_function_type) + misc_function_vector[i].type; + + write_exp_elt_opcode (OP_LONG); + write_exp_elt_type (builtin_type_int); + write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address); + write_exp_elt_opcode (OP_LONG); + write_exp_elt_opcode (UNOP_MEMVAL); + if (mft == mf_data || mft == mf_bss) + write_exp_elt_type (builtin_type_int); + else if (mft == mf_text) + write_exp_elt_type (lookup_function_type (builtin_type_int)); + else + write_exp_elt_type (builtin_type_char); + write_exp_elt_opcode (UNOP_MEMVAL); + } + else if (symtab_list == 0 + && partial_symtab_list == 0) + error ("No symbol table is loaded. Use the \"symbol-file\" command."); + else + error ("No symbol \"%s\" in current context.", + copy_name (yyvsp[0].sval)); + } + ; + break;} +case 67: +#line 648 "expread.y" +{ + /* This is where the interesting stuff happens. */ + int done = 0; + int array_size; + struct type *follow_type = yyvsp[-1].tval; + + while (!done) + switch (pop_type ()) + { + case tp_end: + done = 1; + break; + case tp_pointer: + follow_type = lookup_pointer_type (follow_type); + break; + case tp_reference: + follow_type = lookup_reference_type (follow_type); + break; + case tp_array: + array_size = (int) pop_type (); + if (array_size != -1) + follow_type = create_array_type (follow_type, + array_size); + else + follow_type = lookup_pointer_type (follow_type); + break; + case tp_function: + follow_type = lookup_function_type (follow_type); + break; + } + yyval.tval = follow_type; + ; + break;} +case 68: +#line 683 "expread.y" +{ push_type (tp_pointer); yyval.voidval = 0; ; + break;} +case 69: +#line 685 "expread.y" +{ push_type (tp_pointer); yyval.voidval = yyvsp[0].voidval; ; + break;} +case 71: +#line 690 "expread.y" +{ yyval.voidval = yyvsp[-1].voidval; ; + break;} +case 72: +#line 692 "expread.y" +{ + push_type ((enum type_pieces) yyvsp[0].lval); + push_type (tp_array); + ; + break;} +case 73: +#line 697 "expread.y" +{ + push_type ((enum type_pieces) yyvsp[0].lval); + push_type (tp_array); + yyval.voidval = 0; + ; + break;} +case 74: +#line 703 "expread.y" +{ push_type (tp_function); ; + break;} +case 75: +#line 705 "expread.y" +{ push_type (tp_function); ; + break;} +case 76: +#line 709 "expread.y" +{ yyval.lval = -1; ; + break;} +case 77: +#line 711 "expread.y" +{ yyval.lval = yyvsp[-1].lval; ; + break;} +case 78: +#line 715 "expread.y" +{ yyval.voidval = 0; ; + break;} +case 80: +#line 720 "expread.y" +{ yyval.tval = lookup_member_type (builtin_type_int, yyvsp[-2].tval); ; + break;} +case 81: +#line 722 "expread.y" +{ yyval.tval = lookup_member_type (yyvsp[-5].tval, yyvsp[-3].tval); ; + break;} +case 82: +#line 724 "expread.y" +{ yyval.tval = lookup_member_type + (lookup_function_type (yyvsp[-7].tval), yyvsp[-5].tval); ; + break;} +case 83: +#line 727 "expread.y" +{ yyval.tval = lookup_member_type + (lookup_function_type (yyvsp[-8].tval), yyvsp[-6].tval); + free (yyvsp[-1].tvec); ; + break;} +case 84: +#line 734 "expread.y" +{ yyval.tval = lookup_typename (copy_name (yyvsp[0].sval), + expression_context_block, 0); ; + break;} +case 85: +#line 737 "expread.y" +{ yyval.tval = builtin_type_int; ; + break;} +case 86: +#line 739 "expread.y" +{ yyval.tval = builtin_type_long; ; + break;} +case 87: +#line 741 "expread.y" +{ yyval.tval = builtin_type_short; ; + break;} +case 88: +#line 743 "expread.y" +{ yyval.tval = builtin_type_long; ; + break;} +case 89: +#line 745 "expread.y" +{ yyval.tval = builtin_type_unsigned_long; ; + break;} +case 90: +#line 747 "expread.y" +{ yyval.tval = builtin_type_short; ; + break;} +case 91: +#line 749 "expread.y" +{ yyval.tval = builtin_type_unsigned_short; ; + break;} +case 92: +#line 751 "expread.y" +{ yyval.tval = lookup_struct (copy_name (yyvsp[0].sval), + expression_context_block); ; + break;} +case 93: +#line 754 "expread.y" +{ yyval.tval = lookup_union (copy_name (yyvsp[0].sval), + expression_context_block); ; + break;} +case 94: +#line 757 "expread.y" +{ yyval.tval = lookup_enum (copy_name (yyvsp[0].sval), + expression_context_block); ; + break;} +case 95: +#line 760 "expread.y" +{ yyval.tval = lookup_unsigned_typename (copy_name (yyvsp[0].sval)); ; + break;} +case 96: +#line 762 "expread.y" +{ yyval.tval = builtin_type_unsigned_int; ; + break;} +case 97: +#line 764 "expread.y" +{ yyval.tval = lookup_typename (copy_name (yyvsp[0].sval), + expression_context_block, 0); ; + break;} +case 98: +#line 767 "expread.y" +{ yyval.tval = builtin_type_int; ; + break;} +case 100: +#line 772 "expread.y" +{ + yyval.sval.ptr = "int"; + yyval.sval.length = 3; + ; + break;} +case 101: +#line 777 "expread.y" +{ + yyval.sval.ptr = "long"; + yyval.sval.length = 4; + ; + break;} +case 102: +#line 782 "expread.y" +{ + yyval.sval.ptr = "short"; + yyval.sval.length = 5; + ; + break;} +case 103: +#line 790 "expread.y" +{ yyval.tvec = (struct type **)xmalloc (sizeof (struct type *) * 2); + yyval.tvec[0] = (struct type *)0; + yyval.tvec[1] = yyvsp[0].tval; + ; + break;} +case 104: +#line 795 "expread.y" +{ int len = sizeof (struct type *) * ++(yyvsp[-2].ivec[0]); + yyval.tvec = (struct type **)xrealloc (yyvsp[-2].tvec, len); + yyval.tvec[yyval.ivec[0]] = yyvsp[0].tval; + ; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 331 "bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + yyerror("parse error"); + } + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; #endif -YYSTYPE yylval, yyval; -# define YYERRCODE 256 -# line 630 "expread.y" +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; +} +#line 810 "expread.y" /* Begin counting arguments for a function call, @@ -268,7 +1709,7 @@ write_exp_string (str) } bcopy (str.ptr, (char *) &expout->elts[expout_ptr - lenelt], len); ((char *) &expout->elts[expout_ptr - lenelt])[len] = 0; - write_exp_elt_longcst (len); + write_exp_elt_longcst ((LONGEST) len); } /* During parsing of a C expression, the pointer to the next character @@ -306,11 +1747,12 @@ parse_number (olen) int olen; { register char *p = lexptr; - register long n = 0; + register LONGEST n = 0; register int c; register int base = 10; register int len = olen; char *err_copy; + int unsigned_p = 0; extern double atof (); @@ -336,7 +1778,7 @@ parse_number (olen) { c = *p++; if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; - if (c != 'l') + if (c != 'l' && c != 'u') n *= base; if (c >= '0' && c <= '9') n += c - '0'; @@ -346,6 +1788,16 @@ parse_number (olen) n += c - 'a' + 10; else if (len == 0 && c == 'l') ; + else if (len == 0 && c == 'u') + unsigned_p = 1; + else if (base == 10 && len != 0 && (c == 'e' || c == 'E')) + { + /* Scientific notation, where we are unlucky enough not + to have a '.' in the string. */ + yylval.dval = atof (lexptr); + lexptr += olen; + return FLOAT; + } else { err_copy = (char *) alloca (olen + 1); @@ -357,8 +1809,16 @@ parse_number (olen) } lexptr = p; - yylval.lval = n; - return INT; + if (unsigned_p) + { + yylval.ulval = n; + return UINT; + } + else + { + yylval.lval = n; + return INT; + } } struct token @@ -492,6 +1952,11 @@ yylex () lexptr++; return c; + case '.': + /* Might be a floating point number. */ + if (lexptr[1] >= '0' && lexptr[1] <= '9') + break; /* Falls into number code. */ + case '+': case '-': case '*': @@ -507,7 +1972,6 @@ yylex () case '>': case '[': case ']': - case '.': case '?': case ':': case '=': @@ -533,29 +1997,47 @@ yylex () lexptr += namelen + 1; return STRING; } - if (c >= '0' && c <= '9') + + /* Is it a number? */ + /* Note: We have already dealt with the case of the token '.'. + See case '.' above. */ + if ((c >= '0' && c <= '9') || c == '.') { - /* It's a number */ - for (namelen = 0; - c = tokstart[namelen], - (c == '_' || c == '$' || c == '.' || (c >= '0' && c <= '9') - || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); - namelen++) - ; - return parse_number (namelen); + /* It's a number. */ + int got_dot = 0, got_e = 0; + register char *p = tokstart; + int hex = c == '0' && (p[1] == 'x' || p[1] == 'X'); + if (hex) + p += 2; + for (;; ++p) + { + if (!hex && !got_e && (*p == 'e' || *p == 'E')) + got_dot = got_e = 1; + else if (!hex && !got_dot && *p == '.') + got_dot = 1; + else if (got_e && (p[-1] == 'e' || p[-1] == 'E') + && (*p == '-' || *p == '+')) + /* This is the sign of the exponent, not the end of the + number. */ + continue; + else if (*p < '0' || *p > '9' + && (!hex || ((*p < 'a' || *p > 'f') + && (*p < 'A' || *p > 'F')))) + break; + } + return parse_number (p - tokstart); } if (!(c == '_' || c == '$' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) error ("Invalid token in expression."); - /* It is a name. See how long it is. */ - - for (namelen = 0; - c = tokstart[namelen], + /* It's a name. See how long it is. */ + namelen = 0; + for (c = tokstart[namelen]; (c == '_' || c == '$' || (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); - namelen++) + c = tokstart[++namelen]) ; /* The token "if" terminates the expression and is NOT @@ -620,36 +2102,45 @@ yylex () return REGNAME; } } - if (namelen == 6 && !strncmp (tokstart, "struct", 6)) - { - return STRUCT; - } - if (namelen == 5) + /* Catch specific keywords. Should be done with a data structure. */ + switch (namelen) { + case 8: + if (!strncmp (tokstart, "unsigned", 8)) + return UNSIGNED; + break; + case 6: + if (!strncmp (tokstart, "struct", 6)) + return STRUCT; + if (!strncmp (tokstart, "signed", 6)) + return SIGNED; + if (!strncmp (tokstart, "sizeof", 6)) + return SIZEOF; + break; + case 5: if (!strncmp (tokstart, "union", 5)) - { - return UNION; - } - } - if (namelen == 4) - { + return UNION; + if (!strncmp (tokstart, "short", 5)) + return SHORT; + break; + case 4: if (!strncmp (tokstart, "enum", 4)) - { - return ENUM; - } + return ENUM; + if (!strncmp (tokstart, "long", 4)) + return LONG; if (!strncmp (tokstart, "this", 4) && lookup_symbol ("$this", expression_context_block, VAR_NAMESPACE, 0)) return THIS; + break; + case 3: + if (!strncmp (tokstart, "int", 3)) + return INT_KEYWORD; + break; + default: + break; } - if (namelen == 6 && !strncmp (tokstart, "sizeof", 6)) - { - return SIZEOF; - } - if (namelen == 8 && !strncmp (tokstart, "unsigned", 6)) - { - return UNSIGNED; - } + yylval.sval.ptr = tokstart; yylval.sval.length = namelen; @@ -661,12 +2152,25 @@ yylex () return VARIABLE; } - /* Use token-type TYPENAME for symbols that happen to be defined + /* Use token-type BLOCKNAME for symbols that happen to be defined as + functions or symtabs. If this is not so, then ... + Use token-type TYPENAME for symbols that happen to be defined currently as names of types; NAME for other symbols. The caller is not constrained to care about the distinction. */ - if (lookup_typename (copy_name (yylval.sval), expression_context_block, 1)) - return TYPENAME; - return NAME; + { + char *tmp = copy_name (yylval.sval); + struct symbol *sym; + + if (lookup_partial_symtab (tmp)) + return BLOCKNAME; + sym = lookup_symbol (tmp, expression_context_block, + VAR_NAMESPACE, 0); + if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK) + return BLOCKNAME; + if (lookup_typename (copy_name (yylval.sval), expression_context_block, 1)) + return TYPENAME; + return NAME; + } } static void @@ -929,6 +2433,7 @@ parse_c_1 (stringptr, block, comma) lexptr = *stringptr; paren_depth = 0; + type_stack_depth = 0; comma_terminates = comma; @@ -973,720 +2478,33 @@ parse_c_expression (string) error ("Junk after end of expression."); return exp; } -short yyexca[] ={ --1, 1, - 0, -1, - -2, 0, --1, 26, - 268, 79, - -2, 64, --1, 124, - 268, 60, - -2, 61, - }; -# define YYNPROD 81 -# define YYLAST 696 -short yyact[]={ - - 43, 54, 140, 39, 123, 41, 44, 120, 45, 37, - 42, 78, 77, 73, 39, 29, 30, 31, 142, 32, - 37, 131, 33, 52, 60, 53, 59, 40, 80, 81, - 143, 148, 33, 135, 149, 43, 54, 59, 39, 135, - 41, 44, 71, 45, 37, 42, 137, 129, 122, 138, - 90, 33, 144, 92, 38, 23, 74, 55, 52, 60, - 53, 59, 40, 146, 118, 38, 119, 88, 117, 17, - 43, 54, 1, 39, 0, 41, 44, 0, 45, 37, - 42, 128, 118, 0, 119, 0, 117, 56, 0, 38, - 0, 0, 55, 52, 0, 53, 59, 40, 7, 0, - 0, 75, 2, 5, 0, 13, 0, 4, 0, 0, - 6, 43, 54, 115, 39, 0, 41, 44, 0, 45, - 37, 42, 56, 0, 38, 0, 118, 55, 119, 132, - 117, 0, 0, 0, 52, 0, 53, 59, 40, 7, - 91, 0, 0, 0, 5, 0, 70, 0, 4, 0, - 0, 6, 0, 43, 54, 0, 39, 56, 41, 44, - 0, 45, 37, 42, 0, 38, 0, 0, 55, 116, - 118, 0, 119, 121, 117, 0, 52, 0, 53, 59, - 40, 0, 0, 0, 0, 0, 0, 147, 12, 0, - 0, 8, 150, 0, 145, 0, 43, 54, 56, 39, - 0, 41, 44, 0, 45, 37, 42, 38, 0, 0, - 55, 0, 0, 0, 0, 0, 0, 0, 0, 52, - 0, 53, 59, 40, 0, 0, 0, 0, 0, 12, - 39, 0, 8, 0, 0, 61, 37, 0, 58, 57, - 48, 49, 50, 51, 46, 47, 0, 34, 35, 36, - 38, 80, 81, 59, 40, 0, 0, 0, 34, 35, - 36, 0, 43, 0, 0, 39, 0, 41, 80, 81, - 61, 37, 42, 58, 57, 48, 49, 50, 51, 46, - 47, 38, 34, 35, 36, 80, 81, 0, 59, 40, - 0, 0, 0, 0, 43, 0, 0, 39, 0, 41, - 44, 0, 45, 37, 42, 0, 0, 0, 0, 57, - 48, 49, 50, 51, 46, 47, 38, 34, 35, 36, - 59, 40, 14, 15, 16, 26, 28, 21, 29, 30, - 31, 11, 32, 25, 18, 19, 20, 0, 22, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 38, 9, - 10, 48, 49, 50, 51, 46, 47, 0, 34, 35, - 36, 0, 0, 14, 15, 16, 26, 28, 21, 29, - 30, 31, 11, 32, 25, 18, 19, 20, 43, 22, - 0, 39, 0, 41, 44, 0, 45, 37, 42, 0, - 9, 10, 0, 48, 49, 50, 51, 46, 47, 0, - 34, 35, 36, 43, 59, 40, 39, 0, 41, 44, - 24, 45, 37, 42, 73, 0, 29, 30, 31, 0, - 32, 0, 0, 72, 76, 0, 52, 0, 53, 59, - 40, 0, 38, 0, 0, 0, 48, 49, 50, 51, - 46, 47, 0, 34, 35, 36, 43, 0, 0, 39, - 0, 41, 44, 27, 45, 37, 42, 38, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, - 0, 53, 59, 40, 34, 35, 36, 0, 0, 79, - 0, 76, 0, 82, 83, 84, 85, 0, 0, 0, - 87, 89, 0, 0, 0, 0, 0, 0, 0, 0, - 38, 0, 0, 0, 0, 0, 0, 0, 0, 34, - 35, 36, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 134, 124, 125, 0, 0, 0, 0, 0, 46, 47, - 3, 34, 35, 36, 0, 62, 63, 64, 65, 66, - 67, 68, 69, 0, 0, 72, 0, 0, 0, 0, - 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 86, 0, 0, 125, 0, 0, - 0, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 34, 35, 36, 0, 126, - 0, 127, 0, 130, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 48, 49, 50, 51, 46, 47, 0, - 34, 35, 36, 0, 0, 0, 0, 133, 0, 0, - 0, 0, 136, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 139, 136, 0, 0, 0, 0, 0, 141, - 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, - 46, 47, 0, 34, 35, 36 }; -short yypact[]={ - - 65,-1000, -22, -2, 65, 65, 65, 65, 65, 65, - 65, 106,-248, 65,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-256,-257,-232,-1000,-1000,-1000,-232, --232,-232,-232, 65,-1000,-1000, 25, 8, 65,-1000, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, -26, -26, -26, -26, -26, -26, -26, -26, - 65, 44,-261,-1000, 132, 7,-264,-232,-232,-1000, --1000,-1000,-1000,-1000,-1000,-1000, -2,-1000, 65,-1000, - 65, -12, 65, -26, 190, 190, 190, 225, 225, 341, - 341, 409, 409, 257, 257, 257, 257, 366, 159, 116, - 74, 33, -37, -2, -2, 88, 65,-1000,-1000,-248, - -3, 65,-1000, -9,-1000,-1000, 190, 190,-1000, 5, - -2, 65, 65, -26,-266,-1000, -26,-1000, 65, -2, - -24, -2, -11, 12, 153,-1000, -10, 26,-1000,-248, - 26 }; -short yypgo[]={ - - 0, 540, 101, 72, 69, 42, 410, 63, 55, 453, - 53, 47 }; -short yyr1[]={ - - 0, 3, 2, 2, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, - 1, 11, 11, 11, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, - 8, 4, 4, 4, 4, 5, 5, 5, 5, 5, - 5, 5, 6, 6, 6, 6, 6, 7, 7, 9, - 9 }; -short yyr2[]={ - - 0, 1, 1, 3, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 3, 4, 3, 4, 4, 0, - 5, 0, 1, 3, 4, 4, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 5, 3, 3, 1, - 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, - 3, 3, 3, 2, 1, 1, 2, 2, 3, 6, - 8, 9, 1, 2, 2, 2, 2, 1, 3, 1, - 1 }; -short yychk[]={ - --1000, -3, -2, -1, 42, 38, 45, 33, 126, 284, - 285, 266, 123, 40, 257, 258, 259, -4, 269, 270, - 271, 262, 273, -8, -6, 268, 260, -9, 261, 263, - 264, 265, 267, 44, 284, 285, 286, 46, 91, 40, - 64, 42, 47, 37, 43, 45, 281, 282, 277, 278, - 279, 280, 60, 62, 38, 94, 124, 276, 275, 63, - 61, 272, -1, -1, -1, -1, -1, -1, -1, -1, - 40, -5, -6, 261, -5, -2, -6, 268, 268, -9, - 260, 261, -9, -9, -9, -9, -1, -9, 42, -9, - 42, -2, -10, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -5, 125, 42, 38, 40, - 268, 41, 41, 268, -9, -9, -1, -1, 93, -11, - -1, 58, 41, -1, -6, 42, -1, 41, 44, -1, - 268, -1, 42, 41, 40, 41, -7, -5, 41, 44, - -5 }; -short yydef[]={ - - 0, -2, 1, 2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 49, 50, 51, 52, 53, 54, - 55, 57, 58, 0, 0, 0, -2, 59, 72, 0, - 0, 0, 0, 0, 11, 12, 0, 0, 0, 19, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 4, 5, 6, 7, 8, 9, 10, 13, - 0, 0, 65, 72, 0, 0, 65, 0, 0, 63, - 79, 80, 73, 74, 75, 76, 3, 14, 0, 16, - 0, 0, 21, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 0, 47, 48, 0, 0, 66, 67, 0, - 0, 0, 26, 0, -2, 62, 15, 17, 18, 0, - 22, 0, 56, 24, 0, 68, 25, 20, 0, 46, - 0, 23, 0, 69, 0, 70, 0, 77, 71, 0, - 78 }; -#ifndef lint -static char yaccpar_sccsid[] = "@(#)yaccpar 1.5 86/08/27 SMI"; /* from UCB 4.1 83/02/11 */ -#endif - -# -# define YYFLAG -1000 -# define YYERROR goto yyerrlab -# define YYACCEPT return(0) -# define YYABORT return(1) - -/* parser for yacc output */ - -#ifdef YYDEBUG -int yydebug = 0; /* 1 for debugging */ -#endif -YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */ -int yychar = -1; /* current input token number */ -int yynerrs = 0; /* number of errors */ -short yyerrflag = 0; /* error recovery flag */ - -yyparse() { - - short yys[YYMAXDEPTH]; - short yyj, yym; - register YYSTYPE *yypvt; - register short yystate, *yyps, yyn; - register YYSTYPE *yypv; - register short *yyxi; - - yystate = 0; - yychar = -1; - yynerrs = 0; - yyerrflag = 0; - yyps= &yys[-1]; - yypv= &yyv[-1]; - - yystack: /* put a state and value onto the stack */ - -#ifdef YYDEBUG - if( yydebug ) printf( "state %d, char 0%o\n", yystate, yychar ); -#endif - if( ++yyps>= &yys[YYMAXDEPTH] ) { yyerror( "yacc stack overflow" ); return(1); } - *yyps = yystate; - ++yypv; - *yypv = yyval; - - yynewstate: - - yyn = yypact[yystate]; - - if( yyn<= YYFLAG ) goto yydefault; /* simple state */ - - if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0; - if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault; - - if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */ - yychar = -1; - yyval = yylval; - yystate = yyn; - if( yyerrflag > 0 ) --yyerrflag; - goto yystack; - } - - yydefault: - /* default state action */ - - if( (yyn=yydef[yystate]) == -2 ) { - if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0; - /* look through exception table */ - - for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */ - - while( *(yyxi+=2) >= 0 ){ - if( *yyxi == yychar ) break; - } - if( (yyn = yyxi[1]) < 0 ) return(0); /* accept */ - } - - if( yyn == 0 ){ /* error */ - /* error ... attempt to resume parsing */ - - switch( yyerrflag ){ - - case 0: /* brand new error */ - - yyerror( "syntax error" ); - yyerrlab: - ++yynerrs; - - case 1: - case 2: /* incompletely recovered error ... try again */ - - yyerrflag = 3; - - /* find a state where "error" is a legal shift action */ - - while ( yyps >= yys ) { - yyn = yypact[*yyps] + YYERRCODE; - if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){ - yystate = yyact[yyn]; /* simulate a shift of "error" */ - goto yystack; - } - yyn = yypact[*yyps]; - - /* the current yyps has no shift onn "error", pop stack */ - -#ifdef YYDEBUG - if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] ); -#endif - --yyps; - --yypv; - } - - /* there is no state on the stack with an error shift ... abort */ - - yyabort: - return(1); - - - case 3: /* no shift yet; clobber input char */ - -#ifdef YYDEBUG - if( yydebug ) printf( "error recovery discards char %d\n", yychar ); -#endif - - if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */ - yychar = -1; - goto yynewstate; /* try again in the same state */ - } - - } - - /* reduction by production yyn */ - -#ifdef YYDEBUG - if( yydebug ) printf("reduce %d\n",yyn); -#endif - yyps -= yyr2[yyn]; - yypvt = yypv; - yypv -= yyr2[yyn]; - yyval = yypv[1]; - yym=yyn; - /* consult goto table to find next state */ - yyn = yyr1[yyn]; - yyj = yypgo[yyn] + *yyps + 1; - if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]]; - switch(yym){ - -case 3: -# line 165 "expread.y" -{ write_exp_elt_opcode (BINOP_COMMA); } break; -case 4: -# line 170 "expread.y" -{ write_exp_elt_opcode (UNOP_IND); } break; -case 5: -# line 173 "expread.y" -{ write_exp_elt_opcode (UNOP_ADDR); } break; -case 6: -# line 176 "expread.y" -{ write_exp_elt_opcode (UNOP_NEG); } break; -case 7: -# line 180 "expread.y" -{ write_exp_elt_opcode (UNOP_ZEROP); } break; -case 8: -# line 184 "expread.y" -{ write_exp_elt_opcode (UNOP_LOGNOT); } break; -case 9: -# line 188 "expread.y" -{ write_exp_elt_opcode (UNOP_PREINCREMENT); } break; -case 10: -# line 192 "expread.y" -{ write_exp_elt_opcode (UNOP_PREDECREMENT); } break; -case 11: -# line 196 "expread.y" -{ write_exp_elt_opcode (UNOP_POSTINCREMENT); } break; -case 12: -# line 200 "expread.y" -{ write_exp_elt_opcode (UNOP_POSTDECREMENT); } break; -case 13: -# line 204 "expread.y" -{ write_exp_elt_opcode (UNOP_SIZEOF); } break; -case 14: -# line 208 "expread.y" -{ write_exp_elt_opcode (STRUCTOP_PTR); - write_exp_string (yypvt[-0].sval); - write_exp_elt_opcode (STRUCTOP_PTR); } break; -case 15: -# line 214 "expread.y" -{ write_exp_elt_opcode (STRUCTOP_MPTR); } break; -case 16: -# line 218 "expread.y" -{ write_exp_elt_opcode (STRUCTOP_STRUCT); - write_exp_string (yypvt[-0].sval); - write_exp_elt_opcode (STRUCTOP_STRUCT); } break; -case 17: -# line 224 "expread.y" -{ write_exp_elt_opcode (STRUCTOP_MEMBER); } break; -case 18: -# line 228 "expread.y" -{ write_exp_elt_opcode (BINOP_SUBSCRIPT); } break; -case 19: -# line 234 "expread.y" -{ start_arglist (); } break; -case 20: -# line 236 "expread.y" -{ write_exp_elt_opcode (OP_FUNCALL); - write_exp_elt_longcst (end_arglist ()); - write_exp_elt_opcode (OP_FUNCALL); } break; -case 22: -# line 245 "expread.y" -{ arglist_len = 1; } break; -case 23: -# line 249 "expread.y" -{ arglist_len++; } break; -case 24: -# line 253 "expread.y" -{ write_exp_elt_opcode (UNOP_MEMVAL); - write_exp_elt_type (yypvt[-2].tval); - write_exp_elt_opcode (UNOP_MEMVAL); } break; -case 25: -# line 259 "expread.y" -{ write_exp_elt_opcode (UNOP_CAST); - write_exp_elt_type (yypvt[-2].tval); - write_exp_elt_opcode (UNOP_CAST); } break; -case 26: -# line 265 "expread.y" -{ } break; -case 27: -# line 271 "expread.y" -{ write_exp_elt_opcode (BINOP_REPEAT); } break; -case 28: -# line 275 "expread.y" -{ write_exp_elt_opcode (BINOP_MUL); } break; -case 29: -# line 279 "expread.y" -{ write_exp_elt_opcode (BINOP_DIV); } break; -case 30: -# line 283 "expread.y" -{ write_exp_elt_opcode (BINOP_REM); } break; -case 31: -# line 287 "expread.y" -{ write_exp_elt_opcode (BINOP_ADD); } break; -case 32: -# line 291 "expread.y" -{ write_exp_elt_opcode (BINOP_SUB); } break; -case 33: -# line 295 "expread.y" -{ write_exp_elt_opcode (BINOP_LSH); } break; -case 34: -# line 299 "expread.y" -{ write_exp_elt_opcode (BINOP_RSH); } break; -case 35: -# line 303 "expread.y" -{ write_exp_elt_opcode (BINOP_EQUAL); } break; -case 36: -# line 307 "expread.y" -{ write_exp_elt_opcode (BINOP_NOTEQUAL); } break; -case 37: -# line 311 "expread.y" -{ write_exp_elt_opcode (BINOP_LEQ); } break; -case 38: -# line 315 "expread.y" -{ write_exp_elt_opcode (BINOP_GEQ); } break; -case 39: -# line 319 "expread.y" -{ write_exp_elt_opcode (BINOP_LESS); } break; -case 40: -# line 323 "expread.y" -{ write_exp_elt_opcode (BINOP_GTR); } break; -case 41: -# line 327 "expread.y" -{ write_exp_elt_opcode (BINOP_LOGAND); } break; -case 42: -# line 331 "expread.y" -{ write_exp_elt_opcode (BINOP_LOGXOR); } break; -case 43: -# line 335 "expread.y" -{ write_exp_elt_opcode (BINOP_LOGIOR); } break; -case 44: -# line 339 "expread.y" -{ write_exp_elt_opcode (BINOP_AND); } break; -case 45: -# line 343 "expread.y" -{ write_exp_elt_opcode (BINOP_OR); } break; -case 46: -# line 347 "expread.y" -{ write_exp_elt_opcode (TERNOP_COND); } break; -case 47: -# line 351 "expread.y" -{ write_exp_elt_opcode (BINOP_ASSIGN); } break; -case 48: -# line 355 "expread.y" -{ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); - write_exp_elt_opcode (yypvt[-1].opcode); - write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); } break; -case 49: -# line 361 "expread.y" -{ write_exp_elt_opcode (OP_LONG); - write_exp_elt_type (builtin_type_long); - write_exp_elt_longcst (yypvt[-0].lval); - write_exp_elt_opcode (OP_LONG); } break; -case 50: -# line 368 "expread.y" -{ write_exp_elt_opcode (OP_LONG); - write_exp_elt_type (builtin_type_char); - write_exp_elt_longcst (yypvt[-0].lval); - write_exp_elt_opcode (OP_LONG); } break; -case 51: -# line 375 "expread.y" -{ write_exp_elt_opcode (OP_DOUBLE); - write_exp_elt_type (builtin_type_double); - write_exp_elt_dblcst (yypvt[-0].dval); - write_exp_elt_opcode (OP_DOUBLE); } break; -case 53: -# line 385 "expread.y" -{ write_exp_elt_opcode (OP_LAST); - write_exp_elt_longcst (yypvt[-0].lval); - write_exp_elt_opcode (OP_LAST); } break; -case 54: -# line 391 "expread.y" -{ write_exp_elt_opcode (OP_REGISTER); - write_exp_elt_longcst (yypvt[-0].lval); - write_exp_elt_opcode (OP_REGISTER); } break; -case 55: -# line 397 "expread.y" -{ write_exp_elt_opcode (OP_INTERNALVAR); - write_exp_elt_intern (yypvt[-0].ivar); - write_exp_elt_opcode (OP_INTERNALVAR); } break; -case 56: -# line 403 "expread.y" -{ write_exp_elt_opcode (OP_LONG); - write_exp_elt_type (builtin_type_int); - write_exp_elt_longcst ((long) TYPE_LENGTH (yypvt[-1].tval)); - write_exp_elt_opcode (OP_LONG); } break; -case 57: -# line 410 "expread.y" -{ write_exp_elt_opcode (OP_STRING); - write_exp_string (yypvt[-0].sval); - write_exp_elt_opcode (OP_STRING); } break; -case 58: -# line 417 "expread.y" -{ write_exp_elt_opcode (OP_THIS); - write_exp_elt_opcode (OP_THIS); } break; -case 59: -# line 424 "expread.y" -{ - struct symtab *tem = lookup_symtab (copy_name (yypvt[-0].sval)); - struct symbol *sym; - - if (tem) - yyval.bval = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), 1); - else - { - sym = lookup_symbol (copy_name (yypvt[-0].sval), - expression_context_block, - VAR_NAMESPACE, 0); - if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK) - yyval.bval = SYMBOL_BLOCK_VALUE (sym); - else - error ("No file or function \"%s\".", - copy_name (yypvt[-0].sval)); - } - } break; -case 60: -# line 445 "expread.y" -{ struct symbol *tem - = lookup_symbol (copy_name (yypvt[-0].sval), yypvt[-2].bval, VAR_NAMESPACE, 0); - if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK) - error ("No function \"%s\" in specified context.", - copy_name (yypvt[-0].sval)); - yyval.bval = SYMBOL_BLOCK_VALUE (tem); } break; -case 61: -# line 454 "expread.y" -{ struct symbol *sym; - sym = lookup_symbol (copy_name (yypvt[-0].sval), yypvt[-2].bval, VAR_NAMESPACE, 0); - if (sym == 0) - error ("No symbol \"%s\" in specified context.", - copy_name (yypvt[-0].sval)); - write_exp_elt_opcode (OP_VAR_VALUE); - write_exp_elt_sym (sym); - write_exp_elt_opcode (OP_VAR_VALUE); } break; -case 62: -# line 465 "expread.y" +static void +push_type (tp) + enum type_pieces tp; { - struct type *type = yypvt[-2].tval; - if (TYPE_CODE (type) != TYPE_CODE_STRUCT - && TYPE_CODE (type) != TYPE_CODE_UNION) - error ("`%s' is not defined as an aggregate type.", - TYPE_NAME (type)); + if (type_stack_depth == type_stack_size) + { + type_stack_size *= 2; + type_stack = (enum type_pieces *) + xrealloc (type_stack, type_stack_size * sizeof (enum type_pieces)); + } + type_stack[type_stack_depth++] = tp; +} - write_exp_elt_opcode (OP_SCOPE); - write_exp_elt_type (type); - write_exp_string (yypvt[-0].sval); - write_exp_elt_opcode (OP_SCOPE); - } break; -case 63: -# line 478 "expread.y" +static enum type_pieces +pop_type () { - char *name = copy_name (yypvt[-0].sval); - struct symbol *sym; - int i; - - sym = lookup_symbol (name, 0, VAR_NAMESPACE, 0); - if (sym) - { - write_exp_elt_opcode (OP_VAR_VALUE); - write_exp_elt_sym (sym); - write_exp_elt_opcode (OP_VAR_VALUE); - break; - } - for (i = 0; i < misc_function_count; i++) - if (!strcmp (misc_function_vector[i].name, name)) - break; - - if (i < misc_function_count) - { - write_exp_elt_opcode (OP_LONG); - write_exp_elt_type (builtin_type_int); - write_exp_elt_longcst (misc_function_vector[i].address); - write_exp_elt_opcode (OP_LONG); - write_exp_elt_opcode (UNOP_MEMVAL); - write_exp_elt_type (builtin_type_char); - write_exp_elt_opcode (UNOP_MEMVAL); - } - else - if (symtab_list == 0 - && partial_symtab_list == 0) - error ("No symbol table is loaded. Use the \"symbol-file\" command."); - else - error ("No symbol \"%s\" in current context.", name); - } break; -case 64: -# line 515 "expread.y" -{ struct symbol *sym; - int is_a_field_of_this; - - sym = lookup_symbol (copy_name (yypvt[-0].sval), - expression_context_block, - VAR_NAMESPACE, - &is_a_field_of_this); - if (sym) - { - switch (sym->class) - { - case LOC_REGISTER: - case LOC_ARG: - case LOC_LOCAL: - if (innermost_block == 0 || - contained_in (block_found, - innermost_block)) - innermost_block = block_found; - } - write_exp_elt_opcode (OP_VAR_VALUE); - write_exp_elt_sym (sym); - write_exp_elt_opcode (OP_VAR_VALUE); - } - else if (is_a_field_of_this) - { - /* C++: it hangs off of `this'. Must - not inadvertently convert from a method call - to data ref. */ - if (innermost_block == 0 || - contained_in (block_found, innermost_block)) - innermost_block = block_found; - write_exp_elt_opcode (OP_THIS); - write_exp_elt_opcode (OP_THIS); - write_exp_elt_opcode (STRUCTOP_PTR); - write_exp_string (yypvt[-0].sval); - write_exp_elt_opcode (STRUCTOP_PTR); - } - else - { - register int i; - register char *arg = copy_name (yypvt[-0].sval); - - for (i = 0; i < misc_function_count; i++) - if (!strcmp (misc_function_vector[i].name, arg)) - break; - - if (i < misc_function_count) - { - write_exp_elt_opcode (OP_LONG); - write_exp_elt_type (builtin_type_int); - write_exp_elt_longcst (misc_function_vector[i].address); - write_exp_elt_opcode (OP_LONG); - write_exp_elt_opcode (UNOP_MEMVAL); - write_exp_elt_type (builtin_type_char); - write_exp_elt_opcode (UNOP_MEMVAL); - } - else if (symtab_list == 0 - && partial_symtab_list == 0) - error ("No symbol table is loaded. Use the \"symbol-file\" command."); - else - error ("No symbol \"%s\" in current context.", - copy_name (yypvt[-0].sval)); - } - } break; -case 66: -# line 583 "expread.y" -{ yyval.tval = lookup_pointer_type (yypvt[-1].tval); } break; -case 67: -# line 585 "expread.y" -{ yyval.tval = lookup_reference_type (yypvt[-1].tval); } break; -case 68: -# line 587 "expread.y" -{ yyval.tval = lookup_member_type (builtin_type_int, yypvt[-2].tval); } break; -case 69: -# line 589 "expread.y" -{ yyval.tval = lookup_member_type (yypvt[-5].tval, yypvt[-3].tval); } break; -case 70: -# line 591 "expread.y" -{ yyval.tval = lookup_member_type (lookup_function_type (yypvt[-7].tval)); } break; -case 71: -# line 593 "expread.y" -{ yyval.tval = lookup_member_type (lookup_function_type (yypvt[-8].tval)); - free (yypvt[-1].tvec); } break; -case 72: -# line 599 "expread.y" -{ yyval.tval = lookup_typename (copy_name (yypvt[-0].sval), - expression_context_block, 0); } break; -case 73: -# line 602 "expread.y" -{ yyval.tval = lookup_struct (copy_name (yypvt[-0].sval), - expression_context_block); } break; -case 74: -# line 605 "expread.y" -{ yyval.tval = lookup_union (copy_name (yypvt[-0].sval), - expression_context_block); } break; -case 75: -# line 608 "expread.y" -{ yyval.tval = lookup_enum (copy_name (yypvt[-0].sval), - expression_context_block); } break; -case 76: -# line 611 "expread.y" -{ yyval.tval = lookup_unsigned_typename (copy_name (yypvt[-0].sval)); } break; -case 77: -# line 616 "expread.y" -{ yyval.tvec = (struct type **)xmalloc (sizeof (struct type *) * 2); - yyval.tvec[0] = (struct type *)0; - yyval.tvec[1] = yypvt[-0].tval; - } break; -case 78: -# line 621 "expread.y" -{ int len = sizeof (struct type *) * ++(yypvt[-2].ivec[0]); - yyval.tvec = (struct type **)xrealloc (yypvt[-2].tvec, len); - yyval.tvec[yyval.ivec[0]] = yypvt[-0].tval; - } break; - } - goto yystack; /* stack new state and value */ + if (type_stack_depth) + return type_stack[--type_stack_depth]; + return tp_end; +} - } +void +_initialize_expread () +{ + type_stack_size = 80; + type_stack_depth = 0; + type_stack = (enum type_pieces *) + xmalloc (type_stack_size * sizeof (enum type_pieces)); +} diff --git a/gdb/expread.y b/gdb/expread.y index fd6caa91ff..8af164e059 100644 --- a/gdb/expread.y +++ b/gdb/expread.y @@ -1,22 +1,21 @@ /* Parse C expressions for GDB. - Copyright (C) 1986 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! -*/ + 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. */ /* Parse a C expression from text in a string, and return the result as a struct expression pointer. @@ -35,6 +34,7 @@ anyone else from sharing it farther. Help stamp out software hoarding! #include "expression.h" #include +#include static struct expression *expout; static int expout_size; @@ -43,6 +43,12 @@ static int expout_ptr; static int yylex (); static void yyerror (); static void write_exp_elt (); +static void write_exp_elt_opcode (); +static void write_exp_elt_sym (); +static void write_exp_elt_longcst (); +static void write_exp_elt_dblcst (); +static void write_exp_elt_type (); +static void write_exp_elt_intern (); static void write_exp_string (); static void start_arglist (); static int end_arglist (); @@ -83,6 +89,19 @@ struct stoken char *ptr; int length; }; + +/* For parsing of complicated types. + An array should be preceded in the list by the size of the array. */ +enum type_pieces + {tp_end = -1, tp_pointer, tp_reference, tp_array, tp_function}; +static enum type_pieces *type_stack; +static int type_stack_depth, type_stack_size; + +static void push_type (); +static enum type_pieces pop_type (); + +/* Allow debugging of parsing. */ +#define YYDEBUG 1 %} /* Although the yacc "value" of an expression is not used, @@ -91,7 +110,8 @@ struct stoken %union { - long lval; + LONGEST lval; + unsigned LONGEST ulval; double dval; struct symbol *sym; struct type *tval; @@ -110,7 +130,13 @@ struct stoken %type nonempty_typelist %type block +/* Fancy type parsing. */ +%type func_mod direct_abs_decl abs_decl +%type ptype +%type array_mod + %token INT CHAR +%token UINT %token FLOAT /* Both NAME and TYPENAME tokens represent symbols in the input, @@ -122,11 +148,15 @@ struct stoken Contexts where this distinction is not important can use the nonterminal "name", which matches either NAME or TYPENAME. */ -%token NAME TYPENAME STRING -%type name +%token NAME TYPENAME BLOCKNAME STRING +%type name name_not_typename typename %token STRUCT UNION ENUM SIZEOF UNSIGNED COLONCOLON +/* Special type cases, put in to allow the parser to distinguish different + legal basetypes. */ +%token SIGNED LONG SHORT INT_KEYWORD + %token LAST REGNAME %token VARIABLE @@ -139,6 +169,7 @@ struct stoken %left ',' %left ABOVE_COMMA %right '=' ASSIGN_MODIFY +%right '?' %left OR %left AND %left '|' @@ -147,11 +178,11 @@ struct stoken %left EQUAL NOTEQUAL %left '<' '>' LEQ GEQ %left LSH RSH +%left '@' %left '+' '-' %left '*' '/' '%' -%left '@' %right UNARY INCREMENT DECREMENT -%right ARROW '.' '[' +%right ARROW '.' '[' '(' %left COLONCOLON %% @@ -232,9 +263,9 @@ exp : exp '(' /* This is to save the value of arglist_len being accumulated by an outer function call. */ { start_arglist (); } - arglist ')' + arglist ')' %prec ARROW { write_exp_elt_opcode (OP_FUNCALL); - write_exp_elt_longcst (end_arglist ()); + write_exp_elt_longcst ((LONGEST) end_arglist ()); write_exp_elt_opcode (OP_FUNCALL); } ; @@ -343,7 +374,7 @@ exp : exp OR exp { write_exp_elt_opcode (BINOP_OR); } ; -exp : exp '?' exp ':' exp +exp : exp '?' exp ':' exp %prec '?' { write_exp_elt_opcode (TERNOP_COND); } ; @@ -359,15 +390,30 @@ exp : exp ASSIGN_MODIFY exp exp : INT { write_exp_elt_opcode (OP_LONG); - write_exp_elt_type (builtin_type_long); - write_exp_elt_longcst ($1); + if ($1 == (int) $1 || $1 == (unsigned int) $1) + write_exp_elt_type (builtin_type_int); + else + write_exp_elt_type (BUILTIN_TYPE_LONGEST); + write_exp_elt_longcst ((LONGEST) $1); write_exp_elt_opcode (OP_LONG); } ; +exp : UINT + { + write_exp_elt_opcode (OP_LONG); + if ($1 == (unsigned int) $1) + write_exp_elt_type (builtin_type_unsigned_int); + else + write_exp_elt_type (BUILTIN_TYPE_UNSIGNED_LONGEST); + write_exp_elt_longcst ((LONGEST) $1); + write_exp_elt_opcode (OP_LONG); + } + ; + exp : CHAR { write_exp_elt_opcode (OP_LONG); write_exp_elt_type (builtin_type_char); - write_exp_elt_longcst ($1); + write_exp_elt_longcst ((LONGEST) $1); write_exp_elt_opcode (OP_LONG); } ; @@ -383,13 +429,13 @@ exp : variable exp : LAST { write_exp_elt_opcode (OP_LAST); - write_exp_elt_longcst ($1); + write_exp_elt_longcst ((LONGEST) $1); write_exp_elt_opcode (OP_LAST); } ; exp : REGNAME { write_exp_elt_opcode (OP_REGISTER); - write_exp_elt_longcst ($1); + write_exp_elt_longcst ((LONGEST) $1); write_exp_elt_opcode (OP_REGISTER); } ; @@ -399,10 +445,10 @@ exp : VARIABLE write_exp_elt_opcode (OP_INTERNALVAR); } ; -exp : SIZEOF '(' type ')' +exp : SIZEOF '(' type ')' %prec UNARY { write_exp_elt_opcode (OP_LONG); write_exp_elt_type (builtin_type_int); - write_exp_elt_longcst ((long) TYPE_LENGTH ($3)); + write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3)); write_exp_elt_opcode (OP_LONG); } ; @@ -420,7 +466,7 @@ exp : THIS /* end of C++. */ -block : name +block : BLOCKNAME { struct symtab *tem = lookup_symtab (copy_name ($1)); struct symbol *sym; @@ -494,12 +540,21 @@ variable: typebase COLONCOLON name if (i < misc_function_count) { + enum misc_function_type mft = + (enum misc_function_type) + misc_function_vector[i].type; + write_exp_elt_opcode (OP_LONG); write_exp_elt_type (builtin_type_int); - write_exp_elt_longcst (misc_function_vector[i].address); + write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address); write_exp_elt_opcode (OP_LONG); write_exp_elt_opcode (UNOP_MEMVAL); - write_exp_elt_type (builtin_type_char); + if (mft == mf_data || mft == mf_bss) + write_exp_elt_type (builtin_type_int); + else if (mft == mf_text) + write_exp_elt_type (lookup_function_type (builtin_type_int)); + else + write_exp_elt_type (builtin_type_char); write_exp_elt_opcode (UNOP_MEMVAL); } else @@ -511,7 +566,7 @@ variable: typebase COLONCOLON name } ; -variable: NAME +variable: name_not_typename { struct symbol *sym; int is_a_field_of_this; @@ -560,12 +615,21 @@ variable: NAME if (i < misc_function_count) { + enum misc_function_type mft = + (enum misc_function_type) + misc_function_vector[i].type; + write_exp_elt_opcode (OP_LONG); write_exp_elt_type (builtin_type_int); - write_exp_elt_longcst (misc_function_vector[i].address); + write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address); write_exp_elt_opcode (OP_LONG); write_exp_elt_opcode (UNOP_MEMVAL); - write_exp_elt_type (builtin_type_char); + if (mft == mf_data || mft == mf_bss) + write_exp_elt_type (builtin_type_int); + else if (mft == mf_text) + write_exp_elt_type (lookup_function_type (builtin_type_int)); + else + write_exp_elt_type (builtin_type_char); write_exp_elt_opcode (UNOP_MEMVAL); } else if (symtab_list == 0 @@ -578,19 +642,90 @@ variable: NAME } ; -type : typebase - | type '*' - { $$ = lookup_pointer_type ($1); } - | type '&' - { $$ = lookup_reference_type ($1); } + +ptype : typebase + | typebase abs_decl + { + /* This is where the interesting stuff happens. */ + int done = 0; + int array_size; + struct type *follow_type = $1; + + while (!done) + switch (pop_type ()) + { + case tp_end: + done = 1; + break; + case tp_pointer: + follow_type = lookup_pointer_type (follow_type); + break; + case tp_reference: + follow_type = lookup_reference_type (follow_type); + break; + case tp_array: + array_size = (int) pop_type (); + if (array_size != -1) + follow_type = create_array_type (follow_type, + array_size); + else + follow_type = lookup_pointer_type (follow_type); + break; + case tp_function: + follow_type = lookup_function_type (follow_type); + break; + } + $$ = follow_type; + } + ; + +abs_decl: '*' + { push_type (tp_pointer); $$ = 0; } + | '*' abs_decl + { push_type (tp_pointer); $$ = $2; } + | direct_abs_decl + ; + +direct_abs_decl: '(' abs_decl ')' + { $$ = $2; } + | direct_abs_decl array_mod + { + push_type ((enum type_pieces) $2); + push_type (tp_array); + } + | array_mod + { + push_type ((enum type_pieces) $1); + push_type (tp_array); + $$ = 0; + } + | direct_abs_decl func_mod + { push_type (tp_function); } + | func_mod + { push_type (tp_function); } + ; + +array_mod: '[' ']' + { $$ = -1; } + | '[' INT ']' + { $$ = $2; } + ; + +func_mod: '(' ')' + { $$ = 0; } + ; + +type : ptype | typebase COLONCOLON '*' { $$ = lookup_member_type (builtin_type_int, $1); } | type '(' typebase COLONCOLON '*' ')' { $$ = lookup_member_type ($1, $3); } | type '(' typebase COLONCOLON '*' ')' '(' ')' - { $$ = lookup_member_type (lookup_function_type ($1)); } + { $$ = lookup_member_type + (lookup_function_type ($1), $3); } | type '(' typebase COLONCOLON '*' ')' '(' nonempty_typelist ')' - { $$ = lookup_member_type (lookup_function_type ($1)); + { $$ = lookup_member_type + (lookup_function_type ($1), $3); free ($8); } ; @@ -598,6 +733,20 @@ typebase : TYPENAME { $$ = lookup_typename (copy_name ($1), expression_context_block, 0); } + | INT_KEYWORD + { $$ = builtin_type_int; } + | LONG + { $$ = builtin_type_long; } + | SHORT + { $$ = builtin_type_short; } + | LONG INT_KEYWORD + { $$ = builtin_type_long; } + | UNSIGNED LONG INT_KEYWORD + { $$ = builtin_type_unsigned_long; } + | SHORT INT_KEYWORD + { $$ = builtin_type_short; } + | UNSIGNED SHORT INT_KEYWORD + { $$ = builtin_type_unsigned_short; } | STRUCT name { $$ = lookup_struct (copy_name ($2), expression_context_block); } @@ -607,8 +756,33 @@ typebase | ENUM name { $$ = lookup_enum (copy_name ($2), expression_context_block); } - | UNSIGNED name + | UNSIGNED typename { $$ = lookup_unsigned_typename (copy_name ($2)); } + | UNSIGNED + { $$ = builtin_type_unsigned_int; } + | SIGNED typename + { $$ = lookup_typename (copy_name ($2), + expression_context_block, 0); } + | SIGNED + { $$ = builtin_type_int; } + ; + +typename: TYPENAME + | INT_KEYWORD + { + $$.ptr = "int"; + $$.length = 3; + } + | LONG + { + $$.ptr = "long"; + $$.length = 4; + } + | SHORT + { + $$.ptr = "short"; + $$.length = 5; + } ; nonempty_typelist @@ -625,8 +799,14 @@ nonempty_typelist ; name : NAME + | BLOCKNAME | TYPENAME ; + +name_not_typename : NAME + | BLOCKNAME + ; + %% /* Begin counting arguments for a function call, @@ -782,7 +962,7 @@ write_exp_string (str) } bcopy (str.ptr, (char *) &expout->elts[expout_ptr - lenelt], len); ((char *) &expout->elts[expout_ptr - lenelt])[len] = 0; - write_exp_elt_longcst (len); + write_exp_elt_longcst ((LONGEST) len); } /* During parsing of a C expression, the pointer to the next character @@ -820,11 +1000,12 @@ parse_number (olen) int olen; { register char *p = lexptr; - register long n = 0; + register LONGEST n = 0; register int c; register int base = 10; register int len = olen; char *err_copy; + int unsigned_p = 0; extern double atof (); @@ -850,7 +1031,7 @@ parse_number (olen) { c = *p++; if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; - if (c != 'l') + if (c != 'l' && c != 'u') n *= base; if (c >= '0' && c <= '9') n += c - '0'; @@ -860,6 +1041,16 @@ parse_number (olen) n += c - 'a' + 10; else if (len == 0 && c == 'l') ; + else if (len == 0 && c == 'u') + unsigned_p = 1; + else if (base == 10 && len != 0 && (c == 'e' || c == 'E')) + { + /* Scientific notation, where we are unlucky enough not + to have a '.' in the string. */ + yylval.dval = atof (lexptr); + lexptr += olen; + return FLOAT; + } else { err_copy = (char *) alloca (olen + 1); @@ -871,8 +1062,16 @@ parse_number (olen) } lexptr = p; - yylval.lval = n; - return INT; + if (unsigned_p) + { + yylval.ulval = n; + return UINT; + } + else + { + yylval.lval = n; + return INT; + } } struct token @@ -1006,6 +1205,11 @@ yylex () lexptr++; return c; + case '.': + /* Might be a floating point number. */ + if (lexptr[1] >= '0' && lexptr[1] <= '9') + break; /* Falls into number code. */ + case '+': case '-': case '*': @@ -1021,7 +1225,6 @@ yylex () case '>': case '[': case ']': - case '.': case '?': case ':': case '=': @@ -1047,29 +1250,47 @@ yylex () lexptr += namelen + 1; return STRING; } - if (c >= '0' && c <= '9') + + /* Is it a number? */ + /* Note: We have already dealt with the case of the token '.'. + See case '.' above. */ + if ((c >= '0' && c <= '9') || c == '.') { - /* It's a number */ - for (namelen = 0; - c = tokstart[namelen], - (c == '_' || c == '$' || c == '.' || (c >= '0' && c <= '9') - || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); - namelen++) - ; - return parse_number (namelen); + /* It's a number. */ + int got_dot = 0, got_e = 0; + register char *p = tokstart; + int hex = c == '0' && (p[1] == 'x' || p[1] == 'X'); + if (hex) + p += 2; + for (;; ++p) + { + if (!hex && !got_e && (*p == 'e' || *p == 'E')) + got_dot = got_e = 1; + else if (!hex && !got_dot && *p == '.') + got_dot = 1; + else if (got_e && (p[-1] == 'e' || p[-1] == 'E') + && (*p == '-' || *p == '+')) + /* This is the sign of the exponent, not the end of the + number. */ + continue; + else if (*p < '0' || *p > '9' + && (!hex || ((*p < 'a' || *p > 'f') + && (*p < 'A' || *p > 'F')))) + break; + } + return parse_number (p - tokstart); } if (!(c == '_' || c == '$' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) error ("Invalid token in expression."); - /* It is a name. See how long it is. */ - - for (namelen = 0; - c = tokstart[namelen], + /* It's a name. See how long it is. */ + namelen = 0; + for (c = tokstart[namelen]; (c == '_' || c == '$' || (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); - namelen++) + c = tokstart[++namelen]) ; /* The token "if" terminates the expression and is NOT @@ -1134,36 +1355,45 @@ yylex () return REGNAME; } } - if (namelen == 6 && !strncmp (tokstart, "struct", 6)) - { - return STRUCT; - } - if (namelen == 5) + /* Catch specific keywords. Should be done with a data structure. */ + switch (namelen) { + case 8: + if (!strncmp (tokstart, "unsigned", 8)) + return UNSIGNED; + break; + case 6: + if (!strncmp (tokstart, "struct", 6)) + return STRUCT; + if (!strncmp (tokstart, "signed", 6)) + return SIGNED; + if (!strncmp (tokstart, "sizeof", 6)) + return SIZEOF; + break; + case 5: if (!strncmp (tokstart, "union", 5)) - { - return UNION; - } - } - if (namelen == 4) - { + return UNION; + if (!strncmp (tokstart, "short", 5)) + return SHORT; + break; + case 4: if (!strncmp (tokstart, "enum", 4)) - { - return ENUM; - } + return ENUM; + if (!strncmp (tokstart, "long", 4)) + return LONG; if (!strncmp (tokstart, "this", 4) && lookup_symbol ("$this", expression_context_block, VAR_NAMESPACE, 0)) return THIS; + break; + case 3: + if (!strncmp (tokstart, "int", 3)) + return INT_KEYWORD; + break; + default: + break; } - if (namelen == 6 && !strncmp (tokstart, "sizeof", 6)) - { - return SIZEOF; - } - if (namelen == 8 && !strncmp (tokstart, "unsigned", 6)) - { - return UNSIGNED; - } + yylval.sval.ptr = tokstart; yylval.sval.length = namelen; @@ -1175,12 +1405,25 @@ yylex () return VARIABLE; } - /* Use token-type TYPENAME for symbols that happen to be defined + /* Use token-type BLOCKNAME for symbols that happen to be defined as + functions or symtabs. If this is not so, then ... + Use token-type TYPENAME for symbols that happen to be defined currently as names of types; NAME for other symbols. The caller is not constrained to care about the distinction. */ - if (lookup_typename (copy_name (yylval.sval), expression_context_block, 1)) - return TYPENAME; - return NAME; + { + char *tmp = copy_name (yylval.sval); + struct symbol *sym; + + if (lookup_partial_symtab (tmp)) + return BLOCKNAME; + sym = lookup_symbol (tmp, expression_context_block, + VAR_NAMESPACE, 0); + if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK) + return BLOCKNAME; + if (lookup_typename (copy_name (yylval.sval), expression_context_block, 1)) + return TYPENAME; + return NAME; + } } static void @@ -1443,6 +1686,7 @@ parse_c_1 (stringptr, block, comma) lexptr = *stringptr; paren_depth = 0; + type_stack_depth = 0; comma_terminates = comma; @@ -1487,3 +1731,33 @@ parse_c_expression (string) error ("Junk after end of expression."); return exp; } + +static void +push_type (tp) + enum type_pieces tp; +{ + if (type_stack_depth == type_stack_size) + { + type_stack_size *= 2; + type_stack = (enum type_pieces *) + xrealloc (type_stack, type_stack_size * sizeof (enum type_pieces)); + } + type_stack[type_stack_depth++] = tp; +} + +static enum type_pieces +pop_type () +{ + if (type_stack_depth) + return type_stack[--type_stack_depth]; + return tp_end; +} + +void +_initialize_expread () +{ + type_stack_size = 80; + type_stack_depth = 0; + type_stack = (enum type_pieces *) + xmalloc (type_stack_size * sizeof (enum type_pieces)); +} diff --git a/gdb/expression.h b/gdb/expression.h index ade7adbd70..5a5e20e060 100644 --- a/gdb/expression.h +++ b/gdb/expression.h @@ -1,22 +1,21 @@ /* Definitions for expressions stored in reversed prefix form, for GDB. - Copyright (C) 1986 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! -*/ + 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. */ diff --git a/gdb/findvar.c b/gdb/findvar.c index 0bfd1d8317..82d32b7808 100644 --- a/gdb/findvar.c +++ b/gdb/findvar.c @@ -1,22 +1,21 @@ /* Find a variable's value in memory, for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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" @@ -44,7 +43,7 @@ find_saved_register (frame, regnum) #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 dissapears as you go + 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 @@ -53,9 +52,25 @@ find_saved_register (frame, regnum) 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)) { - fi = get_frame_info (frame); + 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); @@ -228,7 +243,7 @@ supply_register (regno, val) } /* Given a struct symbol for a variable, - and a stack frame address, read the value of the variable + and a stack frame id, read the value of the variable and return a (pointer to a) struct value containing the value. */ value @@ -272,7 +287,13 @@ read_var_value (var, frame) 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); @@ -444,15 +465,15 @@ value_from_register (type, regnum, frame) 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. */ + /* 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); } @@ -461,7 +482,7 @@ value_from_register (type, regnum, frame) } /* Given a struct symbol for a variable, - and a stack frame address, + and a stack frame id, return a (pointer to a) struct value containing the variable's address. */ value @@ -473,6 +494,7 @@ locate_var_value (var, frame) 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; @@ -509,6 +531,12 @@ locate_var_value (var, 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); @@ -523,7 +551,12 @@ locate_var_value (var, frame) break; } - return value_cast (lookup_pointer_type (type), + /* 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)); } diff --git a/gdb/frame.h b/gdb/frame.h index bd5ce5d0b1..5f0a664a9e 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -1,22 +1,21 @@ /* Definitions for dealing with stack frames, for GDB, the GNU debugger. - Copyright (C) 1986 Free Software Foundation, Inc. + Copyright (C) 1986, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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! */ @@ -101,6 +100,7 @@ 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 (); diff --git a/gdb/gdb.texinfo b/gdb/gdb.texinfo index db83964552..8e98d8b464 100644 --- a/gdb/gdb.texinfo +++ b/gdb/gdb.texinfo @@ -1,10 +1,11 @@ \input texinfo -@setfilename ../info/gdb +@setfilename gdb.info @settitle GDB, The GNU Debugger +@synindex ky cp @ifinfo This file documents the GNU debugger GDB. -Copyright (C) 1988 Free Software Foundation, Inc. +Copyright (C) 1988, 1989 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice @@ -19,16 +20,16 @@ notice identical to this one except for the removal of this paragraph @end ignore Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the -sections entitled ``Distribution'' and ``GDB General Public License'' are -included exactly as in the original, and provided that the entire resulting -derived work is distributed under the terms of a permission notice -identical to this one. +section entitled ``GNU General Public License'' is included exactly as +in the original, and provided that the entire resulting derived work is +distributed under the terms of a permission notice identical to this +one. Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, -except that the sections entitled ``Distribution'' and ``GDB General Public -License'' may be included in a translation approved by the author instead -of in the original English. +except that the section entitled ``GNU General Public License'' may be +included in a translation approved by the author instead of in the +original English. @end ifinfo @setchapternewpage odd @@ -39,9 +40,9 @@ of in the original English. @sp 1 @center The GNU Source-Level Debugger @sp 4 -@center Third Edition, GDB version 3.1 +@center Third Edition, GDB version 3.2 @sp 1 -@center January 1989 +@center April 1989 @sp 5 @center Richard M. Stallman @page @@ -54,20 +55,20 @@ are preserved on all copies. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the -sections entitled ``Distribution'' and ``GDB General Public License'' are -included exactly as in the original, and provided that the entire resulting -derived work is distributed under the terms of a permission notice -identical to this one. +section entitled ``GNU General Public License'' is included exactly as +in the original, and provided that the entire resulting derived work is +distributed under the terms of a permission notice identical to this +one. Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, -except that the sections entitled ``Distribution'' and ``GDB General Public -License'' may be included in a translation approved by the author instead -of in the original English. +except that the section entitled ``GNU General Public License'' may be +included in a translation approved by the author instead of in the +original English. @end titlepage @page -@node Top, Commands,, (DIR) +@node Top, Top, Top, (DIR) @unnumbered Summary of GDB The purpose of a debugger such as GDB is to allow you to execute another @@ -97,10 +98,10 @@ is being implemented, and Fortran support will be added when a GNU Fortran compiler is written. @menu -* License:: The GDB General Public License gives you permission +* License:: The GNU General Public License gives you permission to redistribute GDB on certain terms; and also explains that there is no warranty. -* Input:: GDB command syntax and input conventions. +* User Interface:: GDB command syntax and input and output conventions. * Files:: Specifying files for GDB to operate on. * Options:: GDB arguments and options. * Compilation::Compiling your program so you can debug it. @@ -118,95 +119,128 @@ Fortran compiler is written. * Concepts:: Index of GDB concepts. @end menu -@node License, Input, Top, Top -@unnumbered GDB General Public License -@center (Clarified 11 Feb 1988) +@node License, User Interface, Top, Top +@unnumbered GNU GENERAL PUBLIC LICENSE +@center Version 1, February 1989 + +@display +Copyright @copyright{} 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. +@end display + +@unnumberedsec 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. - The license agreements of most software companies keep you at the mercy -of those companies. By contrast, our general public license is intended to -give everyone the right to share GDB. To make sure that you get the rights -we want you to have, we need to make restrictions that forbid anyone to -deny you these rights or to ask you to surrender the rights. Hence this -license agreement. - - Specifically, we want to make sure that you have the right to give away -copies of GDB, that you receive source code or else can get it if you want -it, that you can change GDB or use pieces of it in new free programs, and -that you know you can do these things. - - To make sure that everyone has such rights, we have to forbid you to -deprive anyone else of these rights. For example, if you distribute copies -of GDB, 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. - - Also, for our own protection, we must make certain that everyone finds -out that there is no warranty for GDB. If GDB is modified by someone else -and passed on, we want its recipients to know that what they have is not -what we distributed, so that any problems introduced by others will not -reflect on our reputation. - - Therefore we (Richard Stallman and the Free Software Foundation, -Inc.) make the following terms which say what you must do to be -allowed to distribute or change GDB. - -@unnumberedsec Copying Policies +@iftex +@unnumberedsec TERMS AND CONDITIONS +@end iftex +@ifinfo +@center TERMS AND CONDITIONS +@end ifinfo @enumerate @item -You may copy and distribute verbatim copies of GDB source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each file a valid copyright notice ``Copyright -@copyright{} 1988 Free Software Foundation, Inc.'' (or with whatever year -is appropriate); keep intact the notices on all files that -refer to this License Agreement and to the absence of any warranty; and -give any other recipients of the GDB program a copy of this License -Agreement along with the program. You may charge a distribution fee -for the physical act of transferring a copy. +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''. + +@item +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. @item -You may modify your copy or copies of GDB source code 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: +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: @itemize @bullet @item -cause the modified files to carry prominent notices stating -that you changed the files and the date of any change; and +cause the modified files to carry prominent notices stating that +you changed the files and the date of any change; and @item cause the whole of any work that you distribute or publish, that -in whole or in part contains or is a derivative of GDB or any -part thereof, to be licensed at no charge to all third parties on -terms identical to those contained in this License Agreement -(except that you may choose to grant more extensive warranty -protection to some or all third parties, at your option). +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). @item -if the modified program serves as a debugger, cause it, when -started running in the simplest and usual way, to print an -announcement including a valid copyright notice ``Copyright -@copyright{} 1988 Free Software Foundation, Inc.'' (or with the -year that is appropriate), saying 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 License Agreement. +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. @item -You may charge a distribution fee for the physical act of -transferring a copy, and you may at your option offer warranty -protection in exchange for a fee. +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. @end itemize -Mere aggregation of another unrelated program with this program (or its +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 program under the scope of these terms. +the other work under the scope of these terms. @item -You may copy and distribute GDB (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: +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: @itemize @bullet @item @@ -216,8 +250,8 @@ Paragraphs 1 and 2 above; or, @item accompany it with a written offer, valid for at least three -years, to give any third party free (except for a nominal -shipping charge) a complete machine-readable copy of the +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, @@ -228,70 +262,175 @@ allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) @end itemize -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. +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. @item -You may not copy, sublicense, distribute or transfer GDB except as -expressly provided under this License Agreement. Any attempt -otherwise to copy, sublicense, distribute or transfer GDB is void and -your rights to use GDB under this License agreement shall be -automatically terminated. However, parties who have received computer -software programs from you with this License Agreement will not have -their licenses terminated so long as such parties remain in full -compliance. +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. @item -If you wish to incorporate parts of GDB into other free programs whose -distribution conditions are different, write to the Free Software -Foundation. We have not yet worked out a simple rule that can be -stated here, but we will often permit this. We will be guided by the -two goals of preserving the free status of all derivatives our free -software and of promoting the sharing and reuse of software. +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. + +@item +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. + +@item +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. + +@item +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. + +@iftex +@heading NO WARRANTY +@end iftex +@ifinfo +@center NO WARRANTY +@end ifinfo + +@item +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. + +@item +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 enumerate @iftex -@vfil -@eject +@heading END OF TERMS AND CONDITIONS @end iftex -@unnumberedsec NO WARRANTY - - BECAUSE GDB IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY -NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT -WHEN OTHERWISE STATED IN WRITING, THE FREE SOFTWARE FOUNDATION, INC, -RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE GDB ``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 GDB -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY -SERVICING, REPAIR OR CORRECTION. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL FREE SOFTWARE -FOUNDATION, INC., RICHARD M. STALLMAN, AND/OR ANY OTHER PARTY WHO MAY -MODIFY AND REDISTRIBUTE GDB AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER -SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR -INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA -BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A -FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY -FREE SOFTWARE FOUNDATION, INC.) THE PROGRAM, EVEN IF YOU HAVE BEEN -ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY -OTHER PARTY. - -@node Input, Files, License, Top -@chapter GDB Input Conventions +@ifinfo +@center END OF TERMS AND CONDITIONS +@end ifinfo + +@page +@unnumberedsec 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. + +@smallexample +@var{one line to give the program's name and a brief idea of what it does.} +Copyright (C) 19@var{yy} @var{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. +@end smallexample + +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: + +@smallexample +Gnomovision version 69, Copyright (C) 19@var{yy} @var{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. +@end smallexample + +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: + +@example +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. + +@var{signature of Ty Coon}, 1 April 1989 +Ty Coon, President of Vice +@end example + +That's all there is to it! + +@node User Interface, Files, License, Top +@chapter GDB Input and Output Conventions GDB is invoked with the shell command @samp{gdb}. Once started, it reads commands from the terminal until you tell it to exit. A GDB command is a single line of input. There is no limit on how long it can be. It starts with a command name, which is followed by arguments -whose meaning depends on the command name. Some command names do not -allow arguments. +whose meaning depends on the command name. For example, the command +@samp{step} accepts an argument which is the number of times to step, +as in @samp{step 5}. You can also use the @samp{step} command with +no arguments. Some command names do not allow any arguments. +@cindex abbreviation GDB command names may always be abbreviated if the abbreviation is unambiguous. Sometimes even ambiguous abbreviations are allowed; for example, @samp{s} is specially defined as equivalent to @samp{step} @@ -299,6 +438,7 @@ even though there are other commands whose names start with @samp{s}. Possible command abbreviations are often stated in the documentation of the individual commands. +@cindex repeating commands A blank line as input to GDB means to repeat the previous command verbatim. Certain commands do not allow themselves to be repeated this way; these are commands for which unintentional repetition might cause trouble and which @@ -308,25 +448,12 @@ you are unlikely to want to repeat. Certain others (@samp{list} and A line of input starting with @samp{#} is a comment; it does nothing. This is useful mainly in command files (@xref{Command Files}). -Occasionally it is useful to execute a shell command from within gdb. -This can be done with the @samp{shell} command, or the shell escape -character @samp{!}. - -@table @code -@item shell @var{shell command string} -@kindex shell -@item !@var{shell command string} -@kindex ! -@cindex shell escape -Directs GDB to invoke an inferior shell to execute @samp{shell command string}. -The environmental variable @samp{SHELL} is used if it exists, otherwise gdb -uses @samp{/bin/sh}. -@end table - -GDB @dfn{prompts} for commands with a string that is normally @samp{(gdb)}. -When debugging GDB with GDB, it is useful to change the prompt in one of -the GDBs so that you can distinguish them. This can be done with the -@samp{set prompt} command. +@cindex prompt +GDB indicates its readiness to read a command by printing a string +called the @dfn{prompt}. This string is normally @samp{(gdb)}. You can +change the prompt string with the @samp{set prompt} command. For +instance, when debugging GDB with GDB, it is useful to change the prompt +in one of the GDBs so that you tell which one you are talking to. @table @code @item set prompt @var{newprompt} @@ -342,15 +469,62 @@ of any GDB command that is in progress and return to GDB command level. It is safe to type @kbd{Ctrl-c} at any time because GDB does not allow it to take effect until a time when it is safe. -@node Files, Options, Input, Top +@cindex screen size +@cindex pauses in output +Certain commands to GDB may produce large amounts of information output +to the screen. To help you read all of it, GDB pauses and asks you for +input at the end of each page of output. Type @key{RET} when you want +to continue the output. Normally GDB knows the size of the screen from +on the termcap data base together with the value of the @code{TERM} +environment variable; if this is not correct, you can override it with +the @samp{set screensize} command: + +@table @code +@item set screensize @var{lpp} +@itemx set screensize @var{lpp} @var{cpl} +@kindex set screensize +Specify a screen height of @var{lpp} lines and (optionally) a width of +@var{cpl} characters. If you omit @var{cpl}, the width does not change. + +If you specify a height of zero lines, GDB will not pause during output +no matter how long the output is. This is useful if output is to a file +or to an editor buffer. +@end table + +Also, GDB may at times produce more information about its own workings +than is of interest to the user. Some of these informational messages +can be turned on and off with the @samp{set verbose} command: + +@table @code +@kindex set verbose +@item set verbose off +Disables GDB's output of certain informational messages. + +@item set verbose on +Re-enables GDB's output of certain informational messages. +@end table + +Currently, the messages controlled by @samp{set verbose} are those which +announce that the symbol table for a source file is being read +(@pxref{File Commands}, in the description of the command +@samp{symbol-file}). +@c The following is the right way to do it, but emacs 18.55 doesn't support +@c @ref, and neither the emacs lisp manual version of texinfmt or makeinfo +@c is released. +@ignore +see @samp{symbol-file} in @ref{File Commands}). +@end ignore + +@node Files, Compilation, User Interface, Top @chapter Specifying GDB's Files @cindex core dump file @cindex executable file @cindex symbol table -GDB needs to know the filename of the program to be debugged. To debug a -core dump of a previous run, GDB must be told the filename of the core -dump. +GDB needs to know the file name of the program to be debugged, both in +order to read its symbol table and in order to start the program. To +debug a core dump of a previous run, GDB must be told the file name of +the core dump. @menu * Arguments: File Arguments. Specifying files with arguments @@ -375,8 +549,8 @@ specifies @file{progm} as the executable program and @file{core} as a core dump file to examine. (You do not need to have a core dump file if what you plan to do is debug the program interactively.) -@xref{Options}, for full information on command options and arguments for -GDB. +@xref{Options}, for full information on options and arguments for +invoking GDB. @node File Commands,, File Arguments, Files @section Specifying Files with Commands @@ -392,18 +566,38 @@ files are useful. @kindex exec-file Specify that the program to be run is found in @var{filename}. If you do not specify a directory and the file is not found in GDB's working -directory, GDB will use the environment variable @samp{PATH} as a list +directory, GDB will use the environment variable @code{PATH} as a list of directories to search, just as the shell does when looking for a program to run. @item symbol-file @var{filename} @kindex symbol-file -Read symbol table information from file @var{filename}. @samp{PATH} +Read symbol table information from file @var{filename}. @code{PATH} is searched when necessary. Most of the time you will use both the @samp{exec-file} and @samp{symbol-file} commands on the same file. @samp{symbol-file} with no argument clears out GDB's symbol table. +The @samp{symbol-file} command does not actually read the symbol table in +full right away. Instead, it scans the symbol table quickly to find +which source files and which symbols are present. The details are read +later, one source file at a time, when they are needed. + +The purpose of this two-stage reading strategy is to make GDB start up +faster. For the most part, it is invisible except for occasional +messages telling you that the symbol table details for a particular +source file are being read. (The @samp{set verbose} command controls +whether these messages are printed; @pxref{User Interface}). + +However, you will sometimes see in backtraces lines for functions in +source files whose data has not been read in; these lines omit some of +the information, such as argument values, which cannot be printed +without full details of the symbol table. + +When the symbol table is stored in COFF format, @samp{symbol-file} does +read the symbol table data in full right away. We haven't bothered to +implement the two-stage strategy for COFF. + @item core-file @var{filename} @kindex core-file Specify the whereabouts of a core dump file to be used as the @@ -414,29 +608,27 @@ executable file. @samp{core-file} with no argument specifies that no core file is to be used. +Note that the core file is ignored when your program is actually running +under GDB. So, if you have been running the program and you wish to +debug a core file instead, you must kill the subprocess in which the +program is running. To do this, use the @samp{kill} command +(@pxref{Kill Process}). + @item add-file @var{filename} @var{address} @kindex add-file -The @samp{add-file} command takes two arguments, a file name, and the -address at which that file has been (or should be) dynamically loaded. -GDB will then treat that file as though it had always been dynamically -linked, and provide the user with all the normal GDB features, including -symbolic debugging. - -With the @samp{add-file} command, it is possible to debug code which was -not present in the initial load image of the program under test. -Suppose you have a program which can, while running, dynamically link a -program fragment into its address space. One program which does this is -KCL, a free common lisp implementation. The fragment will be loaded -into the main program's address space at some address, and the main -program can then call functions within the fragment by calculating (or -otherwise obtaining) their addresses. - -@item kill -@kindex kill -Cancel running the program under GDB. This could be used if you wish -to debug a core dump instead. GDB ignores any core dump file if it is -actually running the program, so the @samp{kill} command is the only -sure way to go back to using the core dump file. +@cindex dynamic linking +The @samp{add-file} command reads additional symbol table information +from the file @var{filename}. You would use this when that file has +been dynamically loaded into the program that is running. @var{address} +should be the memory address at which the file has been loaded; GDB cannot +figure this out for itself. + +The symbol table of the file @var{filename} is added to the symbol table +originally read with the @samp{symbol-file} command. You can use the +@samp{add-file} command any number of times; the new symbol data thus +read keeps adding to the old. The @samp{symbol-file} command forgets +all the symbol data GDB has read; that is the only time symbol data is +forgotten in GDB. @item info files @kindex info files @@ -454,88 +646,7 @@ auto-display expressions. This is because they may contain pointers to the internal data recording symbols and data types, which are part of the old symbol table data being discarded inside GDB. -@node Options, Compilation, Files, Top -@chapter Options and Arguments for GDB - -When you invoke GDB, you can pass commands telling it what files to -operate on and what other things to do. - -@menu -* Mode Options:: Options controlling modes of operation. -* File Options:: Options to specify files (executable, coredump, commands) -* Other Arguments:: Any other arguments without options - also specify files. -@end menu - -@node Mode Options, File Options, Options, Options -@section Mode Options - -@table @samp -@item -nx -Do not execute commands from the init files @file{.gdbinit}. -Normally, the commands in these files are executed after all the -command options and arguments have been processed. @xref{Command -Files}. - -@item -q -``Quiet''. Do not print the usual introductory messages. - -@item -batch -Run in batch mode. Exit with code 1 after processing all the command -files specified with @samp{-x} (and @file{.gdbinit}, if not -inhibited). Exit also if, due to an error, GDB would otherwise -attempt to read a command from the terminal. - -@item -fullname -This option is used when Emacs runs GDB as a subprocess. It tells GDB -to output the full file name and line number in a standard, -recognizable fashion each time a stack frame is displayed (which -includes each time the program stops). This recognizable format looks -like two @samp{\032} characters, followed by the filename, line number -and character position separated by colons, and a newline. The -Emacs-to-GDB interface program uses the two @samp{\032} characters as -a signal to display the source code for the frame. -@end table - -@node File Options, Other Arguments, Mode Options, Options -@section File-specifying Options - -All the options and command line arguments given are processed -in sequential order. The order makes a difference when the -@samp{-x} command is used. - -@table @samp -@item -s @var{file} -Read symbol table from file @var{file}. - -@item -e @var{file} -Use file @var{file} as the executable file to execute when -appropriate, and for examining pure data in conjunction with a core -dump. - -@item -se @var{file} -Read symbol table from file @var{file} and use it as the executable -file. - -@item -c @var{file} -Use file @var{file} as a core dump to examine. - -@item -x @var{file} -Execute GDB commands from file @var{file}. - -@item -d @var{directory} -Add @var{directory} to the path to search for source files. -@end table - -@node Other Arguments,, File Options, Options -@section Other Arguments - -If there are arguments to GDB that are not options or associated with -options, the first one specifies the symbol table and executable file name -(as if it were preceded by @samp{-se}) and the second one specifies a core -dump file name (as if it were preceded by @samp{-c}). - -@node Compilation, Running, Options, Top +@node Compilation, Running, Files, Top @chapter Compiling Your Program for Debugging In order to debug a program effectively, you need to ask for debugging @@ -555,27 +666,20 @@ possible to debug optimized code. We recommend that you @emph{always} use @samp{-g} whenever you compile a program. You may think the program is correct, but there's no sense in pushing your luck. -If you are using the GNU C compiler, the GNU assembler and the GNU linker, -you can choose between two formats of debugging information: the standard -Unix format, which is what you get with @samp{-g}, and GDB's own format, -which you request by using @samp{-gg} instead of @samp{-g}. This stores -debugging information in the executable file in a format much like that -which is used inside GDB. This has these advantages and disadvantages: +GDB no longer supports the debugging information produced by giving the +GNU C compiler the @samp{-gg} option, so do not use this option. -@itemize @bullet -@item -GDB can read @samp{-gg} format more than twice as fast as Unix -@samp{-g} format. +If your program includes archives made with the @code{ar} program, and +if the object files used as input to @code{ar} were compiled without the +@samp{-g} option and have names longer than 15 characters, GDB will get +confused reading the program's symbol table. No error message will be +given, but GDB may behave strangely. The reason for this problem is a +deficiency in the Unix archive file format, which cannot represent file +names longer than 15 characters. -@item -The @samp{-gg} format uses much more disk space than Unix format. - -@item -The Unix debuggers can understand only Unix format, so you cannot use -Unix source-level debuggers if you compile with @samp{-gg}. (The -@code{adb} debugger works with either format; it does not use this -information in any case.) -@end itemize +To avoid this problem, compile the archive members with the @samp{-g} +option or use shorter file names. Alternatively, use a version of GNU +@code{ar} dated more recently than August 1989. @node Running, Stopping, Compilation, Top @chapter Running Your Program Under GDB @@ -587,16 +691,17 @@ must already have been specified using the @samp{exec-file} command or with an argument to GDB (@pxref{Files}); what @samp{run} does is create an inferior process, load the program into it, and set it in motion. -The execution of a program is affected by certain information it receives -from its superior. GDB provides ways to specify them, which you must do -@i{before} starting the program. (You can change them after starting the -program, but such changes do not affect the program unless you start it -over again.) +The execution of a program is affected by certain information it +receives from its superior. GDB provides ways to specify this +information, which you must do @i{before} starting the program. (You +can change it after starting the program, but such changes do not affect +the program unless you start it over again.) This information may be +divided into three categories: @table @asis @item The @i{arguments.} You specify the arguments to give the program as the arguments of the -@samp{run} command. +@samp{run} command. @item The @i{environment.} The program normally inherits its environment from GDB, but you can @@ -615,7 +720,7 @@ program to stop. @xref{Stopping}. Note that once your program has been started by the @samp{run} command, you may evaluate expressions that involve calls to functions in the inferior. @xref{Expressions}. If you wish to evaluate a function -simply for it's side affects, you may use the @samp{set} command. +simply for its side affects, you may use the @samp{set} command. @xref{Assignment}. @menu @@ -625,13 +730,14 @@ simply for it's side affects, you may use the @samp{set} command. to your program when it is run. * Input/Output:: Specifying the program's standard input and output. * Attach:: Debugging a process started outside GDB. +* Kill Process:: Getting rid of the child process running your program. @end menu @node Arguments, Environment, Running, Running @section Your Program's Arguments @cindex arguments (to your program) -You specify the arguments to give the program as the arguments of the +The arguments to your program are specified by the arguments of the @samp{run} command. They are passed to a shell, which expands wildcard characters and performs redirection of I/O, and thence to the program. @@ -670,7 +776,7 @@ your program when it is started. This command can be abbreviated @samp{i env}. @item set environment @var{varname} @var{value} -@item set environment @var{varname} = @var{value} +@itemx set environment @var{varname} = @var{value} @kindex set environment Sets environment variable @var{varname} to @var{value}, for your program only, not for GDB itself. @var{value} may be any string; the values of @@ -679,25 +785,36 @@ supplied by your program itself. The @var{value} parameter is optional; if it is eliminated, the variable is set to a null value. This command can be abbreviated as short as @samp{set e}. +For example, this command: + +@example +set env USER = foo +@end example + +@noindent +tells the program, when subsequently run, to assume it is being run +on behalf of the user named @samp{foo}. + @item delete environment @var{varname} +@itemx unset environment @var{varname} @kindex delete environment -@item unset environment @var{varname} @kindex unset environment -Remove variable @var{varname} from the environment to be passed to -your program. This is different from @samp{set env @var{varname} =} -because @samp{delete environment} makes a variable not be defined at -all, which is distinguishable from an empty value. This command can -be abbreviated @samp{d e}. +Remove variable @var{varname} from the environment to be passed to your +program. This is different from @samp{set env @var{varname}@ =} because +@samp{delete environment} leaves the variable with no value, which is +distinguishable from an empty value. This command can be abbreviated +@samp{d e}. @end table @node Working Directory, Input/Output, Environment, Running @section Your Program's Working Directory @cindex working directory (of your program) -Each time you start your program with @samp{run}, it inherits its working -directory from the current working directory of GDB. GDB's working -directory is initially whatever it inherited from its superior, but you can -specify the working directory for GDB with the @samp{cd} command. +Each time you start your program with @samp{run}, it inherits its +working directory from the current working directory of GDB. GDB's +working directory is initially whatever it inherited from its parent +process (typically the shell), but you can specify a new working +directory in GDB with the @samp{cd} command. The GDB working directory also serves as a default for the commands that specify files for GDB to operate on. @xref{Files}. @@ -731,49 +848,52 @@ run > outfile starts the program, diverting its output to the file @file{outfile}. @kindex tty -Another way to specify where the program should do input and output is with -the @samp{tty} command. This command accepts a file name as argument, and -causes this file to be the default for future @samp{run} commands. It also -resets the controlling terminal for future @samp{run} commands. For -example, +Another way to specify where the program should do input and output is +with the @samp{tty} command. This command accepts a file name as +argument, and causes this file to be the default for future @samp{run} +commands. It also resets the controlling terminal for the child +process, for future @samp{run} commands. For example, @example tty /dev/ttyb @end example @noindent -directs that processes started with subsequent @samp{run} commands default -to do input and output on the terminal @file{/dev/ttyb} and sets the -controlling terminal to @file{/dev/ttyb}. An explicit redirection in -@samp{run} overrides the @samp{tty} command's effect on input/output -redirection. +directs that processes started with subsequent @samp{run} commands +default to do input and output on the terminal @file{/dev/ttyb} and have +that as their controlling terminal. + +An explicit redirection in @samp{run} overrides the @samp{tty} command's +effect on input/output redirection, but not its effect on the +controlling terminal. When you use the @samp{tty} command or redirect input in the @samp{run} -command, the @emph{input for your program} comes from the specified file, -but the input for GDB still comes from your terminal. +command, only the @emph{input for your program} is affected. The input +for GDB still comes from your terminal. -@node Attach,, Input/Output, Running +@node Attach, Kill Process, Input/Output, Running @section Debugging an Already-Running Process @kindex detach @kindex attach @cindex attach -Some operating systems (in particular, Sun) allow GDB to begin debugging an -already-running process that was started outside of GDB. To do this you -must use the @samp{attach} command instead of the @samp{run} command. +Some operating systems allow GDB to debug an already-running process +that was started outside of GDB. To do this, you use the @samp{attach} +command instead of the @samp{run} command. -The @samp{attach} command requires one argument, which is the process-id of -the process you want to debug. (The usual way to find out the process-id -of the process is with the @samp{ps} utility.) +The @samp{attach} command requires one argument, which is the process-id +of the process you want to debug. (The usual way to find out the +process-id of the process is with the @code{ps} utility.) The first thing GDB does after arranging to debug the process is to stop it. You can examine and modify an attached process with all the GDB commands that ordinarily available when you start processes with @samp{run}. You can insert breakpoints; you can step and continue; you can modify storage. If you would rather the process continue running, -use the @samp{continue} command after attaching. +you may use the @samp{continue} command after attaching GDB to the +process. -When you are finished debugging the attached process, you can use the +When you have finished debugging the attached process, you can use the @samp{detach} command to release it from GDB's control. Detaching the process continues its execution. After the @samp{detach} command, that process and GDB become completely independent once more, and you @@ -783,12 +903,41 @@ If you exit GDB or use the @samp{run} command while you have an attached process, you kill that process. You will be asked for confirmation if you try to do either of these things. +The @samp{attach} command is also used to debug a remote machine via a +serial connection. @xref{Attach}, for more info. + +@node Kill Process,, Attach, Running +@section Killing the Child Process + +@table @code +@item kill +@kindex kill +Kill the child process in which the program being debugged is running +under GDB. + +This command is useful if you wish to debug a core dump instead. GDB +ignores any core dump file if it is actually running the program, so the +@samp{kill} command is the only sure way to make sure the core dump file +is used once again. + +It is also useful if you wish to run the program outside the debugger +for once and then go back to debugging it. + +The @samp{kill} command is also useful if you wish to recompile and +relink the program, since on many systems it is impossible to modify an +executable file which is running in a process. But, in this case, it is +just as good to exit GDB, since you will need to read a new symbol table +after the program is recompiled if you wish to debug the new version, +and restarting GDB is the easiest way to do that. +@end table + @node Stopping, Stack, Running, Top @chapter Stopping and Continuing -When you run a program normally, it runs until exiting. The purpose -of using a debugger is so that you can stop it before that point; -or so that if the program runs into trouble you can find out why. +When you run a program normally, it runs until it terminates. The +principal purpose of using a debugger is so that you can stop it before +that point; or so that if the program runs into trouble you can +investigate and find out why. @menu * Signals:: Fatal signals in your program just stop it; @@ -802,6 +951,7 @@ or so that if the program runs into trouble you can find out why. @node Signals, Breakpoints, Stopping, Stopping @section Signals +@cindex signals A signal is an asynchronous event that can happen in a program. The operating system defines the possible kinds of signals, and gives each kind @@ -811,6 +961,7 @@ gets from referencing a place in memory far away from all the areas in use; @code{SIGALRM} occurs when the alarm clock timer goes off (which happens only if the program has requested an alarm). +@cindex fatal signals Some signals, including @code{SIGALRM}, are a normal part of the functioning of the program. Others, such as @code{SIGSEGV}, indicate errors; these signals are @dfn{fatal} (kill the program immediately) if the @@ -822,6 +973,7 @@ GDB has the ability to detect any occurrence of a signal in the program running under GDB's control. You can tell GDB in advance what to do for each kind of signal. +@cindex handling signals Normally, GDB is set up to ignore non-erroneous signals like @code{SIGALRM} (so as not to interfere with their role in the functioning of the program) but to stop the program immediately whenever an error signal happens. @@ -904,23 +1056,23 @@ enable it again. @kindex info break @kindex $_ The command @samp{info break} prints a list of all breakpoints set and not -cleared, showing their numbers, where in the program they are, and any +deleted, showing their numbers, where in the program they are, and any special features in use for them. Disabled breakpoints are included in the list, but marked as disabled. @samp{info break} with a breakpoint number -as argument lists only that breakpoint. The convenience variable @samp{$_} +as argument lists only that breakpoint. The convenience variable @code{$_} and the default examining-address for the @samp{x} command are set to the address of the last breakpoint listed (@pxref{Memory}). @menu * Set Breaks:: How to establish breakpoints. -* Clear Breaks:: How to remove breakpoints no longer needed. +* Delete Breaks:: How to remove breakpoints no longer needed. * Disabling:: How to disable breakpoints (turn them off temporarily). * Conditions:: Making extra conditions on whether to stop. * Break Commands:: Commands to be executed at a breakpoint. * Error in Breakpoints:: "Cannot insert breakpoints" error--why, what to do. @end menu -@node Set Breaks, Clear Breaks, Breakpoints, Breakpoints +@node Set Breaks, Delete Breaks, Breakpoints, Breakpoints @subsection Setting Breakpoints @kindex break @@ -931,6 +1083,11 @@ You have several ways to say where the breakpoint should go. @item break @var{function} Set a breakpoint at entry to function @var{function}. +@item break @var{+offset} +@itemx break @var{-offset} +Set a breakpoint some number of lines forward or back from the position +at which execution stopped in the currently selected frame. + @item break @var{linenum} Set a breakpoint at line @var{linenum} in the current source file. That file is the last file whose source text was printed. This @@ -942,7 +1099,7 @@ Set a breakpoint at line @var{linenum} in source file @var{filename}. @item break @var{filename}:@var{function} Set a breakpoint at entry to function @var{function} found in file -@var{filename}. Specifying a filename as well as a function name is +@var{filename}. Specifying a file name as well as a function name is superfluous except when multiple files contain similarly named functions. @@ -956,11 +1113,15 @@ Set a breakpoint at the next instruction to be executed in the selected stack frame (@pxref{Stack}). In any selected frame but the innermost, this will cause the program to stop as soon as control returns to that frame. This is equivalent to a @samp{finish} command in the frame -inside the selected frame. If this is done in the innermost frame gdb +inside the selected frame. If this is done in the innermost frame, GDB will stop the next time it reaches the current location; this may be -useful inside of loops. It does not stop at this breakpoint immediately -upon continuation of the program since no code would be executed if it -did. +useful inside of loops. + +GDB normally ignores breakpoints when it resumes execution, until at +least one instruction has been executed. If it did not do this, you +would be unable to proceed past a breakpoint without first disabling the +breakpoint. This rule applies whether or not the breakpoint already +existed when the program stopped. @item break @dots{} if @var{cond} Set a breakpoint with condition @var{cond}; evaluate the expression @@ -973,61 +1134,60 @@ arguments described above (or no argument) specifying where to break. @kindex tbreak Set a breakpoint enabled only for one stop. @var{args} are the same as in the @samp{break} command, and the breakpoint is set in the same -way, but the breakpoint is automatically @dfn{disabled} the first time it -is hit. +way, but the breakpoint is automatically disabled the first time it +is hit. @xref{Disabling}. @end table GDB allows you to set any number of breakpoints at the same place in the program. There is nothing silly or meaningless about this. When the breakpoints are conditional, this is even useful (@pxref{Conditions}). -@node Clear Breaks, Disabling, Set Breaks, Breakpoints -@subsection Clearing Breakpoints +@node Delete Breaks, Disabling, Set Breaks, Breakpoints +@subsection Deleting Breakpoints -@cindex clear breakpoint -@cindex delete breakpoints +@cindex clearing breakpoint +@cindex deleting breakpoints It is often necessary to eliminate a breakpoint once it has done its job and you no longer want the program to stop there. This is called -@dfn{clearing} or @samp{deleting} the breakpoint. A breakpoint that -has been cleared no longer exists in any sense. +@dfn{deleting} the breakpoint. A breakpoint that has been deleted no +longer exists in any sense; it is forgotten. -With the @samp{clear} command you can clear breakpoints according to where -they are in the program. With the @samp{delete} command you can clear +With the @samp{clear} command you can delete breakpoints according to where +they are in the program. With the @samp{delete} command you can delete individual breakpoints by specifying their breakpoint numbers. -@b{It is not necessary to clear a breakpoint to proceed past it.} GDB +@b{It is not necessary to delete a breakpoint to proceed past it.} GDB automatically ignores breakpoints in the first instruction to be executed -when you continue execution at the same address where the program stopped. +when you continue execution without changing the execution address. @table @code @item clear @kindex clear -Clear any breakpoints at the next instruction to be executed in the +Delete any breakpoints at the next instruction to be executed in the selected stack frame (@pxref{Selection}). When the innermost frame -is selected, this is a good way to clear a breakpoint that the program +is selected, this is a good way to delete a breakpoint that the program just stopped at. @item clear @var{function} @itemx clear @var{filename}:@var{function} -Clear any breakpoints set at entry to the function @var{function}. +Delete any breakpoints set at entry to the function @var{function}. @item clear @var{linenum} -@item clear @var{filename}:@var{linenum} -Clear any breakpoints set at or within the code of the specified line. +@itemx clear @var{filename}:@var{linenum} +Delete any breakpoints set at or within the code of the specified line. @item delete @var{bnums}@dots{} @kindex delete Delete the breakpoints of the numbers specified as arguments. -A breakpoint deleted is forgotten completely. @end table -@node Disabling, Conditions, Clear Breaks, Breakpoints +@node Disabling, Conditions, Delete Breaks, Breakpoints @subsection Disabling Breakpoints @cindex disabled breakpoints @cindex enabled breakpoints -Rather than clearing a breakpoint, you might prefer to @dfn{disable} it. -This makes the breakpoint inoperative as if it had been cleared, but +Rather than deleting a breakpoint, you might prefer to @dfn{disable} it. +This makes the breakpoint inoperative as if it had been deleted, but remembers the information on the breakpoint so that you can @dfn{enable} it again later. @@ -1058,8 +1218,8 @@ commands: @table @code @item disable breakpoints @var{bnums}@dots{} +@itemx disable @var{bnums}@dots{} @kindex disable breakpoints -@item disable @var{bnums}@dots{} @kindex disable Disable the specified breakpoints. A disabled breakpoint has no effect but is not forgotten. All options such as ignore-counts, @@ -1067,20 +1227,20 @@ conditions and commands are remembered in case the breakpoint is enabled again later. @item enable breakpoints @var{bnums}@dots{} +@itemx enable @var{bnums}@dots{} @kindex enable breakpoints -@item enable @var{bnums}@dots{} @kindex enable Enable the specified breakpoints. They become effective once again in stopping the program, until you specify otherwise. @item enable breakpoints once @var{bnums}@dots{} -@item enable once @var{bnums}@dots{} +@itemx enable once @var{bnums}@dots{} Enable the specified breakpoints temporarily. Each will be disabled again the next time it stops the program (unless you have used one of these commands to specify a different state before that time comes). @item enable breakpoints delete @var{bnums}@dots{} -@item enable delete @var{bnums}@dots{} +@itemx enable delete @var{bnums}@dots{} Enable the specified breakpoints to work once and then die. Each of the breakpoints will be deleted the next time it stops the program (unless you have used one of these commands to specify a different @@ -1094,14 +1254,15 @@ is used. @node Conditions, Break Commands, Disabling, Breakpoints @subsection Break Conditions +@cindex conditional breakpoints +@cindex breakpoint conditions -@cindex conditions The simplest sort of breakpoint breaks every time the program reaches a -specified place. You can also specify a @dfn{condition} for a breakpoint. -A condition is just a boolean expression in your programming language -(@xref{Expressions}). A breakpoint with a condition evaluates the -expression each time the program reaches it, and the program stops -only if the condition is true. +specified place. You can also specify a @dfn{condition} for a +breakpoint. A condition is just a boolean expression in your +programming language. (@xref{Expressions}). A breakpoint with a +condition evaluates the expression each time the program reaches it, and +the program stops only if the condition is true. Break conditions may have side effects, and may even call functions in your program. These may sound like strange things to do, but their effects are @@ -1131,12 +1292,16 @@ an ordinary unconditional breakpoint. @end table @cindex ignore count (of breakpoint) -A special feature is provided for one kind of condition: to prevent the -breakpoint from doing anything until it has been reached a certain number -of times. This is done with the @dfn{ignore count} of the breakpoint. -When the program reaches a breakpoint whose ignore count is positive, then -instead of stopping, it just decrements the ignore count by one and -continues. +A special case of a breakpoint condition is to stop only when the +breakpoint has been reached a certain number of times. This is so +useful that there is a special way to do it, using the @dfn{ignore +count} of the breakpoint. Every breakpoint has an ignore count, which +is an integer. Most of the time, the ignore count is zero, and +therefore has no effect. But if the program reaches a breakpoint whose +ignore count is positive, then instead of stopping, it just decrements +the ignore count by one and continues. As a result, if the ignore count +value is @var{n}, the breakpoint will not stop the next @var{n} times it +is reached. @table @code @item ignore @var{bnum} @var{count} @@ -1150,9 +1315,8 @@ a count of zero. @item cont @var{count} Continue execution of the program, setting the ignore count of the breakpoint that the program stopped at to @var{count} minus one. -Continuing through the breakpoint does not itself count as one of -@var{count}. Thus, the program will not stop at this breakpoint until the -@var{count}'th time it is hit. +Thus, the program will not stop at this breakpoint until the +@var{count}'th time it is reached. This command is allowed only when the program stopped due to a breakpoint. At other times, the argument to @samp{cont} is ignored. @@ -1162,10 +1326,9 @@ If a breakpoint has a positive ignore count and a condition, the condition is not checked. Once the ignore count reaches zero, the condition will start to be checked. -Note that you could achieve the effect of the ignore count with a condition -such as @samp{$foo-- <= 0} using a debugger convenience variable that is -decremented each time. That is why the ignore count is considered a -special case of a condition. @xref{Convenience Vars}. +Note that you could achieve the effect of the ignore count with a +condition such as @w{@samp{$foo-- <= 0}} using a debugger convenience +variable that is decremented each time. @xref{Convenience Vars}. @node Break Commands, Error in Breakpoints, Conditions, Breakpoints @subsection Commands Executed on Breaking @@ -1191,8 +1354,8 @@ With no arguments, @samp{commands} refers to the last breakpoint set. It is possible for breakpoint commands to start the program up again. Simply use the @samp{cont} command, or @samp{step}, or any other command to resume execution. However, any remaining breakpoint commands are -ignored. When the program stops again, GDB will act according to why -that stop took place. +ignored. When the program stops again, GDB will act according to the +cause of that stop. @kindex silent If the first command specified is @samp{silent}, the usual message about @@ -1206,13 +1369,11 @@ The commands @samp{echo} and @samp{output} that allow you to print precisely controlled output are often useful in silent breakpoints. @xref{Output}. For example, here is how you could use breakpoint commands to print the -value of @code{x} at entry to @code{foo} whenever it is positive. We -assume that the newly created breakpoint is number 4; @samp{break} will -print the number that is assigned. +value of @code{x} at entry to @code{foo} whenever it is positive. @example break foo if x>0 -commands 4 +commands silent echo x is\040 output x @@ -1231,7 +1392,7 @@ produced. Here is an example: @example break 403 -commands 5 +commands silent set x = y + 4 cont @@ -1256,19 +1417,20 @@ condition 5 (x = y + 4), 0 @end example @noindent -is a condition expression (@xref{Expressions}) that will change @code{x} -as needed, then always have the value 0 so the program will not stop. -Loss of input is avoided here because break conditions are evaluated -without changing the terminal modes. When you want to have nontrivial -conditions for performing the side effects, the operators @samp{&&}, -@samp{||} and @samp{?@: @dots{} :@:} may be useful. +specifies a condition expression (@xref{Expressions}) that will change +@code{x} as needed, then always have the value 0 so the program will not +stop. Loss of input is avoided here because break conditions are +evaluated without changing the terminal modes. When you want to have +nontrivial conditions for performing the side effects, the operators +@samp{&&}, @samp{||} and @samp{?@dots{}:} may be useful. @node Error in Breakpoints,, Break Commands, Breakpoints @subsection ``Cannot Insert Breakpoints'' Error -Under some Unix systems, breakpoints cannot be used in a program if any -other process is running that program. Attempting to run or continue -the program with a breakpoint in this case will cause GDB to stop it. +Under some operating systems, breakpoints cannot be used in a program if +any other process is running that program. Attempting to run or +continue the program with a breakpoint in this case will cause GDB to +stop it. When this happens, you have three ways to proceed: @@ -1282,8 +1444,9 @@ Resume GDB and use the @samp{exec-file} command to specify that GDB should run the program under that name. Then start the program again. @item -Recompile the program so that the text is non-sharable (a.out format -OMAGIC). +Relink the program so that the text segment is nonsharable, using the +linker option @samp{-N}. The operating system limitation may not apply +to nonsharable executables. @end enumerate @node Continuing, Stepping, Breakpoints, Stopping @@ -1302,7 +1465,7 @@ If the program stopped at a breakpoint, the place to continue running is the address of the breakpoint. You might expect that continuing would just stop at the same breakpoint immediately. In fact, @samp{cont} takes special care to prevent that from happening. You do not need -to clear the breakpoint to proceed through it after stopping at it. +to delete the breakpoint to proceed through it after stopping at it. You can, however, specify an ignore-count for the breakpoint that the program stopped at, by means of an argument to the @samp{cont} command. @@ -1332,18 +1495,19 @@ stepping command specifies. @table @code @item step @kindex step -Proceed the program until control reaches a different line, then stop -it and return to the debugger. This command is abbreviated @samp{s}. +Continue running the program until control reaches a different line, +then stop it and return control to the debugger. This command is +abbreviated @samp{s}. -@item step @var{count} -Proceed as in @samp{step}, but do so @var{count} times. If a breakpoint -or a signal not related to stepping is reached before @var{count} steps, -stepping stops right away. - -This command may be given when control is within a routine for which +This command may be given when control is within a function for which there is no debugging information. In that case, execution will proceed -until control reaches a different routine, or is about to return from -this routine. An argument repeats this action. +until control reaches a different function, or is about to return from +this function. An argument repeats this action. + +@item step @var{count} +Continue running as in @samp{step}, but do so @var{count} times. If a +breakpoint is reached or a signal not related to stepping occurs before +@var{count} steps, stepping stops right away. @item next @kindex next @@ -1354,37 +1518,58 @@ different line of code at the stack level which was executing when the An argument is a repeat count, as in @samp{step}. -@samp{next} within a routine without debugging information acts as does +@samp{next} within a function without debugging information acts as does @samp{step}, but any function calls appearing within the code of the -routine are executed without stopping. +function are executed without stopping. @item finish @kindex finish -Continue running until just after the selected stack frame returns -(or until there is some other reason to stop, such as a fatal signal -or a breakpoint). Print value returned by the selected stack frame (if -any). +Continue running until just after the selected stack frame returns (or +until there is some other reason to stop, such as a fatal signal or a +breakpoint). Print value returned by the selected stack frame (if any). Contrast this with the @samp{return} command (@pxref{Returning}). @item until @kindex until -Proceed the program until control reaches a line greater than the current -line, then stop is and return to the debugger. Control is also returned to -the debugger if the program exits the current stack frame. Note that this -form of the command uses single stepping, and hence is slower than -@samp{until} with an argument. This command is abbreviated @samp{u}. +This command is used to avoid single stepping through a loop more than +once. It is like the @samp{next} command, except that when @samp{until} +encounters a jump, it automatically continues execution until the +program counter is greater than the address of the jump. + +This means that when you reach the end of a loop after single stepping +though it, @samp{until} will cause the program to continue execution +until the loop is exited. In contrast, a @samp{next} command at the end +of a loop will simply step back to the beginning of the loop, which +would force you to step through the next iteration. + +@samp{until} always stops the program if it attempts to exit the current +stack frame. + +@samp{until} may produce somewhat counterintuitive results if the order +of the source lines does not match the actual order of execution. For +example, in a typical C @code{for}-loop, the third expression in the +@code{for}-statement (the loop-step expression) is executed after the +statements in the body of the loop, but is written before them. +Therefore, the @samp{until} command would appear to step back to the +beginning of the loop when it advances to this expression. However, it +has not really done so, not in terms of the actual machine code. + +Note that @samp{until} with no argument works by means of single +instruction stepping, and hence is slower than @samp{until} with an +argument. @item until @var{location} -Proceed the program until either the specified location is reached, or the -current (innermost) stack frame returns. This form of the command uses -breakpoints, and hence is quicker than @samp{until} without an argument. +Continue running the program until either the specified location is +reached, or the current (innermost) stack frame returns. This form of +the command uses breakpoints, and hence is quicker than @samp{until} +without an argument. @item stepi @itemx si @kindex stepi @kindex si -Proceed one machine instruction, then stop and return to the debugger. +Execute one machine instruction, then stop and return to the debugger. It is often useful to do @samp{display/i $pc} when stepping by machine instructions. This will cause the next instruction to be executed to @@ -1396,7 +1581,7 @@ An argument is a repeat count, as in @samp{step}. @itemx ni @kindex nexti @kindex ni -Proceed one machine instruction, but if it is a subroutine call, +Execute one machine instruction, but if it is a subroutine call, proceed until the subroutine returns. An argument is a repeat count, as in @samp{next}. @@ -1449,10 +1634,12 @@ frame and describes it briefly as the @samp{frame} command does @section Stack Frames @cindex frame -The call stack is divided up into contiguous pieces called @dfn{frames}; -each frame is the data associated with one call to one function. The frame -contains the arguments given to the function, the function's local -variables, and the address at which the function is executing. +@cindex stack frame +The call stack is divided up into contiguous pieces called @dfn{stack +frames}, or @dfn{frames} for short; each frame is the data associated +with one call to one function. The frame contains the arguments given +to the function, the function's local variables, and the address at +which the function is executing. @cindex initial frame @cindex outermost frame @@ -1487,6 +1674,16 @@ frame using one set of GDB commands, and then other commands will operate on that frame. When your program stops, GDB automatically selects the innermost frame. +@cindex frameless execution +Some functions can be compiled to run without a frame reserved for them +on the stack. This is occasionally done with heavily used library +functions to save the frame setup time. GDB has limited facilities for +dealing with these function invocations; if the innermost function +invocation has no stack frame, GDB will give it a virtual stack frame of +0 and correctly allow tracing of the function call chain. Results are +undefined if a function invocation besides the innermost one is +frameless. + @node Backtrace, Selection, Frames, Stack @section Backtraces @@ -1498,6 +1695,8 @@ stack. @table @code @item backtrace @itemx bt +@kindex backtrace +@kindex bt Print a backtrace of the entire stack: one line per frame for all frames in the stack. @@ -1506,19 +1705,47 @@ character, normally @kbd{Control-C}. @item backtrace @var{n} @itemx bt @var{n} -Similar, but stop after @var{n} frames. +Similar, but print only the innermost @var{n} frames. @item backtrace @var{-n} @itemx bt @var{-n} -Similar, but print the outermost @var{n} frames instead of the -innermost. +Similar, but print only the outermost @var{n} frames. @end table -Each line in a backtrace shows the frame number, the program counter, the -function and its arguments, and the source file name and line number (if -known). The program counter is omitted if is the beginning of the code for -the source line. This is the same as the first of the two lines printed -when you select a frame. +@kindex where +@kindex info stack +The names @samp{where} and @samp{info stack} are additional aliases +for @samp{backtrace}. + +Every line in the backtrace shows the frame number, the function name +and the program counter value. + +If the function is in a source file whose symbol table data has been +fully read, the backtrace shows the source file name and line number, as +well as the arguments to the function. (The program counter value is +omitted if it is at the beginning of the code for that line number.) + +If the source file's symbol data has not been fully read, just scanned, +this extra information is replaced with an ellipsis. You can force the +symbol data for that frame's source file to be read by selecting the +frame. (@xref{Selection}). + +Here is an example of a backtrace. It was made with the command +@samp{bt 3}, so it shows the innermost three frames. + +@example +#0 rtx_equal_p (x=(rtx) 0x8e58c, y=(rtx) 0x1086c4) (/gp/rms/cc/rtlanal.c line 337) +#1 0x246b0 in expand_call (...) (...) +#2 0x21cfc in expand_expr (...) (...) +(More stack frames follow...) +@end example + +@noindent +The functions @code{expand_call} and @code{expand_expr} are in a file +whose symbol details have not been fully read. Full detail is available +for the function @code{rtx_equal_p}, which is in the file +@file{rtlanal.c}. Its arguments, named @code{x} and @code{y}, are shown +with their typed values. @node Selection, Frame Info, Backtrace, Stack @section Selecting a Frame @@ -1653,7 +1880,7 @@ printed; however, if the last line printed was a solitary line printed as part of displaying a stack frame (@pxref{Stack}), this prints ten lines centered around that line. -@item list @minus{} +@item list - Print ten lines just before the lines last printed. @end table @@ -1663,6 +1890,7 @@ than listing the same lines again. An exception is made for an argument of @samp{-}; that argument is preserved in repetition so that each repetition moves up in the file. +@cindex linespec In general, the @samp{list} command expects you to supply zero, one or two @dfn{linespecs}. Linespecs specify source lines; there are several ways of writing them but the effect is always to specify some source line. @@ -1685,7 +1913,7 @@ Print ten lines starting with @var{first}. @item list + Print ten lines just after the lines last printed. -@item list @minus{} +@item list - Print ten lines just before the lines last printed. @item list @@ -1695,7 +1923,7 @@ As described in the preceding table. Here are the ways of specifying a single source line---all the kinds of linespec. -@table @asis +@table @code @item @var{linenum} Specifies line @var{linenum} of the current source file. When a @samp{list} command has two linespecs, this refers to @@ -1707,7 +1935,7 @@ When used as the second linespec in a @samp{list} command that has two, this specifies the line @var{offset} lines down from the first linespec. -@item @minus{}@var{offset} +@item -@var{offset} Specifies the line @var{offset} lines before the last line printed. @item @var{filename}:@var{linenum} @@ -1740,7 +1968,7 @@ source line @var{linenum}. The default examine address for the @samp{x} command is changed to the starting address of the line, so that @samp{x/i} is sufficient to begin examining the machine code (@pxref{Memory}). Also, this address -is saved as the value of the convenience variable @samp{$_} +is saved as the value of the convenience variable @code{$_} (@pxref{Convenience Vars}). @end table @@ -1768,31 +1996,33 @@ this command with as little as @samp{rev}. @cindex source path @cindex directories for source files -Executable programs do not record the directories of the source files they -were compiled from, just the names. GDB remembers a list of directories to -search for source files; this is called the @dfn{source path}. Each time -GDB wants a source file, it tries all the directories in the list, in the -order they are present in the list, until it finds a file with the desired -name. +Executable programs do not record the directories of the source files +from which they were compiled, just the names. GDB remembers a list of +directories to search for source files; this is called the @dfn{source +path}. Each time GDB wants a source file, it tries all the directories +in the list, in the order they are present in the list, until it finds a +file with the desired name. @b{Note that the executable search path is +@i{not} used for this purpose. Neither is the current working +directory, unless it happens to be in the source path.} @kindex directory When you start GDB, its source path contains just the current working directory. To add other directories, use the @samp{directory} command. -@b{Note that the search path for executable files and the working directory -are @i{not} used for finding source files.} @table @code -@item directory @var{dirname} -Add directory @var{dirname} to the end of the source path. +@item directory @var{dirnames...} +Add directory @var{dirname} to the end of the source path. Several +directory names may be given to this command, separated by whitespace or +@samp{:}. @item directory Reset the source path to just the current working directory of GDB. This requires confirmation. -@samp{directory} with no argument can cause source files previously -found by GDB to be found in a different directory. To make this work -correctly, this command also clears out the tables GDB maintains -about the source files it has already found. +Since this command deletes directories from the search path, it may +change the directory in which a previously read source file will be +discovered. To make this work correctly, this command also clears out +the tables GDB maintains about the source files it has already found. @item info directories @kindex info directories @@ -1825,7 +2055,7 @@ directories you want in the source path. @cindex printing data @cindex examining data @kindex print -The usual way of examining data in your program is with the @samp{print} +The usual way to examine data in your program is with the @samp{print} command (abbreviated @samp{p}). It evaluates and prints the value of any valid expression of the language the program is written in (for now, C). You type @@ -1842,21 +2072,13 @@ A more low-level way of examining data is with the @samp{x} command. It examines data in memory at a specified address and prints it in a specified format. -GDB supports one command to modify the default format of displayed data: - -@table @samp -@item set array-max -@kindex set array-max -@samp{set array-max} sets the maximum number of elements of an array which -will be printed. This limit also applies to the display of strings. -@end table - @menu * Expressions:: Expressions that can be computed and printed. * Variables:: Using your program's variables in expressions. * Assignment:: Setting your program's variables. * Arrays:: Examining part of memory as an array. -* Formats:: Specifying formats for printing values. +* Format Options:: Controlling how structures and arrays are printed. +* Output formats:: Specifying formats for printing values. * Memory:: Examining memory explicitly. * Auto Display:: Printing certain expressions whenever program stops. * Value History:: Referring to values previously printed. @@ -1873,7 +2095,7 @@ Any kind of constant, variable or operator defined by the programming language you are using is legal in an expression in GDB. This includes conditional expressions, function calls, casts and string constants. It unfortunately does not include symbols defined by preprocessor -#define commands. +@code{#define} commands. Casts are supported in all languages, not just in C, because it is so useful to cast a number into a pointer so as to examine a structure @@ -1942,7 +2164,7 @@ you can specify any one of them using the colon-colon construct: @noindent Here @var{block} is the name of the source file whose variable you want. -@node Arrays, Formats, Variables, Data +@node Arrays, Format options, Variables, Data @section Artificial Arrays @cindex artificial array @@ -1977,8 +2199,91 @@ subscripting, and are coerced to pointers when used in expressions. (It would probably appear in an expression via the value history, after you had printed it out.) -@node Formats, Memory, Arrays, Data -@section Formats +@node Format options, Output formats, Arrays, Data +@section Format options + +@cindex format options +GDB provides a few ways to control how arrays and structures are +printed. + +@table @code +@item info format +@kindex info format +Display the current settings for the format options. + +@item set array-max @var{number-of-elements} +@kindex set array-max +If GDB is printing a large array, it will stop printing after it has +printed the number of elements set by the @samp{set array-max} command. +This limit also applies to the display of strings. + +@item set prettyprint on +@kindex set prettyprint +Cause GDB to print structures in an indented format with one member per +line, like this: + +@example +$1 = @{ + next = 0x0, + flags = @{ + sweet = 1, + sour = 1 + @}, + meat = 0x54 "Pork" +@} +@end example + +@item set prettyprint off +Cause GDB to print structures in a compact format, like this: + +@example +$1 = @{next = 0x0, flags = @{sweet = 1, sour = 1@}, meat = 0x54 "Pork"@} +@end example + +This is the default format. + +@item set unionprint on +@kindex set unionprint +Tell GDB to print unions which are contained in structures. This is the +default setting. +@item set unionprint off +Tell GDB not to print unions which are contained in structures. + +For example, given the declarations + +@example +typedef enum @{Tree, Bug@} Species; +typedef enum @{Big_tree, Acorn, Seedling@} Tree_forms; +typedef enum @{Caterpiller, Cocoon, Butterfly@} Bug_forms; + +struct thing @{ + Species it; + union @{ + Tree_forms tree; + Bug_forms bug; + @} form; +@}; + +struct thing foo = @{Tree, @{Acorn@}@}; +@end example + +@noindent +with @samp{set unionprint on} in effect @samp{p foo} would print + +@example +$1 = @{it = Tree, form = @{tree = Acorn, bug = Cocoon@}@} +@end example + +@noindent +and with @samp{set unionprint off} in effect it would print + +@example +$1 = @{it = Tree, form = @{...@}@} +@end example +@end table + +@node Output formats, Memory, Format options, Data +@section Output formats @cindex formatted output @cindex output formats @@ -2033,19 +2338,22 @@ To reprint the last value in the value history with a different format, you can use the @samp{print} command with just a format and no expression. For example, @samp{p/x} reprints the last value in hex. -@node Memory, Auto Display, Formats, Data +@node Memory, Auto Display, Output formats, Data @subsection Examining Memory @cindex examining memory @kindex x -The command @samp{x} (for `examine') can be used to examine memory under -explicit control of formats, without reference to the program's data types. +The command @samp{x} (for `examine') can be used to examine memory +without reference to the program's data types. The format in which you +wish to examine memory is instead explicitly specified. The allowable +formats are a superset of the formats described in the previous section. @samp{x} is followed by a slash and an output format specification, followed by an expression for an address. The expression need not have a pointer value (though it may); it is used as an integer, as the -address of a byte of memory. @xref{Expressions} for more information -on expressions. +address of a byte of memory. @xref{Expressions} for more information on +expressions. For example, @samp{x/4xw $sp} prints the four words of +memory above the stack pointer in hexadecimal. The output format in this case specifies both how big a unit of memory to examine and how to print the contents of that unit. It is done @@ -2068,7 +2376,7 @@ Many assemblers and cpu designers still use `word' for a 16-bit quantity, as a holdover from specific predecessor machines of the 1970's that really did use two-byte words. But more generally the term `word' has always referred to the size of quantity that a machine normally operates on and -stores in its registers. This is 32 bits for all the machines that GNU +stores in its registers. This is 32 bits for all the machines that GDB runs on. @item g @@ -2137,14 +2445,14 @@ You can examine several consecutive units of memory with one command by writing a repeat-count after the slash (before the format letters, if any). The repeat count must be a decimal integer. It has the same effect as repeating the @samp{x} command that many times except that the output may -be more compact with several units per line. +be more compact with several units per line. For example, @example x/10i $pc @end example @noindent -Prints ten instructions starting with the one to be executed next in the +prints ten instructions starting with the one to be executed next in the selected frame. After doing this, you could print another ten following instructions with @@ -2160,19 +2468,29 @@ in which the format and address are allowed to default. The addresses and contents printed by the @samp{x} command are not put in the value history because there is often too much of them and they would get in the way. Instead, GDB makes these values available for subsequent -use in expressions as values of the convenience variables @samp{$_} and -@samp{$__}. +use in expressions as values of the convenience variables @code{$_} and +@code{$__}. After an @samp{x} command, the last address examined is available for use -in expressions in the convenience variable @samp{$_}. The contents of that -address, as examined, are available in the convenience variable @samp{$__}. +in expressions in the convenience variable @code{$_}. The contents of that +address, as examined, are available in the convenience variable @code{$__}. If the @samp{x} command has a repeat count, the address and contents saved are from the last memory unit printed; this is not the same as the last address printed if several units were printed on the last line of output. +@kindex disassemble +The specialized command @samp{disassemble} is also provided to dump a +range of memory as machine instructions. The default memory range is +the function surrounding the program counter of the selected frame. A +single argument to this command is a program counter value; the function +surrounding this value will be dumped. Two arguments specify a range of +addresss (first inclusive, second exclusive) to be dumped. + @node Auto Display, Value History, Memory, Data @section Automatic Display +@cindex automatic display +@cindex display of expressions If you find that you want to print the value of an expression frequently (to see how it changes), you might want to add it to the @dfn{automatic @@ -2189,6 +2507,14 @@ The automatic display looks like this: @noindent showing item numbers, expressions and their current values. +If the expression refers to local variables, then it does not make sense +outside the lexical context for which it was set up. Such an expression +is printed only when execution is inside that lexical context. For +example, if you give the command @samp{display name} while inside a +function with an argument @code{name}, then this argument will be +displayed whenever the program stops inside that function, but not when +it stops elsewhere (since this argument doesn't exist elsewhere). + @table @code @item display @var{exp} @kindex display @@ -2207,15 +2533,16 @@ be examined each time the program stops. Examining means in effect doing @samp{x/@var{fmt} @var{addr}}. @xref{Memory}. @item undisplay @var{dnums}@dots{} -@kindex undisplay -@item delete display @var{dnums}@dots{} +@itemx delete display @var{dnums}@dots{} @kindex delete display +@kindex undisplay Remove item numbers @var{dnums} from the list of expressions to display. @item disable display @var{dnums}@dots{} @kindex disable display -Disable the display of item numbers @var{dnums}. A disabled display item -has no effect but is not forgotten. It may be later enabled. +Disable the display of item numbers @var{dnums}. A disabled display +item is not printed automatically, but is not forgotten. It may be +reenabled later. @item enable display @var{dnums}@dots{} @kindex enable display @@ -2228,8 +2555,11 @@ done when the program stops. @item info display @kindex info display -Print the list of expressions to display automatically, each one -with its item number, but without showing the values. +Print the list of expressions previously set up to display +automatically, each one with its item number, but without showing the +values. This includes disabled expressions, which are marked as such. +It also includes expressions which would not be displayed right now +because they refer to automatic variables not currently available. @end table @node Value History, Convenience Vars, Auto Display, Data @@ -2240,17 +2570,18 @@ Every value printed by the @samp{print} command is saved for the entire session in GDB's @dfn{value history} so that you can refer to it in other expressions. -@cindex $ -@cindex $$ +@cindex @code{$} +@cindex @code{$$} +@cindex history number The values printed are given @dfn{history numbers} for you to refer to them by. These are successive integers starting with 1. @samp{print} shows you -the history number assigned to a value by printing @samp{$@var{n} = } -before the value; here @var{n} is the history number. +the history number assigned to a value by printing @samp{$@var{num} = } +before the value; here @var{num} is the history number. To refer to any previous value, use @samp{$} followed by the value's history number. The output printed by @samp{print} is designed to remind -you of this. Just @samp{$} refers to the most recent value in the history, -and @samp{$$} refers to the value before that. +you of this. Just @code{$} refers to the most recent value in the history, +and @code{$$} refers to the value before that. For example, suppose you have just printed a pointer to a structure and want to see the contents of the structure. It suffices to type @@ -2260,16 +2591,17 @@ p *$ @end example If you have a chain of structures where the component @samp{next} points -to the next one, you can print the contents of the next one with +to the next one, you can print the contents of the next one with this: @example p *$.next @end example +@noindent It might be useful to repeat this command many times by typing @key{RET}. Note that the history records values, not expressions. If the value of -@code{x} is 4 and you type +@code{x} is 4 and you type this command: @example print x @@ -2278,17 +2610,20 @@ set x=5 @noindent then the value recorded in the value history by the @samp{print} command -remains 4 even though @code{x}'s value has changed. +remains 4 even though the value of @code{x} has changed. @table @code -@item info history -@kindex info history +@item info values +@kindex info values Print the last ten values in the value history, with their item numbers. This is like @samp{p $$9} repeated ten times, except that -@samp{info history} does not change the history. +@samp{info values} does not change the history. -@item info history @var{n} +@item info values @var{n} Print ten history values centered on history item number @var{n}. + +@item info values + +Print ten history values just after the values last printed. @end table @node Convenience Vars, Registers, Value History, Data @@ -2313,7 +2648,7 @@ set $foo = *object_ptr @end example @noindent -would save in @samp{$foo} the value contained in the object pointed to by +would save in @code{$foo} the value contained in the object pointed to by @code{object_ptr}. Using a convenience variable for the first time creates it; but its value @@ -2344,16 +2679,16 @@ print bar[$i++]->contents Some convenience variables are created automatically by GDB and given values likely to be useful. -@table @samp +@table @code @item $_ -The variable @samp{$_} is automatically set by the @samp{x} command to +The variable @code{$_} is automatically set by the @samp{x} command to the last address examined (@pxref{Memory}). Other commands which -provide a default address for @samp{x} to examine also set @samp{$_} +provide a default address for @samp{x} to examine also set @code{$_} to that address; these commands include @samp{info line} and @samp{info breakpoint}. @item $__ -The variable @samp{$__} is automatically set by the @samp{x} command +The variable @code{$__} is automatically set by the @samp{x} command to the value found in the last address examined. @end table @@ -2364,9 +2699,15 @@ to the value found in the last address examined. Machine register contents can be referred to in expressions as variables with names starting with @samp{$}. The names of registers are different for each machine; use @samp{info registers} to see the names used on your -machine. The names @samp{$pc} and @samp{$sp} are used on all machines for -the program counter register and the stack pointer. Often @samp{$fp} is -used for a register that contains a pointer to the current stack frame. +machine. The names @code{$pc} and @code{$sp} are used on all machines for +the program counter register and the stack pointer. Often @code{$fp} is +used for a register that contains a pointer to the current stack frame, +and @code{$ps} is used for a register that contains the processor +status. These standard register names may be available on your machine +even though the @code{info registers} command displays them with a +different name. For example, on the SPARC, @code{info registers} +displays the processor status register as @code{$psr} but you can also +refer to it as @code{$ps}. GDB always considers the contents of an ordinary register as an integer when the register is examined in this way. Some machines have special @@ -2379,7 +2720,7 @@ Some registers have distinct ``raw'' and ``virtual'' data formats. This means that the data format in which the register contents are saved by the operating system is not the same one that your program normally sees. For example, the registers of the 68881 floating point coprocessor are always -saved in ``extended'' format, but virtually all C programs expect to work with +saved in ``extended'' format, but all C programs expect to work with ``double'' format. In such cases, GDB normally works with the virtual format only (the format that makes sense for your program), but the @samp{info registers} command prints the data in both formats. @@ -2430,7 +2771,7 @@ set $sp += 4 @noindent The last is a way of removing one word from the stack, on machines where stacks grow downward in memory (most machines, nowadays). This assumes -that the innermost stack frame is selected. Setting @samp{$sp} is +that the innermost stack frame is selected. Setting @code{$sp} is not allowed when other stack frames are selected. @node Symbols, Altering, Data, Top @@ -2451,16 +2792,18 @@ assignments or function calls) inside it do not take place. @xref{Expressions}. @item whatis -Print the data type of @samp{$}, the last value in the value history. +Print the data type of @code{$}, the last value in the value history. @item info address @var{symbol} @kindex info address -Describe where the data for @var{symbol} is stored. For register -variables, this says which register. For other automatic variables, -this prints the stack-frame offset at which the variable is always -stored. Note the contrast with @samp{print &@var{symbol}}, which does -not work at all for register variables and for automatic variables -prints the exact address of the current instantiation of the variable. +Describe where the data for @var{symbol} is stored. For a register +variable, this says which register it is kept in. For a non-register +local variable, this prints the stack-frame offset at which the variable +is always stored. + +Note the contrast with @samp{print &@var{symbol}}, which does not work +at all for a register variables, and for a stack local variable prints +the exact address of the current instantiation of the variable. @item ptype @var{typename} @kindex ptype @@ -2488,11 +2831,11 @@ start with @samp{step}. @item info variables @kindex info variables Print the names and data types of all variables that are declared -outside of functions. +outside of functions (i.e., except for local variables). @item info variables @var{regexp} -Print the names and data types of all variables, declared outside of -functions, whose names contain a match for regular expression +Print the names and data types of all variables (except for local +variables) whose names contain a match for regular expression @var{regexp}. @item info types @@ -2504,17 +2847,15 @@ Print all data types that are defined in the program whose names contain a match for regular expression @var{regexp}. @item info methods -@item info methods @var{regexp} +@itemx info methods @var{regexp} @kindex info methods The @samp{info-methods} command permits the user to examine all defined -methods within C@code{++} program, or (with the @var{regexp} argument) a -specific set of methods found in the various C@code{++} classes. Many -C@code{++} classes which implement a large number of differently typed -methods implement a large number of methods as well. Thus, the -@samp{ptype} command can give the user a tremendous overdose of -information about what methods are associated with a given class. The -@samp{info-methods} command filters these methods do to only those -methods which match the regular-expression search key. +methods within C++ program, or (with the @var{regexp} argument) a +specific set of methods found in the various C++ classes. Many +C++ classes provide a large number of methods. Thus, the output +from the @samp{ptype} command can be overwhelming and hard to use. The +@samp{info-methods} command filters the methods, printing only those +which match the regular-expression @var{regexp}. @item printsyms @var{filename} @kindex printsyms @@ -2525,8 +2866,15 @@ file @var{filename}. @node Altering, Sequences, Symbols, Top @chapter Altering Execution -There are several ways to alter the execution of your program with GDB -commands. +Once you think you have find an error in the program, you might want to +find out for certain whether correcting the apparent error would lead to +correct results in the rest of the run. You can find the answer by +experiment, using the GDB features for altering execution of the +program. + +For example, you can store new values into variables or memory +locations, give the program a signal, restart it at a different address, +or even return prematurely from a function to its caller. @menu * Assignment:: Altering variable values or memory contents. @@ -2551,6 +2899,10 @@ print x=4 would store the value 4 into the variable @code{x}, and then print the value of the assignment expression (which is 4). +All the assignment operators of C are supported, including the +incrementation operators @samp{++} and @samp{--}, and combining +assignments such as @samp{+=} and @samp{<<=}. + @kindex set @kindex set variable If you are not interested in seeing the value of the assignment, use the @@ -2569,20 +2921,25 @@ freely store an integer value into a pointer variable or vice versa, and any structure can be converted to any other structure that is the same length or shorter. -In C, all the other assignment operators such as @samp{+=} and @samp{++} -are supported as well. - -To store into arbitrary places in memory, use the @samp{@{@dots{}@}} +To store values into arbitrary places in memory, use the @samp{@{@dots{}@}} construct to generate a value of specified type at a specified address -(@pxref{Expressions}). For example, +(@pxref{Expressions}). For example, @code{@{int@}0x83040} would refer +to memory location 0x83040 as an integer (which implies a certain size +and representation in memory), and @example set @{int@}0x83040 = 4 @end example +would store the value 4 into that memory location. + @node Jumping, Signaling, Assignment, Altering @section Continuing at a Different Address +Ordinarily, when you continue the program, you do so at the place where +it stopped, with the @samp{cont} command. You can instead continue at +an address of your own choosing, with the following commands: + @table @code @item jump @var{linenum} @kindex jump @@ -2593,27 +2950,43 @@ The @samp{jump} command does not change the current stack frame, or the stack pointer, or the contents of any memory location or any register other than the program counter. If line @var{linenum} is in a different function from the one currently executing, the results may -be wild if the two functions expect different patterns of arguments or +be bizarre if the two functions expect different patterns of arguments or of local variables. For this reason, the @samp{jump} command requests confirmation if the specified line is not in the function currently -executing. However, even wild results are predictable based on -changing the program counter. +executing. However, even bizarre results are predictable based on +careful study of the machine-language code of the program. @item jump *@var{address} Resume execution at the instruction at address @var{address}. @end table -A similar effect can be obtained by storing a new value into the register -@samp{$pc}, but not exactly the same. +You can get much the same effect as the @code{jump} command by storing a +new value into the register @code{$pc}. The difference is that this +does not start the program running; it only changes the address where it +@emph{will} run when it is continued. For example, @example set $pc = 0x485 @end example @noindent -specifies the address at which execution will resume, but does not resume -execution. That does not happen until you use the @samp{cont} command or a -stepping command (@pxref{Stepping}). +causes the next @samp{cont} command or stepping command to execute at +address 0x485, rather than at the address where the program stopped. +@xref{Stepping}. + +The most common occasion to use the @samp{jump} command is when you have +stepped across a function call with @code{next}, and found that the +return value is incorrect. If all the relevant data appeared correct +before the function call, the error is probably in the function that +just returned. + +In general, your next step would now be to rerun the program and execute +up to this function call, and then step into it to see where it goes +astray. But this may be time consuming. If the function did not have +significant side effects, you could get the same information by resuming +execution just before the function call and stepping through it. To do this, +first put a breakpoint on that function; then, use the @samp{jump} command +to continue on the line with the function call. @node Signaling, Returning, Jumping, Altering @section Giving the Program a Signal @@ -2621,13 +2994,14 @@ stepping command (@pxref{Stepping}). @table @code @item signal @var{signalnum} @kindex signal -Resume execution where the program stopped, but give it immediately -the signal number @var{signalnum}. - -Alternatively, if @var{signalnum} is zero, continue execution and give -no signal. This is useful when the program has received a signal -but you don't want the program to see that signal; the @samp{cont} command -would signal the program. +Resume execution where the program stopped, but give it immediately the +signal number @var{signalnum}. + +Alternatively, if @var{signalnum} is zero, continue execution without +giving a signal. This is useful when the program stopped on account of +a signal and would ordinary see the signal when resumed with the +@samp{cont} command; @samp{signal 0} causes it to resume without a +signal. @end table @node Returning,, Signaling, Altering @@ -2635,24 +3009,28 @@ would signal the program. @cindex returning from a function @kindex return -You can make any function call return immediately, using the @samp{return} -command. +You can cancel execution of a function call with the @samp{return} +command. This command has the effect of discarding the selected stack +frame (and all frames within it), so that control moves to the caller of +that function. You can think of this as making the discarded frame +return prematurely. First select the stack frame that you wish to return from -(@pxref{Selection}). Then type the @samp{return} command. If you wish to -specify the value to be returned, give that as an argument. +(@pxref{Selection}). Then type the @samp{return} command. If you wish +to specify the value to be returned, give that as an argument. This pops the selected stack frame (and any other frames inside of it), leaving its caller as the innermost remaining frame. That frame becomes selected. The specified value is stored in the registers used for returning values of functions. -The @samp{return} command does not resume execution; it leaves the program -stopped in the state that would exist if the function had just returned. -Contrast this with the @samp{finish} command (@pxref{Stepping}), which -resumes execution @i{until} the selected stack frame returns naturally. +The @samp{return} command does not resume execution; it leaves the +program stopped in the state that would exist if the function had just +returned. Contrast this with the @samp{finish} command +(@pxref{Stepping}), which resumes execution until the selected stack +frame returns @emph{naturally}. -@node Sequences, Emacs, Altering, Top +@node Sequences, Options, Altering, Top @chapter Canned Sequences of Commands GDB provides two ways to store sequences of commands for execution as a @@ -2668,7 +3046,7 @@ unit: user-defined commands and command files. @node Define, Command Files, Sequences, Sequences @section User-Defined Commands -@cindex user-defined commands +@cindex user-defined command A @dfn{user-defined command} is a sequence of GDB commands to which you assign a new name as a command. This is done with the @samp{define} command. @@ -2688,9 +3066,9 @@ commands is marked by a line containing @samp{end}. Give documentation to the user-defined command @var{commandname}. The command @var{commandname} must already be defined. This command reads lines of documentation just as @samp{define} reads the lines of the -command definition, ending with @samp{end}. After the @samp{document} command is finished, -@samp{help} on command @var{commandname} will print the documentation -you have specified. +command definition, ending with @samp{end}. After the @samp{document} +command is finished, @samp{help} on command @var{commandname} will print +the documentation you have specified. You may use the @samp{document} command again to change the documentation of a command. Redefining the command with @samp{define} @@ -2716,7 +3094,7 @@ command file does nothing; it does not mean to repeat the last command, as it would from the terminal. @cindex init file -@cindex .gdbinit +@cindex @file{.gdbinit} When GDB starts, it automatically executes its @dfn{init files}, command files named @file{.gdbinit}. GDB reads the init file (if any) in your home directory and then the init file (if any) in the current working @@ -2750,30 +3128,46 @@ exactly the output you want. @table @code @item echo @var{text} @kindex echo -Print @var{text}. Nonprinting characters can be included in -@var{text} using C escape sequences, such as @samp{\n} to print a -newline. @b{No newline will be printed unless you specify one.} +@comment I don't consider backslash-space a standard C escape sequence +@comment because it's not in ANSI. +Print @var{text}. Nonprinting characters can be included in @var{text} +using C escape sequences, such as @samp{\n} to print a newline. @b{No +newline will be printed unless you specify one.} In addition to the +standard C escape sequences a backslash followed by a space stands for a +space. This is useful for outputting a string with spaces at the +beginning or the end, since leading and trailing spaces are trimmed from +all arguments. Thus, to print @w{`` and foo = ''}, use the command +@w{``echo \ and foo = \ ''}. +@comment AAARGGG! How am I supposed to do @samp{ and foo = } and not +@comment have the spaces be invisible in TeX? + +A backslash at the end of @var{text} can be used, as in C, to continue +the command onto subsequent lines. For example, -A backslash at the end of @var{text} is ignored. It is useful for -outputting a string ending in spaces, since trailing spaces are -trimmed from all arguments. A backslash at the beginning preserves -leading spaces in the same way, because @samp{\ } as an escape -sequence stands for a space. Thus, to print @samp{ and foo = }, do +@example +echo This is some text\n\ +which is continued\n\ +onto several lines.\n +@end example + +produces the same output as @example -echo \ and foo = \ +echo This is some text\n +echo which is continued\n +echo onto several lines.\n @end example @item output @var{expression} @kindex output Print the value of @var{expression} and nothing but that value: no newlines, no @samp{$@var{nn} = }. The value is not entered in the -value history either. @xref{Expressions} for more information -on expressions. +value history either. @xref{Expressions} for more information on +expressions. @item output/@var{fmt} @var{expression} Print the value of @var{expression} in format @var{fmt}. -@xref{Formats}, for more information. +@xref{Output formats}, for more information. @item printf @var{string}, @var{expressions}@dots{} @kindex printf @@ -2796,19 +3190,101 @@ The only backslash-escape sequences that you can use in the string are the simple ones that consist of backslash followed by a letter. @end table -@node Emacs, Remote, Sequences, Top +@node Options, Emacs, Sequences, Top +@chapter Options and Arguments for GDB + +When you invoke GDB, you can specify arguments telling it what files to +operate on and what other things to do. + +@menu +* Mode Options:: Options controlling modes of operation. +* File Options:: Options to specify files (executable, coredump, commands) +* Other Arguments:: Any other arguments without options + also specify files. +@end menu + +@node Mode Options, File Options, Options, Options +@section Mode Options + +@table @samp +@item -nx +Do not execute commands from the init files @file{.gdbinit}. +Normally, the commands in these files are executed after all the +command options and arguments have been processed. @xref{Command +Files}. + +@item -q +``Quiet''. Do not print the usual introductory messages. + +@item -batch +Run in batch mode. Exit with code 0 after processing all the command +files specified with @samp{-x} (and @file{.gdbinit}, if not inhibited). +Exit with nonzero status if an error occurs in executing the GDB +commands in the command files. + +@item -fullname +This option is used when Emacs runs GDB as a subprocess. It tells GDB +to output the full file name and line number in a standard, +recognizable fashion each time a stack frame is displayed (which +includes each time the program stops). This recognizable format looks +like two @samp{\032} characters, followed by the file name, line number +and character position separated by colons, and a newline. The +Emacs-to-GDB interface program uses the two @samp{\032} characters as +a signal to display the source code for the frame. +@end table + +@node File Options, Other Arguments, Mode Options, Options +@section File-specifying Options + +All the options and command line arguments given are processed +in sequential order. The order makes a difference when the +@samp{-x} option is used. + +@table @samp +@item -s @var{file} +Read symbol table from file @var{file}. + +@item -e @var{file} +Use file @var{file} as the executable file to execute when +appropriate, and for examining pure data in conjunction with a core +dump. + +@item -se @var{file} +Read symbol table from file @var{file} and use it as the executable +file. + +@item -c @var{file} +Use file @var{file} as a core dump to examine. + +@item -x @var{file} +Execute GDB commands from file @var{file}. + +@item -d @var{directory} +Add @var{directory} to the path to search for source files. +@end table + +@node Other Arguments,, File Options, Options +@section Other Arguments + +If there are arguments to GDB that are not options or associated with +options, the first one specifies the symbol table and executable file name +(as if it were preceded by @samp{-se}) and the second one specifies a core +dump file name (as if it were preceded by @samp{-c}). + +@node Emacs, Remote, Options, Top @chapter Using GDB under GNU Emacs A special interface allows you to use GNU Emacs to view (and edit) the source files for the program you are debugging with GDB. -To use this interface, use the command @kbd{M-x gdb} in Emacs. -Give the executable file you want to debug as an argument. This -command starts a GDB process as a subprocess of Emacs, with input -and output through a newly created Emacs buffer. +To use this interface, use the command @kbd{M-x gdb} in Emacs. Give the +executable file you want to debug as an argument. This command starts +GDB as a subprocess of Emacs, with input and output through a newly +created Emacs buffer. -Using this GDB process is just like using GDB normally except for two things: +Using GDB under Emacs is just like using GDB normally except for two +things: @itemize @bullet @item @@ -2844,19 +3320,12 @@ calls, like the GDB @samp{next} command. @item M-i Execute one instruction, like the GDB @samp{stepi} command. -@item M-u -Move up one stack frame (and display that frame's source file in -Emacs), like the GDB @samp{up} command. - -@item M-d -Move down one stack frame (and display that frame's source file in -Emacs), like the GDB @samp{down} command. (This means that you cannot -delete words in the usual fashion in the GDB buffer; I am guessing you -won't often want to do that.) - @item C-c C-f Execute until exit from the selected stack frame, like the GDB @samp{finish} command. + +@item C-c C-c +Continue execution of the program, like the GDB @samp{cont} command. @end table In any source file, the Emacs command @kbd{C-x SPC} (@code{gdb-break}) @@ -2910,15 +3379,109 @@ step and continue the remote program. To resume the remote program and stop debugging it, use the @samp{detach} command. +@ignore +This material will be merged in when better Readline documentation +is done. + +@node GDB Readline, History Top ,Readline Top, Command Editing +@subsection GDB Readline + +You may control the behavior of command line editing in GDB with the +following commands: + +@table @code +@kindex set editing +@item set editing +@itemx set editing on +Enable command line editing (enabled by default). + +@item set editing off +Disable command line editing. + +@kindex set history file +@item set history file @var{filename} +Set the name of the GDB command history file to @var{filename}. This is +the file from which GDB will read an initial command history +list or to which it will write this list when it exits. This list is +accessed through history expansion or through the history +command editing characters listed below. This file defaults to the +value of the environmental variable @code{GDBHISTFILE}, or to +@code{./.gdb_history} if this variable is not set. + +@kindex set history write +@item set history write +@itemx set history write on +Enable the writing of the command history to the command history file +named above. This is enabled by default. + +@item set history write off +Disable the writing of the command history to the command history file. + +@kindex set history size +@item set history size @var{size} +Set the number of commands which GDB will keep in its history list. +This defaults to the value of the environmental variable +@code{HISTSIZE}, or to 256 if this variable is not set. + +@kindex info editing +@item info editing +Display the current settings relating to command line editing, and also +display the last ten commands in the command history. + +@item info editing @var{n} +Print ten commands centered on command number @var{n}. + +@item info editing + +Print ten commands just after the commands last printed. +@end table + +@node GDB History, , History Top, Command editing +@comment node-name, next, previous, up +Note that because of the additional meaning of @code{!} to GDB (as the +logical not operator in C), history expansion is off by default. If you +decide to enable history expansion with the @samp{set history expansion +on} command, you will need to follow @samp{!} with a space or a tab to +prevent it from being expanded. + +The commands to control history expansion are: + +@table @code + +@kindex set history expansion +@item set history expansion on +@itemx set history expansion +Enable history expansion. + +@item set history expansion off +Disable history expansion. History expansion is off by default. + +@end table +@end ignore + @node Commands, Concepts, Remote, Top @unnumbered Command Index @printindex ky -@node Concepts,, Commands, Top +@node Concepts, , Commands, Top @unnumbered Concept Index @printindex cp @contents @bye + + + + +Occasionally it is useful to execute a shell command from within GDB. +This can be done with the @samp{shell} command. + +@table @code +@item shell @var{shell command string} +@kindex shell +@cindex shell escape +Directs GDB to invoke an inferior shell to execute @var{shell command string}. +The environment variable @code{SHELL} is used if it exists, otherwise GDB +uses @samp{/bin/sh}. +@end table diff --git a/gdb/gdbcore.h b/gdb/gdbcore.h deleted file mode 100644 index b03e66c373..0000000000 --- a/gdb/gdbcore.h +++ /dev/null @@ -1,68 +0,0 @@ -/* Machine independent variables that describe the core file under GDB. - Copyright (C) 1986, 1987, 1989 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! -*/ - -/* 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; diff --git a/gdb/gld-pinsn.c b/gdb/gld-pinsn.c index 1567180e48..1ef4e7fba1 100644 --- a/gdb/gld-pinsn.c +++ b/gdb/gld-pinsn.c @@ -1,22 +1,21 @@ /* Print GOULD RISC instructions for GDB, the GNU debugger. - Copyright (C) 1986, 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! -*/ + 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 #include diff --git a/gdb/gould-dep.c b/gdb/gould-dep.c index c078ec1c32..79080c8f5e 100644 --- a/gdb/gould-dep.c +++ b/gdb/gould-dep.c @@ -1,22 +1,21 @@ /* Low level interface to ptrace, for GDB when running under Unix. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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" @@ -258,6 +257,7 @@ write_inferior_memory (memaddr, myaddr, len) /* Work with core dump and executable files, for GDB. This code would be in core.c if it weren't machine-dependent. */ +/* This should probably be deleted. */ /* Recognize COFF format systems because a.out.h defines AOUTHDR. */ #ifdef AOUTHDR #define COFF_FORMAT @@ -279,8 +279,10 @@ write_inferior_memory (memaddr, myaddr, len) #endif #ifndef COFF_FORMAT +#ifndef AOUTHDR #define AOUTHDR struct exec #endif +#endif extern char *sys_siglist[]; @@ -384,6 +386,9 @@ core_file_command (filename, from_tty) 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); @@ -472,6 +477,9 @@ exec_file_command (filename, from_tty) if (filename) { + filename = tilde_expand (filename); + make_cleanup (free, filename); + execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, &execfile); if (execchan < 0) diff --git a/gdb/hp-include/a.out.h b/gdb/hp-include/a.out.h index 85d427542c..87e72199d7 100644 --- a/gdb/hp-include/a.out.h +++ b/gdb/hp-include/a.out.h @@ -1,132 +1,79 @@ /* Special version of for use under hp-ux. - Copyright (C) 1988 Free Software Foundation, Inc. */ + Copyright (C) 1988 Free Software Foundation, Inc. + + This file 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 file 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 file; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* The `exec' structure and overall layout must be close to HP's when we are running on an HP system, otherwise we will not be able to execute the resulting file. */ /* Allow this file to be included twice. */ -#ifndef EXEC_PAGESIZE +#ifndef __GNU_EXEC_MACROS__ struct exec - { - unsigned short a_machtype; /* machine type */ - unsigned short a_magic; /* magic number */ - unsigned long a_spare1; - unsigned long a_spare2; - unsigned long a_text; /* size of text segment */ - unsigned long a_data; /* size of data segment */ - unsigned long a_bss; /* size of bss segment */ - unsigned long a_trsize; /* text relocation size */ - unsigned long a_drsize; /* data relocation size */ - unsigned long a_spare3; /* HP = pascal interface size */ - unsigned long a_spare4; /* HP = symbol table size */ - unsigned long a_spare5; /* HP = debug name table size */ - unsigned long a_entry; /* entry point */ - unsigned long a_spare6; /* HP = source line table size */ - unsigned long a_spare7; /* HP = value table size */ - unsigned long a_syms; /* symbol table size */ - unsigned long a_spare8; - }; - -#define OMAGIC 0x107 -#define NMAGIC 0x108 -#define ZMAGIC 0x10B - -#define N_BADTYPE(x) \ - ((((x) . a_magic) != OMAGIC) \ - && (((x) . a_magic) != NMAGIC) \ - && (((x) . a_magic) != ZMAGIC)) +{ + unsigned short a_machtype; /* machine type */ + unsigned short a_magic; /* magic number */ + unsigned long a_spare1; + unsigned long a_spare2; + unsigned long a_text; /* length of text, in bytes */ + unsigned long a_data; /* length of data, in bytes */ + unsigned long a_bss; /* length of uninitialized data area for file, in bytes */ + unsigned long a_trsize; /* length of relocation info for text, in bytes */ + unsigned long a_drsize; /* length of relocation info for data, in bytes */ + unsigned long a_spare3; /* HP = pascal interface size */ + unsigned long a_spare4; /* HP = symbol table size */ + unsigned long a_spare5; /* HP = debug name table size */ + unsigned long a_entry; /* start address */ + unsigned long a_spare6; /* HP = source line table size */ + unsigned long a_spare7; /* HP = value table size */ + unsigned long a_syms; /* length of symbol table data in file, in bytes */ + unsigned long a_spare8; +}; + +/* Tell a.out.gnu.h not to define `struct exec'. */ +#define __STRUCT_EXEC_OVERRIDE__ + +#include "../a.out.gnu.h" + +#undef N_MAGIC +#undef N_MACHTYPE +#undef N_FLAGS +#undef N_SET_INFO +#undef N_SET_MAGIC +#undef N_SET_MACHTYPE +#undef N_SET_FLAGS + +#define N_MAGIC(exec) ((exec) . a_magic) +#define N_MACHTYPE(exec) ((exec) . a_machtype) +#define N_SET_MAGIC(exec, magic) (((exec) . a_magic) = (magic)) +#define N_SET_MACHTYPE(exec, machtype) (((exec) . a_machtype) = (machtype)) + +#undef N_BADMAG +#define N_BADMAG(x) ((_N_BADMAG (x)) || (_N_BADMACH (x))) + +#define _N_BADMACH(x) \ +(((N_MACHTYPE (x)) != HP9000S200_ID) && \ + ((N_MACHTYPE (x)) != HP98x6_ID)) #define HP98x6_ID 0x20A #define HP9000S200_ID 0x20C -#define N_BADMACH(x) \ - ((((x) . a_machtype) != HP9000S200_ID) \ - && (((x) . a_machtype) != HP98x6_ID)) - -#define N_BADMAG(x) ((N_BADTYPE (x)) || (N_BADMACH (x))) - -#define EXEC_PAGESIZE 0x1000 - -#define EXEC_ALIGN(offset) \ - (((offset) + (EXEC_PAGESIZE - 1)) & (~ (EXEC_PAGESIZE - 1))) - -#define N_TXTOFF(x) \ - ((((x) . a_magic) == ZMAGIC) \ - ? (EXEC_ALIGN (sizeof (struct exec))) \ - : (sizeof (struct exec))) - -#define N_DATOFF(x) \ - ((((x) . a_magic) == ZMAGIC) \ - ? ((EXEC_ALIGN (sizeof (struct exec))) \ - + (EXEC_ALIGN ((x) . a_text))) \ - : ((sizeof (struct exec)) + ((x) . a_text))) - -#define N_TROFF(x) \ - ((((x) . a_magic) == ZMAGIC) \ - ? ((EXEC_ALIGN (sizeof (struct exec))) \ - + (EXEC_ALIGN ((x) . a_text)) \ - + (EXEC_ALIGN ((x) . a_data))) \ - : ((sizeof (struct exec)) + ((x) . a_text) + ((x) . a_data))) - -#define N_SYMOFF(x) ((N_TROFF (x)) + ((x) . a_trsize) + ((x) . a_drsize)) - -#define N_STROFF(x) ((N_SYMOFF (x)) + ((x) . a_syms)) - -/* Macros which take exec structures as arguments and tell where the - various pieces will be loaded. */ - -#define N_TXTADDR(x) 0 - -#define N_DATADDR(x) \ - ((((x) . a_magic) == OMAGIC) \ - ? ((x) . a_text) \ - : (EXEC_ALIGN ((x) . a_text))) - -#define N_BSSADDR(x) ((N_DATADDR (x)) + ((x) . a_data)) - -struct relocation_info - { - long r_address; /* address which is relocated */ - unsigned int - r_symbolnum : 24, /* local symbol ordinal */ - r_pcrel : 1, /* was relocated pc relative already */ - r_length : 2, /* 0=byte, 1=word, 2=long */ - r_extern : 1, /* does not include value of sym referenced */ - : 4; /* nothing, yet */ - }; - -struct nlist - { - union - { - char *n_name; /* for use when in-core */ - long n_strx; /* index into file string table */ - } n_un; - unsigned char n_type; /* type flag (N_TEXT,..) */ - char n_other; /* unused */ - short n_desc; /* see */ - unsigned long n_value; /* value of symbol (or sdb offset) */ - }; - -/* Simple values for n_type. */ -#define N_UNDF 0x00 /* undefined */ -#define N_ABS 0x02 /* absolute */ -#define N_TEXT 0x04 /* text */ -#define N_DATA 0x06 /* data */ -#define N_BSS 0x08 /* bss */ -#define N_COMM 0x12 /* common (internal to ld) */ -#define N_FN 0x1F /* file name symbol */ - -#define N_EXT 0x01 /* external bit, or'ed in */ -#define N_TYPE 0x1E /* mask for all the type bits */ - -/* dbx entries have some of the N_STAB bits set. - These are given in */ -#define N_STAB 0xE0 /* if any of these bits set, a dbx symbol */ - -/* Format for namelist values. */ -#define N_FORMAT "%08x" - -#endif /* EXEC_PAGESIZE */ +#undef _N_HDROFF +#define _N_HDROFF(x) (SEGMENT_SIZE - (sizeof (struct exec))) + +#define SEGMENT_SIZE 0x1000 + +#endif /* __GNU_EXEC_MACROS__ */ diff --git a/gdb/hp-include/stab.def b/gdb/hp-include/stab.def new file mode 100644 index 0000000000..b81cda4bdc --- /dev/null +++ b/gdb/hp-include/stab.def @@ -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") diff --git a/gdb/hp-include/stab.h b/gdb/hp-include/stab.h index 9741fdce9d..77f2d411ce 100644 --- a/gdb/hp-include/stab.h +++ b/gdb/hp-include/stab.h @@ -1,47 +1,16 @@ -/* @(#)stab.h 1.1 86/07/07 SMI; from UCB X.X XX/XX/XX */ +#ifndef __GNU_STAB__ +/* Indicate the GNU stab.h is in use. */ -/* IF YOU ADD DEFINITIONS, ADD THEM TO nm.c as well */ -/* - * This file gives definitions supplementing - * for permanent symbol table entries. - * These must have one of the N_STAB bits on, - * and are subject to relocation according to the masks in . - */ -/* - * for symbolic debugger, sdb(1): - */ -#define N_GSYM 0x20 /* global symbol: name,,0,type,0 */ -#define N_FNAME 0x22 /* procedure name (f77 kludge): name,,0 */ -#define N_FUN 0x24 /* procedure: name,,0,linenumber,address */ -#define N_STSYM 0x26 /* static symbol: name,,0,type,address */ -#define N_LCSYM 0x28 /* .lcomm symbol: name,,0,type,address */ -#define N_MAIN 0x2a /* name of main routine : name,,0,0,0 */ -#define N_RSYM 0x40 /* register sym: name,,0,type,register */ -#define N_SLINE 0x44 /* src line: 0,,0,linenumber,address */ -#define N_SSYM 0x60 /* structure elt: name,,0,type,struct_offset */ -#define N_SO 0x64 /* source file name: name,,0,0,address */ -#define N_LSYM 0x80 /* local sym: name,,0,type,offset */ -#define N_BINCL 0x82 /* header file: name,,0,0,0 */ -#define N_SOL 0x84 /* #included file name: name,,0,0,address */ -#define N_PSYM 0xa0 /* parameter: name,,0,type,offset */ -#define N_EINCL 0xa2 /* end of include file */ -#define N_ENTRY 0xa4 /* alternate entry: name,linenumber,address */ -#define N_LBRAC 0xc0 /* left bracket: 0,,0,nesting level,address */ -#define N_EXCL 0xc2 /* excluded include file */ -#define N_RBRAC 0xe0 /* right bracket: 0,,0,nesting level,address */ -#define N_BCOMM 0xe2 /* begin common: name,, */ -#define N_ECOMM 0xe4 /* end common: name,, */ -#define N_ECOML 0xe8 /* end common (local name): ,,address */ -#define N_LENG 0xfe /* second stab entry with length information */ +#define __GNU_STAB__ -/* - * for the berkeley pascal compiler, pc(1): - */ -#define N_PC 0x30 /* global pascal symbol: name,,0,subtype,line */ +#define __define_stab(NAME, CODE, STRING) NAME=CODE, -/* - * for modula-2 compiler only - */ -#define N_M2C 0x42 /* compilation unit stab */ -#define N_SCOPE 0xc4 /* scope information */ +enum __stab_debug_code +{ +#include "stab.def" +}; + +#undef __define_stab + +#endif /* __GNU_STAB_ */ diff --git a/gdb/hp-include/sys/fcntl.h b/gdb/hp-include/sys/fcntl.h index 6d94600925..7523510c74 100644 --- a/gdb/hp-include/sys/fcntl.h +++ b/gdb/hp-include/sys/fcntl.h @@ -1,73 +1,4 @@ -/* @(#)fcntl.h 1.3 86/07/16 SMI; from UCB 5.1 85/05/30 */ -/* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. The Berkeley software License Agreement - * specifies the terms and conditions for redistribution. - */ - -#ifndef __FCNTL_HEADER__ -#define __FCNTL_HEADER__ - -/* - * Flag values accessible to open(2) and fcntl(2) - * (The first three can only be set by open) - */ -#define O_RDONLY 0 -#define O_WRONLY 1 -#define O_RDWR 2 -#define O_NDELAY FNDELAY /* Non-blocking I/O */ -#define O_APPEND FAPPEND /* append (writes guaranteed at the end) */ -#define O_CREAT FCREAT /* open with file create */ -#define O_TRUNC FTRUNC /* open with truncation */ -#define O_EXCL FEXCL /* error on create if file exists */ - -/* flags for F_GETFL, F_SETFL-- needed by */ -#define FNDELAY 00004 /* non-blocking reads */ -#define FAPPEND 00010 /* append on each write */ -#define FASYNC 00100 /* signal pgrp when data ready */ -#define FCREAT 01000 /* create if nonexistant */ -#define FTRUNC 02000 /* truncate to zero length */ -#define FEXCL 04000 /* error if already created */ - -/* fcntl(2) requests */ -#define F_DUPFD 0 /* Duplicate fildes */ -#define F_GETFD 1 /* Get fildes flags */ -#define F_SETFD 2 /* Set fildes flags */ -#define F_GETFL 3 /* Get file flags */ -#define F_SETFL 4 /* Set file flags */ -#define F_GETOWN 5 /* Get owner */ -#define F_SETOWN 6 /* Set owner */ -#define F_GETLK 7 /* Get record-locking information */ -#define F_SETLK 8 /* Set or Clear a record-lock (Non-Blocking) */ -#define F_SETLKW 9 /* Set or Clear a record-lock (Blocking) */ - -/* access(2) requests */ -#define F_OK 0 /* does file exist */ -#define X_OK 1 /* is it executable by caller */ -#define W_OK 2 /* writable by caller */ -#define R_OK 4 /* readable by caller */ - -/* System-V record-locking options */ -/* lockf(2) requests */ -#define F_ULOCK 0 /* Unlock a previously locked region */ -#define F_LOCK 1 /* Lock a region for exclusive use */ -#define F_TLOCK 2 /* Test and lock a region for exclusive use */ -#define F_TEST 3 /* Test a region for other processes locks */ - -/* fcntl(2) flags (l_type field of flock structure) */ -#define F_RDLCK 1 /* read lock */ -#define F_WRLCK 2 /* write lock */ -#define F_UNLCK 3 /* remove lock(s) */ - - -/* file segment locking set data type - information passed to system by user */ -struct flock { - short l_type; /* F_RDLCK, F_WRLCK, or F_UNLCK */ - short l_whence; /* flag to choose starting offset */ - long l_start; /* relative offset, in bytes */ - long l_len; /* length, in bytes; 0 means lock to EOF */ - short l_pid; /* returned with F_GETLK */ - short l_xxx; /* reserved for future use */ -}; - -#endif !__FCNTL_HEADER__ +/* The GNU programs do #include + but on HPUX that file is just fcntl.h. + This "redirects" the #include to the proper directory. */ +#include diff --git a/gdb/hp300bsd-dep.c b/gdb/hp300bsd-dep.c new file mode 100644 index 0000000000..d04977c8fe --- /dev/null +++ b/gdb/hp300bsd-dep.c @@ -0,0 +1,556 @@ +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! +*/ + +#include "defs.h" +#include "param.h" +#include "frame.h" +#include "inferior.h" + +#ifdef USG +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef COFF_ENCAPSULATE +#include "a.out.encap.h" +#else +#include +#endif +#ifndef N_SET_MAGIC +#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val)) +#endif +#include +#include +#include + +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 (PT_KILL, 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 (PT_KILL, 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 ? PT_STEP : PT_CONTINUE, 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 (PT_READ_U, 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 (PT_READ_U, 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]; + extern char registers[]; + register int i; + + struct user u; + unsigned int offset = (char *) &u.u_ar0 - (char *) &u; + offset = ptrace (PT_READ_U, inferior_pid, offset, 0) - KERNEL_U_ADDR; + + if (regno >= 0) + { + regaddr = register_addr (regno, offset); + for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int)) + { + errno = 0; + ptrace (PT_WRITE_U, inferior_pid, regaddr, + *(int *) ®isters[REGISTER_BYTE (regno) + i]); + if (errno != 0) + { + sprintf (buf, "writing register number %d(%d)", regno, i); + perror_with_name (buf); + } + regaddr += sizeof(int); + } + } + else for (regno = 0; regno < NUM_REGS; regno++) + { + regaddr = register_addr (regno, offset); + for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int)) + { + errno = 0; + ptrace (PT_WRITE_U, inferior_pid, regaddr, + *(int *) ®isters[REGISTER_BYTE (regno) + i]); + if (errno != 0) + { + sprintf (buf, "writing register number %d(%d)", regno, i); + perror_with_name (buf); + } + regaddr += sizeof(int); + } + } +} + +/* 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 (remote_debugging) + buffer[i] = remote_fetch_word (addr); + else + buffer[i] = ptrace (PT_READ_I, 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) + buffer[0] = remote_fetch_word (addr); + else + buffer[0] = ptrace (PT_READ_I, inferior_pid, addr, 0); + + if (count > 1) + { + if (remote_debugging) + buffer[count - 1] + = remote_fetch_word (addr + (count - 1) * sizeof (int)); + else + buffer[count - 1] + = ptrace (PT_READ_I, 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; + if (remote_debugging) + remote_store_word (addr, buffer[i]); + else + ptrace (PT_WRITE_I, 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. */ + +/* Recognize COFF format systems because a.out.h defines AOUTHDR. */ +#ifdef AOUTHDR +#define COFF_FORMAT +#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 */ + +/* 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 +#define AOUTHDR struct exec +#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; + + int reg_offset; + + val = myread (corechan, &u, sizeof u); + if (val < 0) + perror_with_name (filename); + 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); + reg_offset = (int) u.u_ar0 - 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) + perror_with_name (filename); + + val = myread (corechan, buf, sizeof buf); + if (val < 0) + perror_with_name (filename); + 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) < 0) + error ("\"%s\": can't read text section header", execfile); + + if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections) < 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; + + fstat (execchan, &st_exec); + 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); +} diff --git a/gdb/hp9k320-dep.c b/gdb/hp9k320-dep.c index 2774303cf2..09876ca1bb 100644 --- a/gdb/hp9k320-dep.c +++ b/gdb/hp9k320-dep.c @@ -1,22 +1,21 @@ /* Low level interface to ptrace, for GDB when running under Unix. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc. + +This file is part of GDB. -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. +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. -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. +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. -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! -*/ +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" @@ -46,8 +45,8 @@ extern int errno; 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; + call_ptrace (request, pid, arg3, arg4) +int request, pid, arg3, arg4; { return ptrace (request, pid, arg3, arg4); } @@ -80,9 +79,9 @@ kill_inferior_fast () If SIGNAL is nonzero, give it that signal. */ void -resume (step, signal) - int step; - int signal; + resume (step, signal) +int step; +int signal; { errno = 0; if (remote_debugging) @@ -101,16 +100,16 @@ resume (step, signal) - KERNEL_U_ADDR) static void -fetch_inferior_register (regno, regaddr) - register int regno; - register unsigned int regaddr; + fetch_inferior_register (regno, regaddr) +register int regno; +register unsigned int regaddr; { #ifndef HPUX_VERSION_5 if (regno == PS_REGNUM) { union { int i; short s[2]; } ps_val; int regval; - + ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0)); regval = ps_val.s[0]; supply_register (regno, ®val); @@ -120,7 +119,7 @@ fetch_inferior_register (regno, regaddr) { char buf[MAX_REGISTER_RAW_SIZE]; register int i; - + for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int)) { *(int *) &buf[i] = ptrace (PT_RUAREA, inferior_pid, regaddr, 0); @@ -132,10 +131,10 @@ fetch_inferior_register (regno, regaddr) } static void -store_inferior_register_1 (regno, regaddr, value) - int regno; - unsigned int regaddr; - int value; + store_inferior_register_1 (regno, regaddr, value) +int regno; +unsigned int regaddr; +int value; { errno = 0; ptrace (PT_WUAREA, inferior_pid, regaddr, value); @@ -145,7 +144,7 @@ store_inferior_register_1 (regno, regaddr, value) if (errno != 0) { char string_buf[64]; - + sprintf (string_buf, "writing register number %d", regno); perror_with_name (string_buf); } @@ -154,15 +153,15 @@ store_inferior_register_1 (regno, regaddr, value) } static void -store_inferior_register (regno, regaddr) - register int regno; - register unsigned int regaddr; + store_inferior_register (regno, regaddr) +register int regno; +register unsigned int regaddr; { #ifndef HPUX_VERSION_5 if (regno == PS_REGNUM) { union { int i; short s[2]; } ps_val; - + ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0)); ps_val.s[0] = (read_register (regno)); store_inferior_register_1 (regno, regaddr, ps_val.i); @@ -173,7 +172,7 @@ store_inferior_register (regno, regaddr) char buf[MAX_REGISTER_RAW_SIZE]; register int i; extern char registers[]; - + for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int)) { store_inferior_register_1 @@ -186,17 +185,23 @@ store_inferior_register (regno, regaddr) } void -fetch_inferior_registers () + fetch_inferior_registers () { struct user u; register int regno; register unsigned int ar0_offset; - - ar0_offset = (INFERIOR_AR0 (u)); - for (regno = 0; (regno < FP0_REGNUM); regno++) - fetch_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno))); - for (; (regno < NUM_REGS); regno++) - fetch_inferior_register (regno, (FP_REGISTER_ADDR (u, regno))); + extern char registers[]; + + if (remote_debugging) + remote_fetch_registers (registers); + else + { + ar0_offset = (INFERIOR_AR0 (u)); + for (regno = 0; (regno < FP0_REGNUM); regno++) + fetch_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno))); + for (; (regno < NUM_REGS); regno++) + fetch_inferior_register (regno, (FP_REGISTER_ADDR (u, regno))); + } } /* Store our register values back into the inferior. @@ -208,24 +213,30 @@ store_inferior_registers (regno) { struct user u; register unsigned int ar0_offset; + extern char registers[]; - if (regno >= FP0_REGNUM) - { - store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno))); - return; - } - - ar0_offset = (INFERIOR_AR0 (u)); - if (regno >= 0) + if (remote_debugging) + remote_store_registers (registers); + else { - store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno))); - return; + if (regno >= FP0_REGNUM) + { + store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno))); + return; + } + + ar0_offset = (INFERIOR_AR0 (u)); + if (regno >= 0) + { + store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno))); + return; + } + + for (regno = 0; (regno < FP0_REGNUM); regno++) + store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno))); + for (; (regno < NUM_REGS); regno++) + store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno))); } - - for (regno = 0; (regno < FP0_REGNUM); regno++) - store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno))); - for (; (regno < NUM_REGS); regno++) - store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno))); return; } @@ -336,6 +347,7 @@ write_inferior_memory (memaddr, myaddr, len) /* Work with core dump and executable files, for GDB. This code would be in core.c if it weren't machine-dependent. */ +/* This should probably be deleted. */ /* Recognize COFF format systems because a.out.h defines AOUTHDR. */ #ifdef AOUTHDR #define COFF_FORMAT @@ -363,8 +375,10 @@ write_inferior_memory (memaddr, myaddr, len) #endif #ifndef COFF_FORMAT +#ifndef AOUTHDR #define AOUTHDR struct exec #endif +#endif extern char *sys_siglist[]; @@ -468,6 +482,9 @@ core_file_command (filename, from_tty) 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); @@ -571,6 +588,9 @@ exec_file_command (filename, from_tty) if (filename) { + filename = tilde_expand (filename); + make_cleanup (free, filename); + execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, &execfile); if (execchan < 0) diff --git a/gdb/i386-dep.c b/gdb/i386-dep.c index 23a553a042..09e7e0d28c 100644 --- a/gdb/i386-dep.c +++ b/gdb/i386-dep.c @@ -1,22 +1,21 @@ /* Low level interface to ptrace, for GDB when running on the Intel 386. - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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" @@ -283,8 +282,10 @@ write_inferior_memory (memaddr, myaddr, len) to reduce conditionals later. */ #ifndef COFF_FORMAT +#ifndef AOUTHDR #define AOUTHDR struct exec #endif +#endif extern char *sys_siglist[]; @@ -388,6 +389,9 @@ core_file_command (filename, from_tty) 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); @@ -478,6 +482,9 @@ exec_file_command (filename, from_tty) if (filename) { + filename = tilde_expand (filename); + make_cleanup (free, filename); + execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, &execfile); if (execchan < 0) @@ -1129,7 +1136,11 @@ print_387_status (status, ep) if (ep->r3) printf ("warning: reserved3 is 0x%x\n", ep->r3); } - + +#ifndef U_FPSTATE +#define U_FPSTATE(u) u.u_fpstate +#endif + i386_float_info () { struct user u; /* just for address computations */ @@ -1171,7 +1182,7 @@ i386_float_info () return; } - uaddr = (char *)&u.u_fpstate - (char *)&u; + uaddr = (char *)&U_FPSTATE(u) - (char *)&u; if (have_inferior_p ()) { int *ip; diff --git a/gdb/i386-pinsn.c b/gdb/i386-pinsn.c index 437d44d91b..649baaf56b 100644 --- a/gdb/i386-pinsn.c +++ b/gdb/i386-pinsn.c @@ -1,22 +1,21 @@ /* Print i386 instructions for GDB, the GNU debugger. - Copyright (C) 1988 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! -*/ + 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. */ /* * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu) diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 086e1f3401..254c9612be 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -1,22 +1,21 @@ /* Memory-access and commands for inferior process, for GDB. - Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1988, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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" @@ -126,8 +125,9 @@ set_args_command (args) } void -tty_command (file) +tty_command (file, from_tty) char *file; + int from_tty; { if (file == 0) error_no_arg ("terminal name for running target process"); @@ -160,13 +160,13 @@ Start it from the beginning? ")) kill_inferior (); } + exec_file = (char *) get_exec_file (1); + if (remote_debugging) { - free (allargs); if (from_tty) { - printf ("Starting program: %s%s\n", - exec_file, inferior_args); + printf ("Starting program: %s\n", exec_file); fflush (stdout); } } @@ -175,7 +175,6 @@ Start it from the beginning? ")) if (args) set_args_command (args); - exec_file = (char *) get_exec_file (1); if (from_tty) { printf ("Starting program: %s%s\n", @@ -566,7 +565,7 @@ finish_command (arg, from_tty) value_type)); printf ("Value returned is $%d = ", record_latest_value (val)); - value_print (val, stdout, 0); + value_print (val, stdout, 0, Val_no_prettyprint); putchar ('\n'); } } @@ -674,11 +673,18 @@ set_environment_command (arg) } static void -unset_environment_command (var) +unset_environment_command (var, from_tty) char *var; + int from_tty; { if (var == 0) - error_no_arg ("environment variable"); + /* If there is no argument, delete all environment variables. + Ask for confirmation if reading from the terminal. */ + if (!from_tty || query ("Delete all environment variables? ")) + { + free_environ (inferior_environ); + inferior_environ = make_environ (); + } unset_in_environ (inferior_environ, var); } @@ -694,25 +700,48 @@ read_memory_integer (memaddr, len) short sbuf; int ibuf; long lbuf; + int result_err; + extern int sys_nerr; + extern char *sys_errlist[]; if (len == sizeof (char)) { - read_memory (memaddr, &cbuf, len); + result_err = read_memory (memaddr, &cbuf, len); + if (result_err) + error ("Error reading memory address 0x%x: %s (%d).", + memaddr, (result_err < sys_nerr ? + sys_errlist[result_err] : + "uknown error"), result_err); return cbuf; } if (len == sizeof (short)) { - read_memory (memaddr, &sbuf, len); + result_err = read_memory (memaddr, &sbuf, len); + if (result_err) + error ("Error reading memory address 0x%x: %s (%d).", + memaddr, (result_err < sys_nerr ? + sys_errlist[result_err] : + "uknown error"), result_err); return sbuf; } if (len == sizeof (int)) { - read_memory (memaddr, &ibuf, len); + result_err = read_memory (memaddr, &ibuf, len); + if (result_err) + error ("Error reading memory address 0x%x: %s (%d).", + memaddr, (result_err < sys_nerr ? + sys_errlist[result_err] : + "uknown error"), result_err); return ibuf; } if (len == sizeof (lbuf)) { - read_memory (memaddr, &lbuf, len); + result_err = read_memory (memaddr, &lbuf, len); + if (result_err) + error ("Error reading memory address 0x%x: %s (%d).", + memaddr, (result_err < sys_nerr ? + sys_errlist[result_err] : + "uknown error"), result_err); return lbuf; } error ("Cannot handle integers of %d bytes.", len); @@ -763,7 +792,8 @@ registers_info (addr_exp) } } else - printf ("Reg\tContents\n\n"); + printf_filtered ( + "Register Contents (relative to selected stack frame)\n\n"); for (i = 0; i < NUM_REGS; i++) { @@ -774,34 +804,26 @@ registers_info (addr_exp) if (addr_exp != 0 && i != regnum) continue; - /* On machines with lots of registers, pause every 16 lines - so user can read the output. */ - if (addr_exp == 0 && i > 0 && i % 16 == 0) - { - printf ("--Type Return to print more--"); - fflush (stdout); - gdb_read_line (0, 0); - } - /* Get the data in raw format, then convert also to virtual format. */ read_relative_register_raw_bytes (i, raw_buffer); REGISTER_CONVERT_TO_VIRTUAL (i, raw_buffer, virtual_buffer); - printf ("%s\t", reg_names[i]); + fputs_filtered (reg_names[i], stdout); + print_spaces_filtered (15 - strlen (reg_names[i]), stdout); /* If virtual format is floating, print it that way. */ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT && ! INVALID_FLOAT (virtual_buffer, REGISTER_VIRTUAL_SIZE (i))) val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, - stdout, 0, 1); + stdout, 0, 1, 0, Val_pretty_default); /* Else if virtual format is too long for printf, print in hex a byte at a time. */ else if (REGISTER_VIRTUAL_SIZE (i) > sizeof (long)) { register int j; - printf ("0x"); + printf_filtered ("0x"); for (j = 0; j < REGISTER_VIRTUAL_SIZE (i); j++) - printf ("%02x", virtual_buffer[j]); + printf_filtered ("%02x", virtual_buffer[j]); } /* Else print as integer in hex and in decimal. */ else @@ -810,9 +832,9 @@ registers_info (addr_exp) bcopy (virtual_buffer, &val, sizeof (long)); if (val == 0) - printf ("0"); + printf_filtered ("0"); else - printf ("0x%08x %d", val, val); + printf_filtered ("0x%08x %d", val, val); } /* If register has different raw and virtual formats, @@ -822,18 +844,20 @@ registers_info (addr_exp) { register int j; - printf (" (raw 0x"); + printf_filtered (" (raw 0x"); for (j = 0; j < REGISTER_RAW_SIZE (i); j++) - printf ("%02x", raw_buffer[j]); - printf (")"); + printf_filtered ("%02x", raw_buffer[j]); + printf_filtered (")"); } - printf ("\n"); + printf_filtered ("\n"); } - - printf ("Contents are relative to selected stack frame.\n"); } #ifdef ATTACH_DETACH +#define PROCESS_ATTACH_ALLOWED 1 +#else +#define PROCESS_ATTACH_ALLOWED 0 +#endif /* * TODO: * Should save/restore the tty state since it might be that the @@ -841,6 +865,7 @@ registers_info (addr_exp) * the tty in some state other than what we want. If it's running * on another terminal or without a terminal, then saving and * restoring the tty state is a harmless no-op. + * This only needs to be done if we are attaching to a process. */ /* @@ -862,14 +887,18 @@ attach_command (args, from_tty) dont_repeat(); if (!args) - error_no_arg ("process-id to attach"); + error_no_arg ("process-id or device file to attach"); while (*args == ' ' || *args == '\t') args++; if (args[0] == '/') remote = 1; else +#ifndef ATTACH_DETACH + error ("Can't attach to a process on this machine."); +#else pid = atoi (args); +#endif if (inferior_pid) { @@ -891,13 +920,17 @@ attach_command (args, from_tty) fflush (stdout); } +#ifdef ATTACH_DETACH if (remote) { +#endif remote_open (args, from_tty); start_remote (); +#ifdef ATTACH_DETACH } else attach_program (pid); +#endif } /* @@ -918,24 +951,36 @@ detach_command (args, from_tty) { int signal = 0; - if (!inferior_pid) - error ("Not currently tracing a program\n"); - if (from_tty) +#ifdef ATTACH_DETACH + if (inferior_pid) { - char *exec_file = (char *)get_exec_file (0); - if (exec_file == 0) - exec_file = ""; - printf ("Detaching program: %s pid %d\n", - exec_file, inferior_pid); - fflush (stdout); + if (from_tty) + { + char *exec_file = (char *)get_exec_file (0); + if (exec_file == 0) + exec_file = ""; + printf ("Detaching program: %s pid %d\n", + exec_file, inferior_pid); + fflush (stdout); + } + if (args) + signal = atoi (args); + + detach (signal); + inferior_pid = 0; } - if (args) - signal = atoi (args); + else +#endif + { + if (!remote_debugging) + error ("Not currently attached to subsidiary or remote process."); - detach (signal); - inferior_pid = 0; + if (args) + error ("Argument given to \"detach\" when remotely debugging."); + + remote_close (from_tty); + } } -#endif /* ATTACH_DETACH */ /* ARGUSUED */ static void @@ -983,15 +1028,25 @@ This does not affect the program until the next \"run\" command.", #ifdef ATTACH_DETACH add_com ("attach", class_run, attach_command, "Attach to a process that was started up outside of GDB.\n\ -To do this, you must have permission to send the process a signal.\n\ -And it must have the same effective uid as the debugger.\n\n\ +This command may take as argument a process id or a device file.\n\ +For a process id, you must have permission to send the process a signal,\n\ +and it must have the same effective uid as the debugger.\n\ +For a device file, the file must be a connection to a remote debug server.\n\n\ Before using \"attach\", you must use the \"exec-file\" command\n\ to specify the program running in the process,\n\ and the \"symbol-file\" command to load its symbol table."); +#else + add_com ("attach", class_run, attach_command, + "Attach to a process that was started up outside of GDB.\n\ +This commands takes as an argument the name of a device file.\n\ +This file must be a connection to a remote debug server.\n\n\ +Before using \"attach\", you must use the \"exec-file\" command\n\ +to specify the program running in the process,\n\ +and the \"symbol-file\" command to load its symbol table."); +#endif add_com ("detach", class_run, detach_command, "Detach the process previously attached.\n\ The process is no longer traced and continues its execution."); -#endif /* ATTACH_DETACH */ add_com ("signal", class_run, signal_command, "Continue program giving it signal number SIGNUMBER."); @@ -1043,9 +1098,9 @@ then the same breakpoint won't break until the Nth time it is reached."); "Start debugged program. You may specify arguments to give it.\n\ Args may include \"*\", or \"[...]\"; they are expanded using \"sh\".\n\ Input and output redirection with \">\", \"<\", or \">>\" are also allowed.\n\n\ -With no arguments, uses arguments last specified (with \"run\" or \"set-args\".\n\ +With no arguments, uses arguments last specified (with \"run\" or \"set args\".\n\ To cancel previous arguments and run with no arguments,\n\ -use \"set-args\" without arguments."); +use \"set args\" without arguments."); add_com_alias ("r", "run", class_run, 1); add_info ("registers", registers_info, diff --git a/gdb/inferior.h b/gdb/inferior.h index c2d6e950ab..900b7390d7 100644 --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -1,23 +1,22 @@ /* Variables that describe the inferior process running under GDB: Where it is, why it stopped, and how to step it. - Copyright (C) 1986 Free Software Foundation, Inc. + Copyright (C) 1986, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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 @@ -62,9 +61,12 @@ extern char *inferior_io_terminal; 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; @@ -127,5 +129,4 @@ extern char stop_registers[REGISTER_BYTES]; extern int pc_changed; - long read_memory_integer (); diff --git a/gdb/inflow.c b/gdb/inflow.c index 19da9960f2..c72b754d75 100644 --- a/gdb/inflow.c +++ b/gdb/inflow.c @@ -1,22 +1,22 @@ /* Low level interface to ptrace, for GDB when running under Unix. - Copyright (C) 1986, 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! -*/ + 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 "frame.h" @@ -70,7 +70,7 @@ static TERMINAL sg_ours; static int tflags_inferior; static int tflags_ours; -#ifdef TIOCGETC +#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) static struct tchars tc_inferior; static struct tchars tc_ours; #endif @@ -78,7 +78,7 @@ static struct tchars tc_ours; #ifdef TIOCGLTC static struct ltchars ltc_inferior; static struct ltchars ltc_ours; -#endif /* TIOCGLTC */ +#endif #ifdef TIOCLGET static int lmode_inferior; @@ -114,7 +114,7 @@ terminal_init_inferior () sg_inferior = sg_ours; tflags_inferior = tflags_ours; -#ifdef TIOCGETC +#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) tc_inferior = tc_ours; #endif @@ -147,7 +147,8 @@ terminal_inferior () fcntl (0, F_SETFL, tflags_inferior); fcntl (0, F_SETFL, tflags_inferior); ioctl (0, TIOCSETN, &sg_inferior); -#ifdef TIOCGETC + +#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) ioctl (0, TIOCSETC, &tc_inferior); #endif #ifdef TIOCGLTC @@ -211,7 +212,7 @@ terminal_ours_1 (output_only) terminal_is_ours = 1; #ifdef TIOCGPGRP - osigttou = signal (SIGTTOU, SIG_IGN); + osigttou = (int (*) ()) signal (SIGTTOU, SIG_IGN); ioctl (0, TIOCGPGRP, &pgrp_inferior); ioctl (0, TIOCSPGRP, &pgrp_ours); @@ -225,7 +226,7 @@ terminal_ours_1 (output_only) tflags_inferior = fcntl (0, F_GETFL, 0); ioctl (0, TIOCGETP, &sg_inferior); -#ifdef TIOCGETC +#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) ioctl (0, TIOCGETC, &tc_inferior); #endif #ifdef TIOCGLTC @@ -250,7 +251,7 @@ terminal_ours_1 (output_only) fcntl (0, F_SETFL, tflags_ours); ioctl (0, TIOCSETN, &sg_ours); -#ifdef TIOCGETC +#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) ioctl (0, TIOCSETC, &tc_ours); #endif #ifdef TIOCGLTC @@ -260,7 +261,6 @@ terminal_ours_1 (output_only) ioctl (0, TIOCLSET, &lmode_ours); #endif - #ifdef HAVE_TERMIO sg_ours.c_lflag |= ICANON; #else /* not HAVE_TERMIO */ @@ -275,47 +275,47 @@ term_status_command () if (remote_debugging) { - printf ("No terminal status when remote debugging.\n"); + printf_filtered ("No terminal status when remote debugging.\n"); return; } - printf ("Inferior's terminal status (currently saved by GDB):\n"); + printf_filtered ("Inferior's terminal status (currently saved by GDB):\n"); #ifdef HAVE_TERMIO - printf ("fcntl flags = 0x%x, c_iflag = 0x%x, c_oflag = 0x%x,\n", + 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 ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n", + 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 ("c_cc: "); + printf_filtered ("c_cc: "); for (i = 0; (i < NCC); i += 1) - printf ("0x%x ", sg_inferior.c_cc[i]); - printf ("\n"); + printf_filtered ("0x%x ", sg_inferior.c_cc[i]); + printf_filtered ("\n"); #else /* not HAVE_TERMIO */ - printf ("fcntl flags = 0x%x, sgttyb.sg_flags = 0x%x, owner pid = %d.\n", + 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 */ -#ifdef TIOCGETC - printf ("tchars: "); +#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) + printf_filtered ("tchars: "); for (i = 0; i < sizeof (struct tchars); i++) - printf ("0x%x ", ((char *)&tc_inferior)[i]); - printf ("\n"); + printf_filtered ("0x%x ", ((char *)&tc_inferior)[i]); + printf_filtered ("\n"); #endif #ifdef TIOCGLTC - printf ("ltchars: "); + printf_filtered ("ltchars: "); for (i = 0; i < sizeof (struct ltchars); i++) - printf ("0x%x ", ((char *)<c_inferior)[i]); - printf ("\n"); + printf_filtered ("0x%x ", ((char *)<c_inferior)[i]); + printf_filtered ("\n"); ioctl (0, TIOCSLTC, <c_ours); #endif - + #ifdef TIOCLGET - printf ("lmode: %x\n", lmode_inferior); + printf_filtered ("lmode: %x\n", lmode_inferior); #endif } @@ -342,10 +342,15 @@ new_tty (ttyname) if (tty == -1) _exit(1); - dup2(tty, 0); - dup2(tty, 1); - dup2(tty, 2); - close(tty); + /* 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. @@ -380,9 +385,14 @@ create_inferior (allargs, env) /* 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 ("fork"); + perror_with_name ("vfork"); if (pid == 0) { @@ -407,6 +417,10 @@ create_inferior (allargs, env) 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); @@ -420,6 +434,10 @@ create_inferior (allargs, env) fflush (stderr); _exit (0177); } + +#ifdef CREATE_INFERIOR_HOOK + CREATE_INFERIOR_HOOK (pid); +#endif return pid; } @@ -443,11 +461,13 @@ inferior_died () inferior_pid = 0; attach_flag = 0; mark_breakpoints_out (); - select_frame ( (FRAME) 0, -1); + 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); } static void @@ -494,7 +514,7 @@ Report which ones can be written."); ioctl (0, TIOCGETP, &sg_ours); fcntl (0, F_GETFL, tflags_ours); -#ifdef TIOCGETC +#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) ioctl (0, TIOCGETC, &tc_ours); #endif #ifdef TIOCGLTC diff --git a/gdb/infrun.c b/gdb/infrun.c index d08a1bf094..66b964c869 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -1,22 +1,21 @@ /* Start and stop the inferior process, for GDB. - Copyright (C) 1986, 1987, 1988 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! -*/ + 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. */ /* Notes on the algorithm used in wait_for_inferior to determine if we just did a subroutine call when stepping. We have the following @@ -134,12 +133,8 @@ anyone else from sharing it farther. Help stamp out software hoarding! #include #endif -/* The idiots at Apple only define X_OK if POSIX is defined. Fuck 'em. */ -#ifndef X_OK -#define X_OK 1 /* Execute permission for access() */ -#endif - #ifdef UMAX_PTRACE +#include #include #include #endif /* UMAX_PTRACE */ @@ -436,6 +431,7 @@ attach_program (pid) clear_proceed_status (); stop_after_attach = 1; /*proceed (-1, 0, -2);*/ + terminal_inferior (); wait_for_inferior (); normal_stop (); } @@ -458,23 +454,26 @@ wait_for_inferior () int random_signal; CORE_ADDR stop_sp, prev_sp; CORE_ADDR prev_func_start, stop_func_start; + char *prev_func_name, *stop_func_name; CORE_ADDR prologue_pc; int stop_step_resume_break; CORE_ADDR step_resume_break_sp; int newmisc; int newfun_pc; - struct symbol *newfun; struct symtab_and_line sal; int prev_pc; extern CORE_ADDR text_end; + int remove_breakpoints_on_following_step = 0; prev_pc = read_pc (); - prev_func_start = get_pc_function_start (prev_pc) + FUNCTION_START_OFFSET; + (void) find_pc_partial_function (prev_pc, &prev_func_name, + &prev_func_start); + prev_func_start += FUNCTION_START_OFFSET; prev_sp = read_register (SP_REGNUM); while (1) { - /* Clean up saved state that will become invalid */ + /* Clean up saved state that will become invalid. */ pc_changed = 0; flush_cached_frames (); @@ -487,7 +486,7 @@ wait_for_inferior () continue; } - /* See if the process still exists; clean up if it doesn't. */ + /* See if the process still exists; clean up if it doesn't. */ if (WIFEXITED (w)) { terminal_ours_for_output (); @@ -498,8 +497,8 @@ wait_for_inferior () fflush (stdout); inferior_died (); #ifdef NO_SINGLE_STEP - one_stepped = 0; /* Clear single_step state since proc gone */ -#endif /* NO_SINGLE_STEP */ + one_stepped = 0; +#endif stop_print_frame = 0; break; } @@ -517,42 +516,29 @@ wait_for_inferior () printf ("The inferior process no longer exists.\n"); fflush (stdout); #ifdef NO_SINGLE_STEP - one_stepped = 0; /* Clear single_step state since proc gone */ -#endif /* NO_SINGLE_STEP */ + one_stepped = 0; +#endif break; } - + #ifdef NO_SINGLE_STEP if (one_stepped) single_step (0); /* This actually cleans up the ss */ #endif /* NO_SINGLE_STEP */ - + fetch_inferior_registers (); stop_pc = read_pc (); set_current_frame ( create_new_frame (read_register (FP_REGNUM), read_pc ())); -#ifdef CONVEX_PTRACE - /* pop frame stored by user-mode trap, if present */ - if (stop_pc == BREAK_TRAP_ADDR) - { - POP_FRAME; - stop_pc = read_pc () - 2; - write_register (PC_REGNUM, stop_pc); -#ifdef NPC_REGNUM - write_register (NPC_REGNUM, stop_pc + 4); -#endif - pc_changed = 0; - } - else if (stop_pc > STACK_END_ADDR) - { - POP_FRAME; - stop_pc = read_pc (); - } -#endif /* CONVEX_PTRACE */ + stop_frame_address = FRAME_FP (get_current_frame ()); stop_sp = read_register (SP_REGNUM); - stop_func_start = - get_pc_function_start (stop_pc) + FUNCTION_START_OFFSET; + stop_func_start = 0; + /* Don't care about return value; stop_func_start will be 0 + if it doesn't work. */ + (void) find_pc_partial_function (stop_pc, &stop_func_name, + &stop_func_start); + stop_func_start += FUNCTION_START_OFFSET; another_trap = 0; stop_breakpoint = 0; stop_step = 0; @@ -562,30 +548,28 @@ wait_for_inferior () random_signal = 0; stopped_by_random_signal = 0; breakpoints_failed = 0; - + /* Look at the cause of the stop, and decide what to do. The alternatives are: 1) break; to really stop and return to the debugger, 2) drop through to start up again - (set another_trap to 1 to single step once) + (set another_trap to 1 to single step once) 3) set random_signal to 1, and the decision between 1 and 2 - will be made according to the signal handling tables. */ - + will be made according to the signal handling tables. */ + stop_signal = WSTOPSIG (w); - + /* First, distinguish signals caused by the debugger from signals that have to do with the program's own actions. Note that breakpoint insns may cause SIGTRAP or SIGILL or SIGEMT, depending on the operating system version. Here we detect when a SIGILL or SIGEMT is really a breakpoint and change it to SIGTRAP. */ - + if (stop_signal == SIGTRAP -#ifndef CONVEX_PTRACE || (breakpoints_inserted && (stop_signal == SIGILL || stop_signal == SIGEMT)) -#endif /* not CONVEX_PTRACE */ || stop_after_attach) { if (stop_signal == SIGTRAP && stop_after_trap) @@ -614,43 +598,44 @@ wait_for_inferior () && step_range_end && !step_resume_break_address)) #endif /* DECR_PC_AFTER_BREAK not zero */ { - /* For condition exprs. */ - select_frame (get_current_frame (), 0); - stop_breakpoint = - breakpoint_stop_status (stop_pc, stop_frame_address); - /* Following in case break condition called a - function. */ - stop_print_frame = 1; - if (stop_breakpoint && DECR_PC_AFTER_BREAK) + /* See if we stopped at the special breakpoint for + stepping over a subroutine call. */ + if (stop_pc - DECR_PC_AFTER_BREAK + == step_resume_break_address) { - stop_pc -= DECR_PC_AFTER_BREAK; - write_register (PC_REGNUM, stop_pc); -#ifdef NPC_REGNUM - write_register (NPC_REGNUM, stop_pc + 4); -#endif - pc_changed = 0; + stop_step_resume_break = 1; + if (DECR_PC_AFTER_BREAK) + { + stop_pc -= DECR_PC_AFTER_BREAK; + write_register (PC_REGNUM, stop_pc); + pc_changed = 0; + } } - } - /* See if we stopped at the special breakpoint for - stepping over a subroutine call. */ - if (stop_pc - DECR_PC_AFTER_BREAK - == step_resume_break_address) - { - stop_step_resume_break = 1; - if (DECR_PC_AFTER_BREAK) + else { - stop_pc -= DECR_PC_AFTER_BREAK; - write_register (PC_REGNUM, stop_pc); - pc_changed = 0; + stop_breakpoint = + breakpoint_stop_status (stop_pc, stop_frame_address); + /* Following in case break condition called a + function. */ + stop_print_frame = 1; + if (stop_breakpoint && DECR_PC_AFTER_BREAK) + { + stop_pc -= DECR_PC_AFTER_BREAK; + write_register (PC_REGNUM, stop_pc); +#ifdef NPC_REGNUM + write_register (NPC_REGNUM, stop_pc + 4); +#endif + pc_changed = 0; + } } } } - + if (stop_signal == SIGTRAP) random_signal = !(stop_breakpoint || trap_expected || stop_step_resume_break -#ifndef CONVEX_PTRACE +#ifndef CANNOT_EXECUTE_STACK || (stop_sp INNER_THAN stop_pc && stop_pc INNER_THAN stop_frame_address) #else @@ -662,11 +647,11 @@ wait_for_inferior () random_signal = !(stop_breakpoint || stop_step_resume_break -#ifdef news800 +#ifdef sony_news || (stop_sp INNER_THAN stop_pc && stop_pc INNER_THAN stop_frame_address) #endif - + ); if (!random_signal) stop_signal = SIGTRAP; @@ -674,18 +659,18 @@ wait_for_inferior () } else random_signal = 1; - + /* For the program's own signals, act according to the signal handling tables. */ - + if (random_signal && !(running_in_shell && stop_signal == SIGSEGV)) { /* Signal not for debugging purposes. */ int printed = 0; - + stopped_by_random_signal = 1; - + if (stop_signal >= NSIG || signal_print[stop_signal]) { @@ -694,8 +679,8 @@ wait_for_inferior () printf ("\nProgram received signal %d, %s\n", stop_signal, stop_signal < NSIG - ? sys_siglist[stop_signal] - : "(undocumented)"); + ? sys_siglist[stop_signal] + : "(undocumented)"); fflush (stdout); } if (stop_signal >= NSIG @@ -706,9 +691,9 @@ wait_for_inferior () else if (printed) terminal_inferior (); } - + /* Handle cases caused by hitting a breakpoint. */ - + if (!random_signal && (stop_breakpoint || stop_step_resume_break)) { @@ -743,20 +728,14 @@ wait_for_inferior () the stack pointer doesn't have to change if it the bp was set in a routine without a frame (pc can be stored in some other window). - + The removal of the sp test is to allow calls to alloca. Nasty things were happening. Oh, well, gdb can only handle one level deep of lack of frame pointer. */ if (stop_step_resume_break && (step_frame_address == 0 - || (stop_frame_address == step_frame_address -#if 0 -#ifndef HAVE_REGISTER_WINDOWS - && step_resume_break_sp INNER_THAN stop_sp -#endif -#endif - ))) + || (stop_frame_address == step_frame_address))) { remove_step_breakpoint (); step_resume_break_address = 0; @@ -770,32 +749,31 @@ wait_for_inferior () breakpoints_inserted = 0; another_trap = 1; } - + /* We come here if we hit a breakpoint but should not stop for it. Possibly we also were stepping and should stop for that. So fall through and test for stepping. But, if not stepping, do not stop. */ } - + /* If this is the breakpoint at the end of a stack dummy, just stop silently. */ -#ifndef CONVEX_PTRACE +#ifndef CANNOT_EXECUTE_STACK if (stop_sp INNER_THAN stop_pc && stop_pc INNER_THAN stop_frame_address) #else - /* "stack" dummy must be in text segment for Convex Unix */ - if (stop_pc == text_end - 2) + if (stop_pc == text_end - 2) #endif - { - stop_print_frame = 0; - stop_stack_dummy = 1; -#ifdef HP9K320 - trap_expected_after_continue = 1; + { + stop_print_frame = 0; + stop_stack_dummy = 1; +#ifdef HP_OS_BUG + trap_expected_after_continue = 1; #endif - break; - } - + break; + } + if (step_resume_break_address) /* Having a step-resume breakpoint overrides anything else having to do with stepping commands until @@ -812,7 +790,7 @@ wait_for_inferior () just changed, we've stepped outside */ && !(stop_pc == step_range_start && stop_frame_address - && (stop_sp != prev_sp + && (stop_sp INNER_THAN prev_sp || stop_frame_address != step_frame_address))) { /* Don't step through the return from a function @@ -823,7 +801,7 @@ wait_for_inferior () break; } } - + /* We stepped out of the stepping range. See if that was due to a subroutine call that we should proceed to the end of. */ else if (!random_signal && step_range_end) @@ -834,16 +812,35 @@ wait_for_inferior () SKIP_PROLOGUE (prologue_pc); } - /* ==> See comments at top of file on this algorithm. <==*/ + /* Did we just take a signal? */ + if (stop_func_name && !strcmp ("_sigtramp", stop_func_name) + && (!prev_func_name || strcmp ("_sigtramp", prev_func_name))) + { + /* We've just taken a signal; go until we are back to + the point where we took it and one more. */ + step_resume_break_address = prev_pc; + step_resume_break_duplicate = + breakpoint_here_p (step_resume_break_address); + step_resume_break_sp = stop_sp; + if (breakpoints_inserted) + insert_step_breakpoint (); + /* Make sure that the stepping range gets us past + that instruction. */ + if (step_range_end == 1) + step_range_end = (step_range_start = prev_pc) + 1; + remove_breakpoints_on_following_step = 1; + } - if (stop_pc == stop_func_start + /* ==> See comments at top of file on this algorithm. <==*/ + + else if (stop_pc == stop_func_start && (stop_func_start != prev_func_start || prologue_pc != stop_func_start || stop_sp != prev_sp)) { - newfun = find_pc_function (stop_pc); /* It's a subroutine call */ - if (step_over_calls > 0 || (step_over_calls && newfun == 0)) + if (step_over_calls > 0 + || (step_over_calls && find_pc_function (stop_pc) == 0)) { /* A subroutine call has happened. */ /* Set a special breakpoint after the return */ @@ -867,7 +864,7 @@ wait_for_inferior () /* If the prologue ends in the middle of a source line, continue to the end of that source line. Otherwise, just go to end of prologue. */ -#ifdef convex +#ifdef PROLOGUE_FIRSTLINE_OVERLAP /* no, don't either. It skips any code that's legitimately on the first line. */ #else @@ -925,6 +922,7 @@ wait_for_inferior () original pc would not have been at the start of a function. */ + prev_func_name = stop_func_name; prev_sp = stop_sp; /* If we did not do break;, it means we should keep @@ -947,6 +945,15 @@ wait_for_inferior () { resume (0, SIGSEGV); } + else if (trap_expected && stop_signal != SIGTRAP) + { + /* We took a signal which we are supposed to pass through to + the inferior and we haven't yet gotten our trap. Simply + continue. */ + resume ((step_range_end && !step_resume_break_address) + || trap_expected, + stop_signal); + } else { /* Here, we are not awaiting another exec to get @@ -954,7 +961,16 @@ wait_for_inferior () Insert breakpoints now, unless we are trying to one-proceed past a breakpoint. */ running_in_shell = 0; - if (!breakpoints_inserted && !another_trap) + /* If we've just finished a special step resume and we don't + want to hit a breakpoint, pull em out. */ + if (!step_resume_break_address && + remove_breakpoints_on_following_step) + { + remove_breakpoints_on_following_step = 0; + remove_breakpoints (); + breakpoints_inserted = 0; + } + else if (!breakpoints_inserted && !another_trap) { insert_step_breakpoint (); breakpoints_failed = insert_breakpoints (); @@ -985,10 +1001,6 @@ wait_for_inferior () BREAKPOINTS_FAILED nonzero means stop was due to error attempting to insert breakpoints. */ -/* FIXME, normal_stop is ALWAYS called immediately after wait_for_inferior. - They should probably be merged into a single function, since that - would avoid numerous tests (e.g. of inferior_pid). */ - static void normal_stop () { @@ -1029,7 +1041,7 @@ Further execution is probably impossible.\n"); delete that auto-display to avoid an infinite recursion. */ if (stopped_by_random_signal) - delete_current_display (); + disable_current_display (); if (step_multi && stop_step) return; @@ -1052,10 +1064,10 @@ This is so that \"sh\" will process wildcards and I/O redirection.\n\ This time, \"sh\" crashed.\n\ \n\ One known bug in \"sh\" bites when the environment takes up a lot of space.\n\ -Try \"info env\" to see the environment; then use \"unset-env\" to kill\n\ +Try \"info env\" to see the environment; then use \"delete env\" to kill\n\ some variables whose values are large; then do \"run\" again.\n\ \n\ -If that works, you might want to put those \"unset-env\" commands\n\ +If that works, you might want to put those \"delete env\" commands\n\ into a \".gdbinit\" file in this directory so they will happen every time.\n"); } /* Don't confuse user with his program's symbols on sh's data. */ @@ -1211,37 +1223,34 @@ signals_info (signum_exp) char *signum_exp; { register int i; - printf ("Number\tStop\tPrint\tPass to program\tDescription\n"); + printf_filtered ("Number\tStop\tPrint\tPass to program\tDescription\n"); if (signum_exp) { i = parse_and_eval_address (signum_exp); - printf ("%d\t", i); - printf ("%s\t", signal_stop[i] ? "Yes" : "No"); - printf ("%s\t", signal_print[i] ? "Yes" : "No"); - printf ("%s\t\t", signal_program[i] ? "Yes" : "No"); - printf ("%s\n", sys_siglist[i]); + if (i >= NSIG || i < 0) + error ("Signal number out of bounds."); + printf_filtered ("%d\t", i); + printf_filtered ("%s\t", signal_stop[i] ? "Yes" : "No"); + printf_filtered ("%s\t", signal_print[i] ? "Yes" : "No"); + printf_filtered ("%s\t\t", signal_program[i] ? "Yes" : "No"); + printf_filtered ("%s\n", sys_siglist[i]); return; } - printf ("\n"); + printf_filtered ("\n"); for (i = 0; i < NSIG; i++) { QUIT; - if (i > 0 && i % 16 == 0) - { - printf ("[Type Return to see more]"); - fflush (stdout); - gdb_read_line (0, 0); - } - printf ("%d\t", i); - printf ("%s\t", signal_stop[i] ? "Yes" : "No"); - printf ("%s\t", signal_print[i] ? "Yes" : "No"); - printf ("%s\t\t", signal_program[i] ? "Yes" : "No"); - printf ("%s\n", sys_siglist[i]); + + printf_filtered ("%d\t", i); + printf_filtered ("%s\t", signal_stop[i] ? "Yes" : "No"); + printf_filtered ("%s\t", signal_print[i] ? "Yes" : "No"); + printf_filtered ("%s\t\t", signal_program[i] ? "Yes" : "No"); + printf_filtered ("%s\n", sys_siglist[i]); } - printf ("\nUse the \"handle\" command to change these tables.\n"); + printf_filtered ("\nUse the \"handle\" command to change these tables.\n"); } /* Save all of the information associated with the inferior<==>gdb diff --git a/gdb/kdb-start.c b/gdb/kdb-start.c index bdbc272683..cbc69fd874 100644 --- a/gdb/kdb-start.c +++ b/gdb/kdb-start.c @@ -1,3 +1,22 @@ +/* Main loop for the standalone kernel debugger. + 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 "defs.h" #include "param.h" diff --git a/gdb/RCS/m-hp9k320.h,v b/gdb/m-altos.h similarity index 54% rename from gdb/RCS/m-hp9k320.h,v rename to gdb/m-altos.h index 8df1709499..b69be6d99e 100644 --- a/gdb/RCS/m-hp9k320.h,v +++ b/gdb/m-altos.h @@ -1,85 +1,93 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.03.27.20.17.11; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.20.19.29.58; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Change "HPUX_ASM" define to "USG_SGS_ASM", since it's really the USG -Software Generation System assembler that we're fighting here. -., -@ -text -@/* Parameters for execution on an HP 9000 model 320, for GDB, the GNU debugger. - Copyright (C) 1986, 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! -*/ - -#ifndef HP9K320 -#define HP9K320 -#endif +/* Definitions to make GDB run on an Altos 3068 (m68k running SVR2) + Copyright (C) 1987,1989 Free Software Foundation, Inc. -/* Set flag to indicate whether HP's assembler is in use. */ -#ifdef __GNU__ -#ifdef __HPUX_ASM__ -#define USG_SGS_ASM -#endif -#else -#define USG_SGS_ASM -#endif +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 this for versions of hp-ux older than 6.0 */ -/* #define HPUX_VERSION_5 */ +/* The altos support would make a good base for a port to other USGR2 systems + (like the 3b1 and the Convergent miniframe). */ + +/* This is only needed in one file, but it's cleaner to put it here than + putting in more #ifdef's. */ +#include +#include + +#ifndef ALTOS +#define ALTOS +#endif -/* define USG if you are using sys5 /usr/include's */ #define USG -#define HAVE_TERMIO +/* Define the bit, byte, and word ordering of the machine. */ +#define BITS_BIG_ENDIAN +#define BYTES_BIG_ENDIAN +#define WORDS_BIG_ENDIAN /* Get rid of any system-imposed stack limit if possible. */ -/* #define SET_STACK_LIMIT_HUGE */ +/*#define SET_STACK_LIMIT_HUGE*/ + +#define HAVE_TERMIO + +#define CBREAK XTABS /* It takes all kinds... */ + +/* + * #define FLOATING_POINT if you have 68881 + * This hasn't been tested + */ + +/*#define FLOATING_POINT*/ +/*#undef FLOATING_POINT*/ + +#ifndef __GNUC__ +#undef USE_GAS +#define ALTOS_AS +#else +#define USE_GAS +#endif + +#ifndef R_OK +#define R_OK 4 +#define W_OK 2 +#define X_OK 1 +#define F_OK 0 +#endif + +#ifndef MAXPATHLEN +#define MAXPATHLEN (1024) +#endif + +/* Motorola assembly format */ +#if !defined(USE_GAS) && !defined(ALTOS) +#define MOTOROLA +#endif + +/* Get sys/wait.h ie. from a Sun and edit it a little (mc68000 to m68k) */ +#define HAVE_WAIT_STRUCT /* 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 +#undef NAMES_HAVE_UNDERSCORE -/* Debugger information will be in DBX format. */ +/* Exec files and symbol tables are in COFF format */ -#define READ_DBX_FORMAT +#define COFF_FORMAT +#define COFF_NO_LONG_FILE_NAMES +#define vfork fork /* Offset from address of function to start of its code. Zero on most machines. */ @@ -91,14 +99,20 @@ anyone else from sharing it farther. Help stamp out software hoarding! #define SKIP_PROLOGUE(pc) \ { register int op = read_memory_integer (pc, 2); \ - if (op == 0047126) \ + if (op == 0047126) \ pc += 4; /* Skip link #word */ \ - else if (op == 0044016) \ + else if (op == 0044016) \ pc += 6; /* Skip link #long */ \ + else if (op == 0060000) \ + pc += 4; /* Skip bra #word */ \ + else if (op == 00600377) \ + pc += 6; /* skip bra #long */ \ + else if ((op & 0177400) == 0060000) \ + pc += 2; /* skip bra #char */ \ } /* Immediately after a function call, return the saved pc. - Can't go through the frames for this because on some machines + 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. */ @@ -106,17 +120,14 @@ anyone else from sharing it farther. Help stamp out software hoarding! 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. */ + to get the offset in the core file of the register values. */ -#ifdef HPUX_VERSION_5 -#define KERNEL_U_ADDR 0x00979000 -#else -#define KERNEL_U_ADDR 0x00C01000 -#endif +#define KERNEL_U_ADDR 0x1fbf000 /* Address of end of stack space. */ -#define STACK_END_ADDR 0xFFF00000 +/*#define STACK_END_ADDR (0xffffff)*/ +#define STACK_END_ADDR (0x1000000) /* Stack grows downward. */ @@ -124,13 +135,14 @@ read_memory_integer (read_register (SP_REGNUM), 4) /* Sequence of bytes for breakpoint instruction. */ -#define BREAKPOINT {0x4e, 0x41} +#define BREAKPOINT {0x4e, 0x4e} /* Amount PC must be decremented by after a breakpoint. This is often the number of bytes in BREAKPOINT - but not always. */ + but not always. + On the Altos, the kernel resets the pc to the trap instr */ -#define DECR_PC_AFTER_BREAK 2 +#define DECR_PC_AFTER_BREAK 0 /* Nonzero if instruction at PC is a return instruction. */ @@ -138,7 +150,7 @@ read_memory_integer (read_register (SP_REGNUM), 4) /* Return 1 if P points to an invalid floating point value. */ -#define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */ +#define INVALID_FLOAT(p, len) (*((int *) (p)) == -1) /* Just a first guess; not checked */ /* Largest integer type */ #define LONGEST long @@ -152,17 +164,30 @@ read_memory_integer (read_register (SP_REGNUM), 4) /* Number of machine registers */ -#define NUM_REGS 29 +#ifdef FLOATING_POINT +#define NUM_REGS 31 +#else +#define NUM_REGS 18 +#endif /* Initializer for an array of names of registers. There should be NUM_REGS strings in this initializer. */ +#ifdef FLOATING_POINT #define REGISTER_NAMES \ {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \ "ps", "pc", \ "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \ - "fpcontrol", "fpstatus", "fpiaddr" } + "fpcontrol", "fpstatus", "fpiaddr", "fpcode", "fpflags" \ + } +#else +#define REGISTER_NAMES \ + {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \ + "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \ + "ps", "pc", \ + } +#endif /* Register numbers of various important registers. Note that some of these values are "real" register numbers, @@ -180,7 +205,7 @@ read_memory_integer (read_register (SP_REGNUM), 4) /* Total amount of space needed to store our copies of the machine's register state, the array `registers'. */ -#define REGISTER_BYTES (16*4+8*12+8+12) +#define REGISTER_BYTES (16*4+8*12+8+20) /* Index within `registers' of the first byte of the space for register N. */ @@ -193,6 +218,8 @@ read_memory_integer (read_register (SP_REGNUM), 4) /* Number of bytes of storage in the actual machine representation for register N. On the 68000, all regs are 4 bytes except the floating point regs which are 12 bytes. */ +/* Note that the unsigned cast here forces the result of the + subtractiion to very high positive values if N < FP0_REGNUM */ #define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4) @@ -202,6 +229,15 @@ read_memory_integer (read_register (SP_REGNUM), 4) #define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 8 : 4) +#define REGISTER_U_ADDR(addr, blockend, regno) \ +{ if (regno <= SP_REGNUM) \ + addr = blockend + regno * 4; \ + else if (regno == PS_REGNUM) \ + addr = blockend + regno * 4 + 4; \ + else if (regno == PC_REGNUM) \ + addr = blockend + regno * 4 + 2; \ +} + /* Largest value REGISTER_RAW_SIZE can have. */ #define MAX_REGISTER_RAW_SIZE 12 @@ -277,11 +313,6 @@ read_memory_integer (read_register (SP_REGNUM), 4) ? (&u.u_pcb.pcb_mc68881[FMC68881_R0 + (((regno) - FP0_REGNUM) * 3)]) \ : (&u.u_pcb.pcb_mc68881[FMC68881_C + ((regno) - FPC_REGNUM)]))) \ - ((char *) (& u))) - -/* It is safe to look for symsegs on a Sun, because Sun's ld - does not screw up with random garbage at end of file. */ - -#define READ_GDB_SYMSEGS /* Describe the pointer in each stack frame to the previous stack frame (its caller). */ @@ -296,18 +327,27 @@ read_memory_integer (read_register (SP_REGNUM), 4) it means the given frame is the outermost one and has no caller. In that case, FRAME_CHAIN_COMBINE is not used. */ -/* In the case of the Sun, the frame's nominal address +/* In the case of the Altos, the frame's nominal address is the address of a 4-byte word containing the calling frame's address. */ -#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4)) +#define FRAME_CHAIN(thisframe) \ + (outside_startup_file ((thisframe)->pc) ? \ + read_memory_integer ((thisframe)->frame, 4) :\ + 0) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (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) @@ -317,13 +357,20 @@ read_memory_integer (read_register (SP_REGNUM), 4) /* Set VAL to the number of args passed to frame described by FI. Can set VAL to -1, meaning no way to tell. */ +/* Return number of args passed to a frame. + Can return -1, meaning no way to tell. */ + /* We can't tell how many args there are - now that the C compiler delays popping them. */ -#define FRAME_NUM_ARGS(val,fi) (val = -1) + now that the (gnu) C compiler delays popping them. + Perhaps we could tell if we use the Altos cc, but I'm not sure + COFF_FORMAT is the right conditional */ + +#ifdef COFF_FORMAT +#define FRAME_NUM_ARGS(val, fi) (val = -1) #if 0 #define FRAME_NUM_ARGS(val, fi) \ -{ register CORE_ADDR pc = FRAME_SAVED_PC (fi); \ +{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame); \ register int insn = 0177777 & read_memory_integer (pc, 2); \ val = 0; \ if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \ @@ -392,7 +439,7 @@ read_memory_integer (read_register (SP_REGNUM), 4) for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \ if (regmask & 1) \ (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \ - else if (0x2f00 == 0xfff0 & read_memory_integer (pc, 2)) \ + else if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2))) \ { regnum = 0xf & read_memory_integer (pc, 2); pc += 2; \ (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \ /* fmovemx to index of sp may follow. */ \ @@ -414,6 +461,147 @@ read_memory_integer (read_register (SP_REGNUM), 4) (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4; \ } +#if 0 +{ register int regnum; \ + register int regmask; \ + register CORE_ADDR next_addr; \ + register CORE_ADDR pc; \ + int nextinsn; \ + bzero (&frame_saved_regs, sizeof frame_saved_regs); \ + if ((frame_info).pc >= (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \ + && (frame_info).pc <= (frame_info).frame) \ + { next_addr = (frame_info).frame; \ + pc = (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\ + else \ + { pc = get_pc_function_start ((frame_info).pc); \ + /* Verify we have a link a6 instruction next; \ + if not we lose. If we win, find the address above the saved \ + regs using the amount of storage from the link instruction. */\ + if (044016 == read_memory_integer (pc, 2)) \ + next_addr = (frame_info).frame + read_memory_integer (pc += 2, 4), pc+=4; \ + else if (047126 == read_memory_integer (pc, 2)) \ + next_addr = (frame_info).frame + read_memory_integer (pc += 2, 2), pc+=2; \ + else goto lose; \ + /* If have an addal #-n, sp next, adjust next_addr. */ \ + if ((0177777 & read_memory_integer (pc, 2)) == 0157774) \ + next_addr += read_memory_integer (pc += 2, 4), pc += 4; \ + } \ + /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ \ + regmask = read_memory_integer (pc + 2, 2); \ + /* But before that can come an fmovem. Check for it. */ \ + nextinsn = 0xffff & read_memory_integer (pc, 2); \ + if (0xf227 == nextinsn \ + && (regmask & 0xff00) == 0xe000) \ + { pc += 4; /* Regmask's low bit is for register fp7, the first pushed */ \ + for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \ + if (regmask & 1) \ + (frame_saved_regs).regs[regnum] = (next_addr -= 12); \ + regmask = read_memory_integer (pc + 2, 2); } \ + if (0044327 == read_memory_integer (pc, 2)) \ + { pc += 4; /* Regmask's low bit is for register 0, the first written */ \ + for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \ + if (regmask & 1) \ + (frame_saved_regs).regs[regnum] = (next_addr += 4) - 4; } \ + else if (0044347 == read_memory_integer (pc, 2)) \ + { pc += 4; /* Regmask's low bit is for register 15, the first pushed */ \ + for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \ + if (regmask & 1) \ + (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \ + else if (0x2f00 == 0xfff0 & read_memory_integer (pc, 2)) \ + { regnum = 0xf & read_memory_integer (pc, 2); pc += 2; \ + (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \ + /* fmovemx to index of sp may follow. */ \ + regmask = read_memory_integer (pc + 2, 2); \ + nextinsn = 0xffff & read_memory_integer (pc, 2); \ + if (0xf236 == nextinsn \ + && (regmask & 0xff00) == 0xf000) \ + { pc += 10; /* Regmask's low bit is for register fp0, the first written */ \ + for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \ + if (regmask & 1) \ + (frame_saved_regs).regs[regnum] = (next_addr += 12) - 12; \ + regmask = read_memory_integer (pc + 2, 2); } \ + /* clrw -(sp); movw ccr,-(sp) may follow. */ \ + if (0x426742e7 == read_memory_integer (pc, 4)) \ + (frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4); \ + lose: ; \ + (frame_saved_regs).regs[SP_REGNUM] = (frame_info).frame + 8; \ + (frame_saved_regs).regs[FP_REGNUM] = (frame_info).frame; \ + (frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 4; \ +} +#endif +#if 0 +#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \ +{ register int regnum; \ + register int regmask; \ + register CORE_ADDR next_addr; \ + register CORE_ADDR pc; \ + register int insn; \ + register int offset; \ + bzero (&frame_saved_regs, sizeof frame_saved_regs); \ + if ((frame_info).pc >= (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \ + && (frame_info).pc <= (frame_info).frame) \ + { next_addr = (frame_info).frame; \ + pc = (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\ + else \ + { pc = get_pc_function_start ((frame_info).pc); \ + /* Verify we have a link a6 instruction next, \ + or a branch followed by a link a6 instruction; \ + if not we lose. If we win, find the address above the saved \ + regs using the amount of storage from the link instruction. */\ +retry: \ + insn = read_memory_integer (pc, 2); \ + if (insn == 044016) \ + next_addr = (frame_info).frame - read_memory_integer (pc += 2, 4), pc+=4; \ + else if (insn == 047126) \ + next_addr = (frame_info).frame - read_memory_integer (pc += 2, 2), pc+=2; \ + else if ((insn & 0177400) == 060000) /* bra insn */ \ + { offset = insn & 0377; \ + pc += 2; /* advance past bra */ \ + if (offset == 0) /* bra #word */ \ + offset = read_memory_integer (pc, 2), pc += 2; \ + else if (offset == 0377) /* bra #long */ \ + offset = read_memory_integer (pc, 4), pc += 4; \ + pc += offset; \ + goto retry; \ + } else goto lose; \ + /* If have an addal #-n, sp next, adjust next_addr. */ \ + if ((0177777 & read_memory_integer (pc, 2)) == 0157774) \ + next_addr += read_memory_integer (pc += 2, 4), pc += 4; \ + } \ + /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ \ + insn = read_memory_integer (pc, 2), pc += 2; \ + regmask = read_memory_integer (pc, 2); \ + if ((insn & 0177760) == 022700) /* movl rn, (sp) */ \ + (frame_saved_regs).regs[(insn&7) + ((insn&010)?8:0)] = next_addr; \ + else if ((insn & 0177760) == 024700) /* movl rn, -(sp) */ \ + (frame_saved_regs).regs[(insn&7) + ((insn&010)?8:0)] = next_addr-=4; \ + else if (insn == 0044327) /* moveml mask, (sp) */ \ + { pc += 2; \ + /* Regmask's low bit is for register 0, the first written */ \ + next_addr -= 4; \ + for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \ + if (regmask & 1) \ + (frame_saved_regs).regs[regnum] = (next_addr += 4); \ + } else if (insn == 0044347) /* moveml mask, -(sp) */ \ + { pc += 2; \ + /* Regmask's low bit is for register 15, the first pushed */ \ + for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \ + if (regmask & 1) \ + (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \ + /* clrw -(sp); movw ccr,-(sp) may follow. */ \ + if (read_memory_integer (pc, 2) == 041147 \ + && read_memory_integer (pc+2, 2) == 042347) \ + (frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4); \ + lose: ; \ + (frame_saved_regs).regs[SP_REGNUM] = (frame_info).frame + 8; \ + (frame_saved_regs).regs[FP_REGNUM] = (frame_info).frame; \ + (frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 4; \ +} +#endif +#else +#define FRAME_NUM_ARGS(val, fi) (val = -1) +#endif + /* Things needed for making the inferior call functions. */ /* Push an empty stack frame, to record the current PC, etc. */ @@ -437,30 +625,30 @@ read_memory_integer (read_register (SP_REGNUM), 4) restoring all saved registers. */ #define POP_FRAME \ -{ register FRAME frame = get_current_frame (); \ - register CORE_ADDR fp; \ - register int regnum; \ - struct frame_saved_regs fsr; \ - struct frame_info *fi; \ - char raw_buffer[12]; \ - fi = get_frame_info (frame); \ - fp = fi->frame; \ - get_frame_saved_regs (fi, &fsr); \ - for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \ - if (fsr.regs[regnum]) \ - { read_memory (fsr.regs[regnum], raw_buffer, 12); \ +{ register FRAME frame = get_current_frame (); \ + register CORE_ADDR fp; \ + register int regnum; \ + struct frame_saved_regs fsr; \ + struct frame_info *fi; \ + char raw_buffer[12]; \ + fi = get_frame_info (frame); \ + fp = fi->frame; \ + get_frame_saved_regs (fi, &fsr); \ + for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \ + if (fsr.regs[regnum]) \ + { read_memory (fsr.regs[regnum], raw_buffer, 12); \ write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\ - for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \ - if (fsr.regs[regnum]) \ + for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \ + if (fsr.regs[regnum]) \ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \ - if (fsr.regs[PS_REGNUM]) \ + if (fsr.regs[PS_REGNUM]) \ write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \ - write_register (FP_REGNUM, read_memory_integer (fp, 4)); \ - write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \ - write_register (SP_REGNUM, fp + 8); \ - flush_cached_frames (); \ - set_current_frame (create_new_frame (read_register (FP_REGNUM),\ - read_pc ()));} + write_register (FP_REGNUM, read_memory_integer (fp, 4)); \ + write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \ + write_register (SP_REGNUM, fp + 8); \ + flush_cached_frames (); \ + set_current_frame (create_new_frame (read_register (FP_REGNUM), \ + read_pc ())); } /* This sequence of words is the instructions fmovem 0xff,-(sp) @@ -471,7 +659,7 @@ read_memory_integer (read_register (SP_REGNUM), 4) no code is needed in the dummy for this. The CALL_DUMMY_START_OFFSET gives the position of the following jsr instruction. *../ - jsr @@#32323232 + jsr @#32323232 addl #69696969,sp bpt nop @@ -484,7 +672,7 @@ But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done, and we cannot allow the moveml to push the registers again lest they be taken for the arguments. */ -#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e414e71} +#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4e4e71} #define CALL_DUMMY_LENGTH 28 @@ -513,95 +701,101 @@ taken for the arguments. */ 0, 0, 0, 0, 0, 0, 0, 0, \ SIGILL } -#ifndef HPUX_ASM - /* 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. */ +#ifdef MOTOROLA +#define INIT_STACK(beg, end) \ +{ asm (".globl end"); \ + asm ("move.l $ end, sp"); \ + asm ("clr.l fp"); } +#else +#ifdef ALTOS_AS +#define INIT_STACK(beg, end) \ +{ asm ("global end"); \ + asm ("mov.l &end,%sp"); \ + asm ("clr.l %fp"); } +#else #define INIT_STACK(beg, end) \ { asm (".globl end"); \ asm ("movel $ end, sp"); \ asm ("clrl fp"); } +#endif +#endif /* Push the frame pointer register on the stack. */ +#ifdef MOTOROLA +#define PUSH_FRAME_PTR \ + asm ("move.l fp, -(sp)"); +#else +#ifdef ALTOS_AS +#define PUSH_FRAME_PTR \ + asm ("mov.l %fp, -(%sp)"); +#else #define PUSH_FRAME_PTR \ asm ("movel fp, -(sp)"); +#endif +#endif /* Copy the top-of-stack to the frame pointer register. */ +#ifdef MOTOROLA +#define POP_FRAME_PTR \ + asm ("move.l (sp), fp"); +#else +#ifdef ALTOS_AS +#define POP_FRAME_PTR \ + asm ("mov.l (%sp), %fp"); +#else #define POP_FRAME_PTR \ asm ("movl (sp), fp"); +#endif +#endif /* 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. */ +#ifdef MOTOROLA +#define PUSH_REGISTERS \ +{ asm ("clr.w -(sp)"); \ + asm ("pea (10,sp)"); \ + asm ("movem $ 0xfffe,-(sp)"); } +#else +#ifdef ALTOS_AS +#define PUSH_REGISTERS \ +{ asm ("clr.w -(%sp)"); \ + asm ("pea (10,%sp)"); \ + asm ("movm.l &0xfffe,-(%sp)"); } +#else #define PUSH_REGISTERS \ { asm ("clrw -(sp)"); \ asm ("pea 10(sp)"); \ asm ("movem $ 0xfffe,-(sp)"); } +#endif +#endif /* 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. */ +#ifdef MOTOROLA #define POP_REGISTERS \ -{ asm ("subil $8,28(sp)"); \ +{ asm ("subi.l $8,28(sp)"); \ asm ("movem (sp),$ 0xffff"); \ asm ("rte"); } - -#else /* HPUX_ASM */ - -/* 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) \ -{ asm ("global end"); \ - asm ("mov.l &end,%sp"); \ - asm ("clr.l %a6"); } - -/* Push the frame pointer register on the stack. */ -#define PUSH_FRAME_PTR \ - asm ("mov.l %fp,-(%sp)"); - -/* Copy the top-of-stack to the frame pointer register. */ -#define POP_FRAME_PTR \ - asm ("mov.l (%sp),%fp"); - -/* 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 \ -{ asm ("clr.w -(%sp)"); \ - asm ("pea 10(%sp)"); \ - asm ("movm.l &0xfffe,-(%sp)"); } - -/* 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 \ -{ asm ("subi.l &8,28(%sp)"); \ - asm ("mov.m (%sp),&0xffff"); \ +#else +#ifdef ALTOS_AS +#define POP_REGISTERS \ +{ asm ("sub.l &8,28(%sp)"); \ + asm ("movem (%sp),&0xffff"); \ + asm ("rte"); } +#else +#define POP_REGISTERS \ +{ asm ("subil $8,28(sp)"); \ + asm ("movem (sp),$ 0xffff"); \ asm ("rte"); } +#endif +#endif -#endif /* HPUX_ASM */ -@ - - -1.1 -log -@Initial revision -@ -text -@d28 1 -a28 1 -#define HPUX_ASM -d31 1 -a31 1 -#define HPUX_ASM -@ diff --git a/gdb/m-convex.h b/gdb/m-convex.h new file mode 100644 index 0000000000..7d162d4b5f --- /dev/null +++ b/gdb/m-convex.h @@ -0,0 +1,603 @@ +/* Definitions to make GDB run on Convex Unix (4bsd) + 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. */ + +/* Describe the endian nature of this machine. */ +#define BITS_BIG_ENDIAN +#define BYTES_BIG_ENDIAN +#define WORDS_BIG_ENDIAN + +/* Include certain files for dbxread.c */ +#include +#include +#include +#include + +#define LONG_LONG +#define ATTACH_DETACH +#define HAVE_WAIT_STRUCT +#define NO_SIGINTERRUPT + +/* 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 + +/* Debugger information will be in DBX format. */ + +#define READ_DBX_FORMAT + +/* There is come problem with the debugging symbols generated by the + compiler such that the debugging symbol for the first line of a + function overlap with the function prologue. */ +#define PROLOGUE_FIRSTLINE_OVERLAP + +/* When convex pcc says CHAR or SHORT, it provides the correct address. */ + +#define BELIEVE_PCC_PROMOTION 1 + +/* Symbol types to ignore. */ + +#define IGNORE_SYMBOL(TYPE) \ + (((TYPE) & ~N_EXT) == N_TBSS || ((TYPE) & ~N_EXT) == N_TDATA) + +/* Use SIGCONT rather than SIGTSTP because convex Unix occasionally + turkeys SIGTSTP. I think. */ + +#define STOP_SIGNAL SIGCONT + +/* Convex ld sometimes omits _etext. + Get text segment end from a.out header in this case. */ + +extern unsigned text_end; +#define END_OF_TEXT_DEFAULT text_end + +/* Use csh to do argument expansion so we get ~ and such. */ + +/* Doesn't work. */ +/* #define SHELL_FILE "/bin/csh" */ + +/* 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. + Convex prolog is: + [sub.w #-,sp] in one of 3 possible sizes + [mov psw,- fc/vc main program prolog + and #-,- (skip it because the "mov psw" saves the + mov -,psw] T bit, so continue gets a surprise trap) + [and #-,sp] fc/vc O2 main program prolog + [ld.- -(ap),-] pcc/gcc register arg loads +*/ + +#define SKIP_PROLOGUE(pc) \ +{ int op, ix; \ + op = read_memory_integer (pc, 2); \ + if ((op & 0xffc7) == 0x5ac0) pc += 2; \ + else if (op == 0x1580) pc += 4; \ + else if (op == 0x15c0) pc += 6; \ + if ((read_memory_integer (pc, 2) & 0xfff8) == 0x7c40 \ + && (read_memory_integer (pc + 2, 2) & 0xfff8) == 0x1240 \ + && (read_memory_integer (pc + 8, 2) & 0xfff8) == 0x7c48) \ + pc += 10; \ + if (read_memory_integer (pc, 2) == 0x1240) pc += 6; \ + for (;;) { \ + op = read_memory_integer (pc, 2); \ + ix = (op >> 3) & 7; \ + if (ix != 6) break; \ + if ((op & 0xfcc0) == 0x3000) pc += 4; \ + else if ((op & 0xfcc0) == 0x3040) pc += 6; \ + else if ((op & 0xfcc0) == 0x2800) pc += 4; \ + else if ((op & 0xfcc0) == 0x2840) pc += 6; \ + else break;}} + +/* Immediately after a function call, return the saved pc. + (ignore frame and return *$sp so we can handle both calls and callq) */ + +#define SAVED_PC_AFTER_CALL(frame) \ + read_memory_integer (read_register (SP_REGNUM), 4) + +/* Address of end of stack space. + This is ((USRSTACK + 0xfff) & -0x1000)) from but + that expression depends on the kernel version; instead, fetch a + page-zero pointer and get it from that. This will be invalid if + they ever change the way bkpt signals are delivered. */ + +#define STACK_END_ADDR (0xfffff000 & *(unsigned *) 0x80000050) + +/* User-mode traps push an extended rtn block, + then fault with one of the following PCs */ + +#define is_trace_pc(pc) ((unsigned) ((pc) - (*(int *) 0x80000040)) <= 4) +#define is_arith_pc(pc) ((unsigned) ((pc) - (*(int *) 0x80000044)) <= 4) +#define is_break_pc(pc) ((unsigned) ((pc) - (*(int *) 0x80000050)) <= 4) + +/* We need to manipulate trap bits in the psw */ + +#define PSW_TRAP_FLAGS 0x69670000 +#define PSW_T_BIT 0x08000000 +#define PSW_S_BIT 0x01000000 + +/* Stack grows downward. */ + +#define INNER_THAN < + +/* Sequence of bytes for breakpoint instruction. (bkpt) */ + +#define BREAKPOINT {0x7d,0x50} + +/* Amount PC must be decremented by after a breakpoint. + This is often the number of bytes in BREAKPOINT but not always. + (The break PC needs to be decremented by 2, but we do it when the + break frame is recognized and popped. That way gdb can tell breaks + from trace traps with certainty.) */ + +#define DECR_PC_AFTER_BREAK 0 + +/* Nonzero if instruction at PC is a return instruction. (rtn or rtnq) */ + +#define ABOUT_TO_RETURN(pc) \ + ((read_memory_integer (pc, 2) & 0xffe0) == 0x7c80) + +/* Return 1 if P points to an invalid floating point value. */ + +#define INVALID_FLOAT(p,len) 0 + +/* Largest integer type */ + +#define LONGEST long long + +/* Name of the builtin type for the LONGEST type above. */ + +#undef BUILTIN_TYPE_LONGEST +#define BUILTIN_TYPE_LONGEST builtin_type_long_long + +/* Say how long (ordinary) registers are. */ + +#define REGISTER_TYPE long long + +/* Number of machine registers */ + +#define NUM_REGS 26 + +/* Initializer for an array of names of registers. + There should be NUM_REGS strings in this initializer. */ + +#define REGISTER_NAMES {"pc","psw","fp","ap","a5","a4","a3","a2","a1","sp",\ + "s7","s6","s5","s4","s3","s2","s1","s0",\ + "S7","S6","S5","S4","S3","S2","S1","S0"} + +/* 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 S0_REGNUM 25 /* the real S regs */ +#define S7_REGNUM 18 +#define s0_REGNUM 17 /* low-order halves of S regs */ +#define s7_REGNUM 10 +#define SP_REGNUM 9 /* A regs */ +#define A1_REGNUM 8 +#define A5_REGNUM 4 +#define AP_REGNUM 3 +#define FP_REGNUM 2 /* Contains address of executing stack frame */ +#define PS_REGNUM 1 /* Contains processor status */ +#define PC_REGNUM 0 /* Contains program counter */ + +/* convert dbx stab register number (from `r' declaration) to a gdb REGNUM */ + +#define STAB_REG_TO_REGNUM(value) \ + ((value) < 8 ? S0_REGNUM - (value) : SP_REGNUM - ((value) - 8)) + +/* Vector register numbers, not handled as ordinary regs. + They are treated as convenience variables whose values are read + from the inferior when needed. */ + +#define V0_REGNUM 0 +#define V7_REGNUM 7 +#define VM_REGNUM 8 +#define VS_REGNUM 9 +#define VL_REGNUM 10 + +/* Total amount of space needed to store our copies of the machine's + register state, the array `registers'. */ +#define REGISTER_BYTES (4*10 + 8*8) + +/* Index within `registers' of the first byte of the space for + register N. + NB: must match structure of struct syscall_context for correct operation */ + +#define REGISTER_BYTE(N) ((N) < s7_REGNUM ? 4*(N) : \ + (N) < S7_REGNUM ? 44 + 8 * ((N)-s7_REGNUM) : \ + 40 + 8 * ((N)-S7_REGNUM)) + +/* Number of bytes of storage in the actual machine representation + for register N. */ + +#define REGISTER_RAW_SIZE(N) ((N) < S7_REGNUM ? 4 : 8) + +/* Number of bytes of storage in the program's representation + for register N. */ + +#define REGISTER_VIRTUAL_SIZE(N) REGISTER_RAW_SIZE(N) + +/* Largest value REGISTER_RAW_SIZE can have. */ + +#define MAX_REGISTER_RAW_SIZE 8 + +/* Largest value REGISTER_VIRTUAL_SIZE can have. */ + +#define MAX_REGISTER_VIRTUAL_SIZE 8 + +/* 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), REGISTER_RAW_SIZE (REGNUM)); + +/* 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), REGISTER_RAW_SIZE (REGNUM)); + +/* Return the GDB type object for the "standard" data type + of data in register N. */ + +#define REGISTER_VIRTUAL_TYPE(N) \ + ((N) < S7_REGNUM ? builtin_type_int : builtin_type_long_long) + +/* 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) \ + { write_register (A1_REGNUM, (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 (&((char *) REGBUF) [REGISTER_BYTE (S0_REGNUM) + \ + 8 - TYPE_LENGTH (TYPE)],\ + 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 (REGISTER_BYTE (S0_REGNUM), VALBUF, 8) + +/* 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 *) & ((char *) REGBUF) [REGISTER_BYTE (s0_REGNUM)]) + +/* Compensate for lack of `vprintf' function. */ +#ifndef HAVE_VPRINTF +#define vprintf(format, ap) _doprnt (format, ap, stdout) +#endif /* not HAVE_VPRINTF */ + +/* Define trapped internal variable hooks to read and write + vector and communication registers. */ + +#define IS_TRAPPED_INTERNALVAR is_trapped_internalvar +#define VALUE_OF_TRAPPED_INTERNALVAR value_of_trapped_internalvar +#define SET_TRAPPED_INTERNALVAR set_trapped_internalvar + +extern struct value *value_of_trapped_internalvar (); + +/* Hooks to read data from soff exec and core files, + and to describe the files. */ + +#define XFER_CORE_FILE +#define FILES_INFO_HOOK print_maps + +/* Hook to call after creating inferior process. */ + +#define CREATE_INFERIOR_HOOK create_inferior_hook + +/* Hook to call to print a typeless integer value, normally printed in decimal. + For convex, use hex instead if the number looks like an address. */ + +#define PRINT_TYPELESS_INTEGER decout + +/* Specify that variables for a particular lexical context are listed + after the beginning LBRAC instead of before in the executables list + of symbols. */ +#define VARIABLES_INSIDE_BLOCK + +/* Pcc occaisionally puts an SO where there should be an SOL. */ +#define PCC_SOL_BROKEN + +/* Cannot execute with pc on the stack. */ +#define CANNOT_EXECUTE_STACK + +/* Describe the pointer in each stack frame to the previous stack frame + (its caller). */ + +/* FRAME_CHAIN takes a frame_info with a frame's nominal address in fi->frame, + 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. */ + +/* (caller fp is saved at 8(fp)) */ + +#define FRAME_CHAIN(fi) (read_memory_integer ((fi)->frame + 8, 4)) + +#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. + On convex, check at the return address for `callq' -- if so, frameless, + otherwise, not. */ + +#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \ +{ \ + extern CORE_ADDR text_start, text_end; \ + CORE_ADDR call_addr = SAVED_PC_AFTER_CALL (FI); \ + (FRAMELESS) = (call_addr >= text_start && call_addr < text_end \ + && read_memory_integer (call_addr - 6, 1) == 0x22); \ +} + +#define FRAME_SAVED_PC(fi) (read_memory_integer ((fi)->frame, 4)) + +#define FRAME_ARGS_ADDRESS(fi) (read_memory_integer ((fi)->frame + 12, 4)) + +#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 = read_memory_integer (FRAME_ARGS_ADDRESS (fi) - 4, 4); \ + if (numargs < 0 || numargs >= 256) numargs = -1;} + +/* Return number of bytes at start of arglist that are not really args. */ + +#define FRAME_ARGS_SKIP 0 + +/* 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. */ + +/* Normal (short) frames save only PC, FP, (callee's) AP. To reasonably + handle gcc and pcc register variables, scan the code following the + call for the instructions the compiler inserts to reload register + variables from stack slots and record the stack slots as the saved + locations of those registers. This will occasionally identify some + random load as a saved register; this is harmless. vc does not + declare its register allocation actions in the stabs. */ + +#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \ +{ register int regnum; \ + register int frame_length = /* 3 short, 2 long, 1 extended, 0 context */\ + (read_memory_integer ((frame_info)->frame + 4, 4) >> 25) & 3; \ + register CORE_ADDR frame_fp = \ + read_memory_integer ((frame_info)->frame + 8, 4); \ + register CORE_ADDR next_addr; \ + bzero (&frame_saved_regs, sizeof frame_saved_regs); \ + (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 0; \ + (frame_saved_regs).regs[PS_REGNUM] = (frame_info)->frame + 4; \ + (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame + 8; \ + (frame_saved_regs).regs[AP_REGNUM] = frame_fp + 12; \ + next_addr = (frame_info)->frame + 12; \ + if (frame_length < 3) \ + for (regnum = A5_REGNUM; regnum < SP_REGNUM; ++regnum) \ + (frame_saved_regs).regs[regnum] = (next_addr += 4); \ + if (frame_length < 2) \ + (frame_saved_regs).regs[SP_REGNUM] = (next_addr += 4); \ + next_addr -= 4; \ + if (frame_length < 3) \ + for (regnum = S7_REGNUM; regnum < S0_REGNUM; ++regnum) \ + (frame_saved_regs).regs[regnum] = (next_addr += 8); \ + if (frame_length < 2) \ + (frame_saved_regs).regs[S0_REGNUM] = (next_addr += 8); \ + else \ + (frame_saved_regs).regs[SP_REGNUM] = next_addr + 8; \ + if (frame_length == 3) { \ + CORE_ADDR pc = read_memory_integer ((frame_info)->frame, 4); \ + int op, ix, disp; \ + op = read_memory_integer (pc, 2); \ + if ((op & 0xffc7) == 0x1480) pc += 4; /* add.w #-,sp */ \ + else if ((op & 0xffc7) == 0x58c0) pc += 2; /* add.w #-,sp */ \ + op = read_memory_integer (pc, 2); \ + if ((op & 0xffc7) == 0x2a06) pc += 4; /* ld.w -,ap */ \ + for (;;) { \ + op = read_memory_integer (pc, 2); \ + ix = (op >> 3) & 7; \ + if ((op & 0xfcc0) == 0x2800) { /* ld.- -,ak */ \ + regnum = SP_REGNUM - (op & 7); \ + disp = read_memory_integer (pc + 2, 2); \ + pc += 4;} \ + else if ((op & 0xfcc0) == 0x2840) { /* ld.- -,ak */ \ + regnum = SP_REGNUM - (op & 7); \ + disp = read_memory_integer (pc + 2, 4); \ + pc += 6;} \ + if ((op & 0xfcc0) == 0x3000) { /* ld.- -,sk */ \ + regnum = S0_REGNUM - (op & 7); \ + disp = read_memory_integer (pc + 2, 2); \ + pc += 4;} \ + else if ((op & 0xfcc0) == 0x3040) { /* ld.- -,sk */ \ + regnum = S0_REGNUM - (op & 7); \ + disp = read_memory_integer (pc + 2, 4); \ + pc += 6;} \ + else if ((op & 0xff00) == 0x7100) { /* br crossjump */ \ + pc += 2 * (char) op; \ + continue;} \ + else if (op == 0x0140) { /* jmp crossjump */ \ + pc = read_memory_integer (pc + 2, 4); \ + continue;} \ + else break; \ + if ((frame_saved_regs).regs[regnum]) \ + break; \ + if (ix == 7) disp += frame_fp; \ + else if (ix == 6) disp += read_memory_integer (frame_fp + 12, 4); \ + else if (ix != 0) break; \ + (frame_saved_regs).regs[regnum] = \ + disp - 8 + (1 << ((op >> 8) & 3)); \ + if (regnum >= S7_REGNUM) \ + (frame_saved_regs).regs[regnum - S0_REGNUM + s0_REGNUM] = \ + disp - 4 + (1 << ((op >> 8) & 3)); \ + } \ + } \ +} + +/* Things needed for making the inferior call functions. */ + +/* Push an empty stack frame, to record the current PC, etc. */ + +#define PUSH_DUMMY_FRAME \ +{ register CORE_ADDR sp = read_register (SP_REGNUM); \ + register int regnum; \ + char buf[8]; \ + long word; \ + for (regnum = S0_REGNUM; regnum >= S7_REGNUM; --regnum) { \ + read_register_bytes (REGISTER_BYTE (regnum), buf, 8); \ + sp = push_bytes (sp, buf, 8);} \ + for (regnum = SP_REGNUM; regnum >= FP_REGNUM; --regnum) { \ + word = read_register (regnum); \ + sp = push_bytes (sp, &word, 4);} \ + word = (read_register (PS_REGNUM) &~ (3<<25)) | (1<<25); \ + sp = push_bytes (sp, &word, 4); \ + word = read_register (PC_REGNUM); \ + sp = push_bytes (sp, &word, 4); \ + write_register (SP_REGNUM, sp); \ + write_register (FP_REGNUM, sp); \ + write_register (AP_REGNUM, sp);} + +/* Discard from the stack the innermost frame, restoring all registers. */ + +#define POP_FRAME do {\ + register CORE_ADDR fp = read_register (FP_REGNUM); \ + register int regnum; \ + register int frame_length = /* 3 short, 2 long, 1 extended, 0 context */ \ + (read_memory_integer (fp + 4, 4) >> 25) & 3; \ + char buf[8]; \ + write_register (PC_REGNUM, read_memory_integer (fp, 4)); \ + write_register (PS_REGNUM, read_memory_integer (fp += 4, 4)); \ + write_register (FP_REGNUM, read_memory_integer (fp += 4, 4)); \ + write_register (AP_REGNUM, read_memory_integer (fp += 4, 4)); \ + if (frame_length < 3) \ + for (regnum = A5_REGNUM; regnum < SP_REGNUM; ++regnum) \ + write_register (regnum, read_memory_integer (fp += 4, 4)); \ + if (frame_length < 2) \ + write_register (SP_REGNUM, read_memory_integer (fp += 4, 4)); \ + fp -= 4; \ + if (frame_length < 3) \ + for (regnum = S7_REGNUM; regnum < S0_REGNUM; ++regnum) { \ + read_memory (fp += 8, buf, 8); \ + write_register_bytes (REGISTER_BYTE (regnum), buf, 8);} \ + if (frame_length < 2) { \ + read_memory (fp += 8, buf, 8); \ + write_register_bytes (REGISTER_BYTE (regnum), buf, 8);} \ + else write_register (SP_REGNUM, fp + 8); \ + flush_cached_frames (); \ + set_current_frame (create_new_frame (read_register (FP_REGNUM), \ + read_pc ())); \ +} while (0) + +/* This sequence of words is the instructions + mov sp,ap + pshea 69696969 + calls 32323232 + bkpt + Note this is 16 bytes. */ + +#define CALL_DUMMY {0x50860d4069696969LL,0x2140323232327d50LL} + +#define CALL_DUMMY_START_OFFSET 0 + +/* 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 *)((char *) dummyname + 4) = nargs; \ + *(int *)((char *) dummyname + 10) = fun; } + +/* Defs to read soff symbol tables, see dbxread.c */ + +#define NUMBER_OF_SYMBOLS ((long) opthdr.o_nsyms) +#define STRING_TABLE_OFFSET ((long) filehdr.h_strptr) +#define SYMBOL_TABLE_OFFSET ((long) opthdr.o_symptr) +#define STRING_TABLE_SIZE ((long) filehdr.h_strsiz) +#define SIZE_OF_TEXT_SEGMENT ((long) txthdr.s_size) +#define ENTRY_POINT ((long) opthdr.o_entry) + +#define READ_STRING_TABLE_SIZE(BUFFER) \ + (BUFFER = STRING_TABLE_SIZE) + +#define DECLARE_FILE_HEADERS \ + FILEHDR filehdr; \ + OPTHDR opthdr; \ + SCNHDR txthdr + +#define READ_FILE_HEADERS(DESC,NAME) \ +{ \ + int n; \ + val = myread (DESC, &filehdr, sizeof filehdr); \ + if (val < 0) \ + perror_with_name (NAME); \ + if (! IS_SOFF_MAGIC (filehdr.h_magic)) \ + error ("%s: not an executable file.", NAME); \ + lseek (DESC, 0L, 0); \ + if (myread (DESC, &filehdr, sizeof filehdr) < 0) \ + perror_with_name (NAME); \ + if (myread (DESC, &opthdr, filehdr.h_opthdr) <= 0) \ + perror_with_name (NAME); \ + for (n = 0; n < filehdr.h_nscns; n++) \ + { \ + if (myread (DESC, &txthdr, sizeof txthdr) < 0) \ + perror_with_name (NAME); \ + if ((txthdr.s_flags & S_TYPMASK) == S_TEXT) \ + break; \ + } \ +} + +/* Interface definitions for kernel debugger KDB. */ + +/* (no kdb) */ diff --git a/gdb/m-aux.h b/gdb/m-hp300bsd.h similarity index 82% rename from gdb/m-aux.h rename to gdb/m-hp300bsd.h index fbc7ca0855..ae0568a5ba 100644 --- a/gdb/m-aux.h +++ b/gdb/m-hp300bsd.h @@ -1,53 +1,53 @@ -/* Parameters for execution on A/UX, for GDB, the GNU debugger. - Copyright (C) 1989 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! -*/ - -#ifndef aux -#define aux -#endif - -/* It's a USG system */ -#define USG +/* Parameters for execution on a Hewlett-Packard 9000/300, running bsd. + Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc. -/* Assembler instructions in USG "SGS" (sw generation system) format */ -#define USG_SGS_ASM +This file is part of GDB. -/* Debugger information will be in COFF format. */ -#define COFF_FORMAT -#define COFF_NO_LONG_FILE_NAMES +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. -/* Terminal interface via termio */ -#define HAVE_TERMIO +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. -/* Unisoft fucked up the include files */ -#define UNISOFT_ASSHOLES +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. */ -/* Big or Little-Endian target machine - BITS: defined if bit #0 is the high-order bit of a byte. - BYTES:defined if byte#0 is the high-order byte of an int. - WORDS:defined if word#0 is the high-order word of a double. */ +/* Describe the endian nature of this machine. */ #define BITS_BIG_ENDIAN -#define BYTES_BIG_ENDIAN +#define BYTES_BIG_ENDIAN #define WORDS_BIG_ENDIAN -/* Floating point is IEEE compatible */ -#define IEEE_FLOAT +/* + * Configuration file for HP9000/300 series machine running + * University of Utah's 4.3bsd port. This is NOT for HP-UX. + * Problems to hpbsd-bugs@cs.utah.edu + */ + +#ifndef hp300 +#define hp300 +#endif + +/* Watch out for NaNs */ + +#define IEEE_FLOAT + +/* 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 + +/* Debugger information will be in DBX format. */ + +#define READ_DBX_FORMAT /* Offset from address of function to start of its code. Zero on most machines. */ @@ -73,34 +73,36 @@ anyone else from sharing it farther. Help stamp out software hoarding! #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 0x00917000 + /* Address of end of stack space. */ -#define STACK_END_ADDR 0x20000000 +#define STACK_END_ADDR 0xfff00000 /* Stack grows downward. */ #define INNER_THAN < /* Sequence of bytes for breakpoint instruction. */ -/* A/UX uses "trap &1" */ -#define BREAKPOINT {0x4e, 0x41} +#define BREAKPOINT {0x4e, 0x42} /* 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 0 +#define DECR_PC_AFTER_BREAK 2 /* Nonzero if instruction at PC is a return instruction. */ #define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e75) /* Return 1 if P points to an invalid floating point value. */ -/* FIXME, it's not clear what "invalid" means here. I take it to mean - "something that coredumps gdb if gdb tries to manipulate it" */ -#define INVALID_FLOAT(p, len) is_nan(p, len) +#define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */ /* Largest integer type */ #define LONGEST long @@ -121,7 +123,7 @@ read_memory_integer (read_register (SP_REGNUM), 4) #define REGISTER_NAMES \ {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \ - "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \ + "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp", \ "ps", "pc", \ "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \ "fpcontrol", "fpstatus", "fpiaddr" } @@ -139,31 +141,11 @@ read_memory_integer (read_register (SP_REGNUM), 4) #define PC_REGNUM 17 /* Contains program counter */ #define FP0_REGNUM 18 /* Floating point register 0 */ #define FPC_REGNUM 26 /* 68881 control register */ +#define FPS_REGNUM 27 /* 68881 status register */ -/* This is a piece of magic that is given a register number REGNO - and as BLOCKEND the address in the system of the end of the user structure - and stores in ADDR the address in the kernel or core dump - of that register. */ - -#define REGISTER_U_ADDR(addr, blockend, regno) { \ - struct user u; \ - if (regno <= SP_REGNUM) \ - addr = blockend + regno * 4; \ - else if (regno == PS_REGNUM) \ - addr = blockend + RPS * 4; /* From reg.h */ \ - else if (regno == PC_REGNUM) \ - addr = blockend + PC * 4; /* From reg.h */ \ - else if (regno < FPC_REGNUM) \ - addr = (char *) u.u_fpdreg [regno-FP0_REGNUM] - (char *)&u; \ - else \ - addr = (char *)&u.u_fpsysreg[regno-FPC_REGNUM] - (char *)&u; \ -} - -/* Describe the pointer in each stack frame to the previous stack frame - (its caller). */ /* Total amount of space needed to store our copies of the machine's register state, the array `registers'. */ -#define REGISTER_BYTES (16*4+8*12+8+20) +#define REGISTER_BYTES (16*4+8*12+8+12) /* Index within `registers' of the first byte of the space for register N. */ @@ -249,6 +231,34 @@ read_memory_integer (read_register (SP_REGNUM), 4) #define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF)) +/* Compensate for lack of `vprintf' function. */ +#ifndef HAVE_VPRINTF +#define vprintf(format, ap) _doprnt (format, ap, stdout) +#endif /* not HAVE_VPRINTF */ + +/* This is a piece of magic that is given a register number REGNO + and as BLOCKEND the address in the system of the end of the user structure + and stores in ADDR the address in the kernel or core dump + of that register. */ + +#define REGISTER_U_ADDR(addr, blockend, regno) \ +{ \ + if (regno < PS_REGNUM) \ + addr = (int) &((struct frame *)(blockend))->f_regs[regno]; \ + else if (regno == PS_REGNUM) \ + addr = (int) &((struct frame *)(blockend))->f_stackadj; \ + else if (regno == PC_REGNUM) \ + addr = (int) &((struct frame *)(blockend))->f_pc; \ + else if (regno < FPC_REGNUM) \ + addr = (int) \ + &((struct user *)0)->u_pcb.pcb_fpregs.fpf_regs[((regno)-FP0_REGNUM)*3];\ + else if (regno == FPC_REGNUM) \ + addr = (int) &((struct user *)0)->u_pcb.pcb_fpregs.fpf_fpcr; \ + else if (regno == FPS_REGNUM) \ + addr = (int) &((struct user *)0)->u_pcb.pcb_fpregs.fpf_fpsr; \ + else \ + addr = (int) &((struct user *)0)->u_pcb.pcb_fpregs.fpf_fpiar; \ +} /* Describe the pointer in each stack frame to the previous stack frame (its caller). */ @@ -263,18 +273,27 @@ read_memory_integer (read_register (SP_REGNUM), 4) it means the given frame is the outermost one and has no caller. In that case, FRAME_CHAIN_COMBINE is not used. */ -/* In the case of the 68k, the frame's nominal address +/* In the case of the Sun, the frame's nominal address is the address of a 4-byte word containing the calling frame's address. */ -#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4)) +#define FRAME_CHAIN(thisframe) \ + (outside_startup_file ((thisframe)->pc) ? \ + read_memory_integer ((thisframe)->frame, 4) :\ + 0) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (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) @@ -321,7 +340,7 @@ read_memory_integer (read_register (SP_REGNUM), 4) int nextinsn; \ bzero (&frame_saved_regs, sizeof frame_saved_regs); \ if ((frame_info)->pc >= (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \ - && (frame_info)->pc <= (frame_info)->frame) \ + && (frame_info)->pc <= (frame_info)->frame) \ { next_addr = (frame_info)->frame; \ pc = (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\ else \ @@ -408,7 +427,7 @@ read_memory_integer (read_register (SP_REGNUM), 4) register CORE_ADDR fp; \ register int regnum; \ struct frame_saved_regs fsr; \ - struct frame_info *fi; \ + struct frame_info *fi; \ char raw_buffer[12]; \ fi = get_frame_info (frame); \ fp = fi->frame; \ @@ -440,7 +459,7 @@ read_memory_integer (read_register (SP_REGNUM), 4) the following jsr instruction. *../ jsr @#32323232 addl #69696969,sp - trap #15 + trap #2 nop Note this is 28 bytes. We actually start executing at the jsr, since the pushing of the @@ -451,7 +470,7 @@ But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done, and we cannot allow the moveml to push the registers again lest they be taken for the arguments. */ -#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71} +#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e424e71} #define CALL_DUMMY_LENGTH 28 diff --git a/gdb/m-hp9k320.h b/gdb/m-hp9k320.h index 460e30d4ab..372547611f 100644 --- a/gdb/m-hp9k320.h +++ b/gdb/m-hp9k320.h @@ -1,34 +1,41 @@ /* Parameters for execution on an HP 9000 model 320, for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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 #ifndef HP9K320 #define HP9K320 #endif +/* Define this to indicate problems with traps after continuing. */ +#define HP_OS_BUG + /* Set flag to indicate whether HP's assembler is in use. */ -#ifdef __GNU__ +#ifdef __GNUC__ #ifdef __HPUX_ASM__ -#define USG_SGS_ASM +#define HPUX_ASM #endif #else -#define USG_SGS_ASM +#define HPUX_ASM #endif /* Define this for versions of hp-ux older than 6.0 */ @@ -40,8 +47,10 @@ anyone else from sharing it farther. Help stamp out software hoarding! #define HAVE_TERMIO /* Get rid of any system-imposed stack limit if possible. */ - +/* The hp9k320.h doesn't seem to have this feature. */ /* #define SET_STACK_LIMIT_HUGE */ +/* So we'll just have to avoid big alloca's. */ +#define BROKEN_LARGE_ALLOCA /* Define this if the C compiler puts an underscore at the front of external names before giving them to the linker. */ @@ -248,11 +257,6 @@ read_memory_integer (read_register (SP_REGNUM), 4) ? (&u.u_pcb.pcb_mc68881[FMC68881_R0 + (((regno) - FP0_REGNUM) * 3)]) \ : (&u.u_pcb.pcb_mc68881[FMC68881_C + ((regno) - FPC_REGNUM)]))) \ - ((char *) (& u))) - -/* It is safe to look for symsegs on a Sun, because Sun's ld - does not screw up with random garbage at end of file. */ - -#define READ_GDB_SYMSEGS /* Describe the pointer in each stack frame to the previous stack frame (its caller). */ @@ -270,15 +274,24 @@ read_memory_integer (read_register (SP_REGNUM), 4) /* In the case of the Sun, the frame's nominal address is the address of a 4-byte word containing the calling frame's address. */ -#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4)) +#define FRAME_CHAIN(thisframe) \ + (outside_startup_file ((thisframe)->pc) ? \ + read_memory_integer ((thisframe)->frame, 4) : \ + 0) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (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) diff --git a/gdb/m-i386-sysv3.2.h b/gdb/m-i386-sysv3.2.h new file mode 100644 index 0000000000..38fb4eb6d5 --- /dev/null +++ b/gdb/m-i386-sysv3.2.h @@ -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 diff --git a/gdb/m-i386.h b/gdb/m-i386.h index f7d9cd2a40..68df8680f2 100644 --- a/gdb/m-i386.h +++ b/gdb/m-i386.h @@ -1,27 +1,32 @@ +/* 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 */ -/* - Copyright (C) 1986, 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! -*/ #ifndef i386 #define i386 @@ -255,15 +260,24 @@ anyone else from sharing it farther. Help stamp out software hoarding! 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) (read_memory_integer ((thisframe)->frame, 4)) +#define FRAME_CHAIN(thisframe) \ + (outside_startup_file ((thisframe)->pc) ? \ + read_memory_integer ((thisframe)->frame, 4) :\ + 0) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (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) diff --git a/gdb/m-i386gas-sysv3.2.h b/gdb/m-i386gas-sysv3.2.h new file mode 100644 index 0000000000..3d69eea184 --- /dev/null +++ b/gdb/m-i386gas-sysv3.2.h @@ -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 diff --git a/gdb/m-i386gas.h b/gdb/m-i386gas.h index 79a7083127..fbd21385cc 100644 --- a/gdb/m-i386gas.h +++ b/gdb/m-i386gas.h @@ -1,3 +1,22 @@ +/* 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 @@ -5,25 +24,6 @@ * i386gnu: COFF_ENCAPSULATE */ -/* - Copyright (C) 1986, 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! -*/ #define COFF_ENCAPSULATE diff --git a/gdb/m-isi.h b/gdb/m-isi.h index a78cc43260..32ac916611 100644 --- a/gdb/m-isi.h +++ b/gdb/m-isi.h @@ -1,66 +1,35 @@ -/* -Date: Thu, 2 Apr 87 00:02:42 EST -From: crl@maxwell.physics.purdue.edu (Charles R. LaBrec) -Message-Id: <8704020502.AA01744@maxwell.physics.purdue.edu> -To: bug-gdb@prep.ai.mit.edu -Subject: gdb for ISI Optimum V - -Here is an m-isi-ov.h file for gdb version 2.1. It supports the 68881 -registers, and tracks down the function prologue (since the ISI cc -puts it at the end of the function and branches to it if not -optimizing). Also included are diffs to core.c, findvar.c, and -inflow.c, since the original code assumed that registers are an int in -the user struct, which isn't the case for 68020's with 68881's (and -not using the NEW_SUN_PTRACE). I have not fixed the bugs associated -with the other direction (writing registers back to the user struct). -I have also included a diff that turns m68k-pinsn.c into isi-pinsn.c, -which is needed since the 3.05 release of as does not understand -floating point ops, and it compiles incorrectly under "cc -20" - -I have used gdb for a while now, and it seems to work relatively well, -but I do not guarantee that it is perfect. The more that use it, the -faster the bugs will get shaken out. One bug I know of is not in gdb, -but in the assembler. It seems to screw up the .stabs of variables. -For externs, this is not important since gdb uses the global symbol -value, but for statics, this makes gdb unable to find them. I am -currently trying to track it down. - -As an aside, I notice that only global functions are used as symbols -to print as relative addresses, i.e. "", and not -static functions, which end up printing as large offsets from the last -global one. Would there be a problem if static functions were also -recorded as misc functions in read_dbx_symtab? - -Charles LaBrec -crl @ maxwell.physics.purdue.edu - - Definitions to make GDB run on a ISI Optimum V (3.05) under 4.2bsd. - - 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! -*/ +/* Definitions to make GDB run on an ISI Optimum V (3.05) under 4.3bsd. + Copyright (C) 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. */ + +/* This has not been tested on ISI's running BSD 4.2, but it will probably + work. */ /* Identify this machine */ #ifndef ISI68K #define ISI68K #endif +/* Define the bit, byte, and word ordering of the machine. */ +#define BITS_BIG_ENDIAN +#define BYTES_BIG_ENDIAN +#define WORDS_BIG_ENDIAN + /* Define this if the C compiler puts an underscore at the front of external names before giving them to the linker. */ @@ -104,11 +73,13 @@ 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 0x10800000 +/*#define KERNEL_U_ADDR 0x10800000*/ +#define KERNEL_U_ADDR 0 /* Address of end of stack space. */ -#define STACK_END_ADDR 0x10000000 +/*#define STACK_END_ADDR 0x10000000*/ +#define STACK_END_ADDR 0xfffe000 /* Stack grows downward. */ @@ -130,7 +101,7 @@ read_memory_integer (read_register (SP_REGNUM), 4) /* Amount PC must be decremented by after a breakpoint. This is often the number of bytes in BREAKPOINT - but not always. + but not always. On the ISI, the kernel resets the pc to the trap instr */ #define DECR_PC_AFTER_BREAK 0 @@ -154,7 +125,6 @@ read_memory_integer (read_register (SP_REGNUM), 4) #define REGISTER_TYPE long /* Number of machine registers */ - #define NUM_REGS 29 /* Initializer for an array of names of registers. @@ -181,23 +151,15 @@ read_memory_integer (read_register (SP_REGNUM), 4) #define FP0_REGNUM 18 /* Floating point register 0 */ #define FPC_REGNUM 26 /* 68881 control register */ -#ifdef BSD43_ISI40D -#define BLOCKFUDGE 0x400000 -#else -#define BLOCKFUDGE 0 -#endif -#define REGISTER_U_ADDR(addr, blockend, regno) \ -{ blockend -= BLOCKFUDGE; \ - if (regno < 2) addr = blockend - 0x18 + regno * 4; \ - else if (regno < 8) addr = blockend - 0x54 + regno * 4; \ - else if (regno < 10) addr = blockend - 0x30 + regno * 4;\ - else if (regno < 15) addr = blockend - 0x5c + regno * 4;\ - else if (regno < 16) addr = blockend - 0x1c; \ - else if (regno < 18) addr = blockend - 0x44 + regno * 4;\ - else if (regno < 26) addr = (int) ((struct user *)0)->u_68881_regs \ - + (regno - 18) * 12; \ - else if (regno < 29) addr = (int) ((struct user *)0)->u_68881_regs \ - + 8 * 12 + (regno - 26) * 4; \ +/* expects blockend to be u.u_ar0 */ +extern int rloc[]; /* Defined in isi-dep.c */ +#define REGISTER_U_ADDR(addr, blockend, regno) \ +{ blockend &= UPAGES*NBPG - 1; \ + if (regno < 18) addr = (int)blockend + rloc[regno]*4; \ + else if (regno < 26) addr = (int) &((struct user *)0)->u_68881_regs \ + + (regno - 18) * 12; \ + else if (regno < 29) addr = (int) &((struct user *)0)->u_68881_regs \ + + 8 * 12 + (regno - 26) * 4; \ } /* Total amount of space needed to store our copies of the machine's @@ -302,15 +264,24 @@ read_memory_integer (read_register (SP_REGNUM), 4) /* In the case of the ISI, the frame's nominal address is the address of a 4-byte word containing the calling frame's address. */ -#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4)) +#define FRAME_CHAIN(thisframe) \ + (outside_startup_file ((thisframe)->pc) ? \ + read_memory_integer ((thisframe)->frame, 4) :\ + 0) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (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) @@ -411,8 +382,10 @@ retry: \ (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4; \ } -/* Compensate for lack of `vprintf' function. */ -#define vprintf(format, ap) _doprnt (format, ap, stdout) +/* Compensate for lack of `vprintf' function. */ +#ifndef HAVE_VPRINTF +#define vprintf(format, ap) _doprnt (format, ap, stdout) +#endif /* Things needed for making the inferior call functions. */ @@ -468,7 +441,7 @@ retry: \ movew ccr,-(sp) /..* The arguments are pushed at this point by GDB; no code is needed in the dummy for this. - The CALL_DUMMY_START_OFFSET gives the position of + The CALL_DUMMY_START_OFFSET gives the position of the following jsr instruction. *../ jsr @#32323232 addl #69696969,sp diff --git a/gdb/m-merlin.h b/gdb/m-merlin.h index 196d73458a..ef8d1ec363 100644 --- a/gdb/m-merlin.h +++ b/gdb/m-merlin.h @@ -1,27 +1,31 @@ /* Definitions to make GDB run on a merlin under utek 2.1 - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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. */ #ifndef ns16000 #define ns16000 #endif +/* Define the bit, byte, and word ordering of the machine. */ +/* #define BITS_BIG_ENDIAN */ +/* #define BYTES_BIG_ENDIAN */ +/* #define WORDS_BIG_ENDIAN */ + # include /* Define this if the C compiler puts an underscore at the front @@ -265,10 +269,13 @@ anyone else from sharing it farther. Help stamp out software hoarding! /* In the case of the Merlin, the frame's nominal address is the FP value, and at that address is saved previous FP value as a 4-byte word. */ -#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4)) +#define FRAME_CHAIN(thisframe) \ + (outside_startup_file ((thisframe)->pc) ? \ + read_memory_integer ((thisframe)->frame, 4) :\ + 0) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe)))) #define FRAME_CHAIN_COMBINE(chain, thisframe) (chain) @@ -337,8 +344,10 @@ anyone else from sharing it farther. Help stamp out software hoarding! (frame_saved_regs).regs[FP_REGNUM] \ = read_memory_integer ((frame_info)->frame, 4); } -/* Compensate for lack of `vprintf' function. */ -#define vprintf(format, ap) _doprnt (format, ap, stdout) +/* Compensate for lack of `vprintf' function. */ +#ifndef HAVE_VPRINTF +#define vprintf(format, ap) _doprnt (format, ap, stdout) +#endif /* not HAVE_VPRINTF */ /* Things needed for making the inferior call functions. */ @@ -374,7 +383,7 @@ anyone else from sharing it farther. Help stamp out software hoarding! write_register (SP_REGNUM, fp + 8); \ flush_cached_frames (); \ set_current_frame (create_new_frame (read_register (FP_REGNUM),\ - read_pc ())); + read_pc ())); \ } /* This sequence of words is the instructions diff --git a/gdb/m-news.h b/gdb/m-news.h index 4edf5944c9..25e0551477 100644 --- a/gdb/m-news.h +++ b/gdb/m-news.h @@ -1,42 +1,63 @@ /* Parameters for execution on a Sony/NEWS, for GDB, the GNU debugger. - Probably ths parameters is match as news800, news700 and news900. + Copyright (C) 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. */ + +/* See following cpu type determination macro to get the machine type. + +Here is an m-news.h file for gdb. It supports the 68881 registers. + by hikichi@srava.sra.junet + +* Support Sun assembly format instead of Motorola one. +* Ptrace for handling floating register has a bug(before NEWS OS version 2.2), +* After NEWS OS version 3.2, some of ptrace's bug is fixed. + But we cannot change the floating register(see adb(1) in OS 3.2) yet. Here is an m-news800.h file for gdb version 2.6. It supports the 68881 registers. -(hikichi@srava.sra.junet or hikichi%srava.sra.junet%kddlabs@uunet.uu.net - and now hikichi@wheaties.ai.mit.edu) -* Now(9/2 '87) NEWS's printf has a bug. -* And support Sun assembly format instead of Motorola one. -* Probably not well support floating registers from core file rarely that -I do not know detail. -* Ptrace for handling floating register has a bug(7/3 '87), but not fixed -yet. We cannot write floating register. - - 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! -*/ - /* Identify this machine */ -#ifndef news800 -#define news800 +#ifndef sony_news +#define sony_news #endif +/* determine the cpu type from machine type. */ +#if defined(news1500)||defined(news1700)||defined(news1800)||defined(news1900) +# ifndef mc68020 +# define mc68020 +# endif /* not def mc68020 */ +# ifndef mc68030 +# define mc68030 +# endif /* not def mc68030 */ +#else /* 1000 Series */ +# if defined(news700)||defined(news800)||defined(news900) +# ifndef mc68020 +# define mc68020 +# endif +# else /* 800 Series */ +/* unkown model ? */ +# endif /* 800 Series */ +#endif /* 1000 Series */ + +/* Define the bit, byte, and word ordering of the machine. */ +#define BITS_BIG_ENDIAN +#define BYTES_BIG_ENDIAN +#define WORDS_BIG_ENDIAN + /* Use GNU assembler instead of standard assembler */ #define USE_GAS @@ -45,6 +66,15 @@ anyone else from sharing it farther. Help stamp out software hoarding! #define MOTOROLA #endif +/* Doesn't have siginterrupt. */ +#define NO_SIGINTERRUPT + +#define HAVE_WAIT_STRUCT + +/* 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. */ @@ -53,6 +83,10 @@ anyone else from sharing it farther. Help stamp out software hoarding! /* Symbols on this machine are in DBX format. */ #define READ_DBX_FORMAT +/* We can't use "isatty" or "fileno" on this machine. This isn't good, + but it will have to do. */ +#define ISATTY(FP) ((FP) == stdin || (FP) == stdout) + /* Offset from address of function to start of its code. Zero on most machines. */ @@ -85,7 +119,7 @@ read_memory_integer (read_register (SP_REGNUM), 4) /* Address of end of stack space. */ -#define STACK_END_ADDR (0x80000000 - ctob(UPAGES + 1)) +#define STACK_END_ADDR (0x80000000 - (UPAGES+CLSIZE)*NBPG) /* Stack grows downward. */ @@ -147,6 +181,8 @@ read_memory_integer (read_register (SP_REGNUM), 4) #define FP0_REGNUM 18 /* Floating point register 0 */ #define FPC_REGNUM 26 /* 68881 control register */ +/* before NEWSOS version 2.2 or more. If you have a new OS, + redefine this macro in 'see m-newsos3.h'. */ #define REGISTER_U_ADDR(addr, blockend, regno) \ { if (regno <= FP_REGNUM) \ addr = blockend + 4 + regno * 4; \ @@ -155,7 +191,7 @@ read_memory_integer (read_register (SP_REGNUM), 4) else if (regno <= PS_REGNUM) \ addr = blockend + (regno - PS_REGNUM) * 4; \ else if (regno < FPC_REGNUM) \ - addr = blockend + 4 + 4 * 14 + 4 * 5 + (regno - FP0_REGNUM) * 12; \ + addr = blockend + 4 + 4 * 14 + 4 * 4 + (regno - FP0_REGNUM) * 12; \ else \ addr = blockend + 4 + 4 * 16 + (regno - FPC_REGNUM) * 4; \ } @@ -231,14 +267,30 @@ read_memory_integer (read_register (SP_REGNUM), 4) a function return value of type TYPE, and copy that, in virtual format, into VALBUF. */ +/* when it return the floating value, use the FP0 in NEWS. */ #define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \ - bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE)) + { if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \ + { \ + REGISTER_CONVERT_TO_VIRTUAL (FP0_REGNUM, \ + ®BUF[REGISTER_BYTE (FP0_REGNUM)], VALBUF); \ + } \ + else \ + bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE)); } /* Write into appropriate registers a function return value of type TYPE, given in virtual format. */ +/* when it return the floating value, use the FP0 in NEWS. */ #define STORE_RETURN_VALUE(TYPE,VALBUF) \ - write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE)) + { if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \ + { \ + char raw_buf[REGISTER_RAW_SIZE (FP0_REGNUM)]; \ + REGISTER_CONVERT_TO_RAW (FP0_REGNUM, VALBUF, raw_buf); \ + write_register_bytes (FP0_REGNUM, \ + raw_buf, REGISTER_RAW_SIZE (FP0_REGNUM)); \ + } \ + else \ + 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, @@ -246,8 +298,10 @@ read_memory_integer (read_register (SP_REGNUM), 4) #define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF)) -/* Compensate for lack of `vprintf' function. */ -#define vprintf(format, ap) _doprnt (format, ap, stdout) +/* Compensate for lack of `vprintf' function. */ +#ifndef HAVE_VPRINTF +#define vprintf(format, ap) _doprnt (format, ap, stdout) +#endif /* not HAVE_VPRINTF */ /* Describe the pointer in each stack frame to the previous stack frame (its caller). */ @@ -265,15 +319,24 @@ read_memory_integer (read_register (SP_REGNUM), 4) /* In the case of the NEWS, the frame's nominal address is the address of a 4-byte word containing the calling frame's address. */ -#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4)) +#define FRAME_CHAIN(thisframe) \ + (outside_startup_file ((thisframe)->pc) ? \ + read_memory_integer ((thisframe)->frame, 4) :\ + 0) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (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) @@ -311,8 +374,7 @@ read_memory_integer (read_register (SP_REGNUM), 4) register int regmask; \ register CORE_ADDR next_addr; \ register CORE_ADDR pc; \ - register int insn; \ - register int offset; \ + int nextinsn; \ bzero (&frame_saved_regs, sizeof frame_saved_regs); \ if ((frame_info)->pc >= (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \ && (frame_info)->pc <= (frame_info)->frame) \ @@ -320,53 +382,54 @@ read_memory_integer (read_register (SP_REGNUM), 4) pc = (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\ else \ { pc = get_pc_function_start ((frame_info)->pc); \ - /* Verify we have a link a6 instruction next, \ - or a branch followed by a link a6 instruction; \ + /* Verify we have a link a6 instruction next; \ if not we lose. If we win, find the address above the saved \ regs using the amount of storage from the link instruction. */\ -retry: \ - insn = read_memory_integer (pc, 2); \ - if (insn == 044016) \ - next_addr = (frame_info)->frame - read_memory_integer (pc += 2, 4), pc+=4; \ - else if (insn == 047126) \ - next_addr = (frame_info)->frame - read_memory_integer (pc += 2, 2), pc+=2; \ - else if ((insn & 0177400) == 060000) /* bra insn */ \ - { offset = insn & 0377; \ - pc += 2; /* advance past bra */ \ - if (offset == 0) /* bra #word */ \ - offset = read_memory_integer (pc, 2), pc += 2; \ - else if (offset == 0377) /* bra #long */ \ - offset = read_memory_integer (pc, 4), pc += 4; \ - pc += offset; \ - goto retry; \ - } else goto lose; \ + if (044016 == read_memory_integer (pc, 2)) \ + next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 4), pc+=4; \ + else if (047126 == read_memory_integer (pc, 2)) \ + next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 2), pc+=2; \ + else goto lose; \ /* If have an addal #-n, sp next, adjust next_addr. */ \ if ((0177777 & read_memory_integer (pc, 2)) == 0157774) \ next_addr += read_memory_integer (pc += 2, 4), pc += 4; \ } \ /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ \ - insn = read_memory_integer (pc, 2), pc += 2; \ - regmask = read_memory_integer (pc, 2); \ - if ((insn & 0177760) == 022700) /* movl rn, (sp) */ \ - (frame_saved_regs).regs[(insn&7) + ((insn&010)?8:0)] = next_addr; \ - else if ((insn & 0177760) == 024700) /* movl rn, -(sp) */ \ - (frame_saved_regs).regs[(insn&7) + ((insn&010)?8:0)] = next_addr-=4; \ - else if (insn == 0044327) /* moveml mask, (sp) */ \ - { pc += 2; \ - /* Regmask's low bit is for register 0, the first written */ \ - next_addr -= 4; \ + regmask = read_memory_integer (pc + 2, 2); \ + /* But before that can come an fmovem. Check for it. */ \ + nextinsn = 0xffff & read_memory_integer (pc, 2); \ + if (0xf227 == nextinsn \ + && (regmask & 0xff00) == 0xe000) \ + { pc += 4; /* Regmask's low bit is for register fp7, the first pushed */ \ + for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \ + if (regmask & 1) \ + (frame_saved_regs).regs[regnum] = (next_addr -= 12); \ + regmask = read_memory_integer (pc + 2, 2); } \ + if (0044327 == read_memory_integer (pc, 2)) \ + { pc += 4; /* Regmask's low bit is for register 0, the first written */ \ for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \ if (regmask & 1) \ - (frame_saved_regs).regs[regnum] = (next_addr += 4); \ - } else if (insn == 0044347) /* moveml mask, -(sp) */ \ - { pc += 2; \ - /* Regmask's low bit is for register 15, the first pushed */ \ + (frame_saved_regs).regs[regnum] = (next_addr += 4) - 4; } \ + else if (0044347 == read_memory_integer (pc, 2)) \ + { pc += 4; /* Regmask's low bit is for register 15, the first pushed */ \ for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \ if (regmask & 1) \ (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \ + else if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2))) \ + { regnum = 0xf & read_memory_integer (pc, 2); pc += 2; \ + (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \ + /* fmovemx to index of sp may follow. */ \ + regmask = read_memory_integer (pc + 2, 2); \ + nextinsn = 0xffff & read_memory_integer (pc, 2); \ + if (0xf236 == nextinsn \ + && (regmask & 0xff00) == 0xf000) \ + { pc += 10; /* Regmask's low bit is for register fp0, the first written */ \ + for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \ + if (regmask & 1) \ + (frame_saved_regs).regs[regnum] = (next_addr += 12) - 12; \ + regmask = read_memory_integer (pc + 2, 2); } \ /* clrw -(sp); movw ccr,-(sp) may follow. */ \ - if (read_memory_integer (pc, 2) == 041147 \ - && read_memory_integer (pc+2, 2) == 042347) \ + if (0x426742e7 == read_memory_integer (pc, 4)) \ (frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4); \ lose: ; \ (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 8; \ @@ -375,19 +438,17 @@ retry: \ } /* Things needed for making the inferior call functions. */ +/* On NEWS os 2.x ptrace cannot modify fp and floating registers. */ +#define PTRACE_BUG /* Push an empty stack frame, to record the current PC, etc. */ -#if 0 /* now these define is not used */ +/* now ptrace has a bug to write floating register in old OS */ #define PUSH_DUMMY_FRAME \ { register CORE_ADDR sp = read_register (SP_REGNUM); \ register int regnum; \ - char raw_buffer[12]; \ sp = push_word (sp, read_register (PC_REGNUM)); \ sp = push_word (sp, read_register (FP_REGNUM)); \ write_register (FP_REGNUM, sp); \ - for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \ - { read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \ - sp = push_bytes (sp, raw_buffer, 12); } \ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \ sp = push_word (sp, read_register (regnum)); \ sp = push_word (sp, read_register (PS_REGNUM)); \ @@ -401,14 +462,9 @@ retry: \ register int regnum; \ struct frame_saved_regs fsr; \ struct frame_info *fi; \ - char raw_buffer[12]; \ fi = get_frame_info (frame); \ fp = fi->frame; \ get_frame_saved_regs (fi, &fsr); \ - for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \ - if (fsr.regs[regnum]) \ - { read_memory (fsr.regs[regnum], raw_buffer, 12); \ - write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \ if (fsr.regs[regnum]) \ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \ @@ -420,44 +476,10 @@ retry: \ flush_cached_frames (); \ set_current_frame (create_new_frame (read_register (FP_REGNUM), \ read_pc ())); } -#else /* now ptrace has a bug to write floating register */ -#define PUSH_DUMMY_FRAME \ -{ register CORE_ADDR sp = read_register (SP_REGNUM); \ - register int regnum; \ - sp = push_word (sp, read_register (PC_REGNUM)); \ - sp = push_word (sp, read_register (FP_REGNUM)); \ - write_register (FP_REGNUM, sp); \ - for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \ - sp = push_word (sp, read_register (regnum)); \ - sp = push_word (sp, read_register (PS_REGNUM)); \ - write_register (SP_REGNUM, sp); } - -/* Discard from the stack the innermost frame, restoring all registers. */ -#define POP_FRAME \ -{ register FRAME frame = get_current_frame (); \ - register CORE_ADDR fp; \ - register int regnum; \ - struct frame_saved_regs fsr; \ - struct frame_info *fi; \ - fi = get_frame_info (frame); \ - fp = fi->frame; \ - get_frame_saved_regs (fi, &fsr); \ - for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \ - if (fsr.regs[regnum]) \ - write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \ - if (fsr.regs[PS_REGNUM]) \ - write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \ - write_register (FP_REGNUM, read_memory_integer (fp, 4)); \ - write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \ - write_register (SP_REGNUM, fp + 8); \ - flush_cached_frames (); \ - set_current_frame (create_new_frame (read_register (FP_REGNUM), \ - read_pc ())); } -#endif /* This sequence of words is the instructions fmove.m #,-(sp) - movem.l 0xfffc,-(sp) + movem.l 0xfffc,-(sp) ;; no save a6(fp) and a7(sp) clr.w -(sp) move.w ccr,-(sp) /..* The arguments are pushed at this point by GDB; diff --git a/gdb/m-newsos3.h b/gdb/m-newsos3.h new file mode 100644 index 0000000000..066b51b1ba --- /dev/null +++ b/gdb/m-newsos3.h @@ -0,0 +1,117 @@ +/* Parameters for execution on a Sony/NEWS with News-OS version 3, + for GDB, the GNU debugger. + 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. */ +#define NEWSOS3 +#include "m-news.h" + +#undef STACK_END_ADDR +/* USRSTACK */ +#define STACK_END_ADDR (0x80000000 - UPAGES*NBPG) + +/* Have siginterupt on NEWS OS 3.x. */ +#undef NO_SIGINTERRUPT + +#undef USE_PCB + +/* now old ptrace bug has fixed almost. Remain constrain is; + When some process do not touch the floating register, + ptrace cannot change the floating register containts. +*/ +#undef PTRACE_BUG + +#undef PUSH_DUMMY_FRAME +#undef POP_FRAME +/* now ptrace has a bug to write floating register in NEWS OS version 2.x */ +#define PUSH_DUMMY_FRAME \ +{ register CORE_ADDR sp = read_register (SP_REGNUM); \ + register int regnum; \ + char raw_buffer[12]; \ + sp = push_word (sp, read_register (PC_REGNUM)); \ + sp = push_word (sp, read_register (FP_REGNUM)); \ + write_register (FP_REGNUM, sp); \ + for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \ + { read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \ + sp = push_bytes (sp, raw_buffer, 12); } \ + for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \ + sp = push_word (sp, read_register (regnum)); \ + sp = push_word (sp, read_register (PS_REGNUM)); \ + write_register (SP_REGNUM, sp); } + +/* Discard from the stack the innermost frame, restoring all registers. */ + +#define POP_FRAME \ +{ register FRAME frame = get_current_frame (); \ + register CORE_ADDR fp; \ + register int regnum; \ + struct frame_saved_regs fsr; \ + struct frame_info *fi; \ + char raw_buffer[12]; \ + fi = get_frame_info (frame); \ + fp = fi->frame; \ + get_frame_saved_regs (fi, &fsr); \ + for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \ + if (fsr.regs[regnum]) \ + { read_memory (fsr.regs[regnum], raw_buffer, 12); \ + write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\ + for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \ + if (fsr.regs[regnum]) \ + write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \ + if (fsr.regs[PS_REGNUM]) \ + write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \ + write_register (FP_REGNUM, read_memory_integer (fp, 4)); \ + write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \ + write_register (SP_REGNUM, fp + 8); \ + flush_cached_frames (); \ + set_current_frame (create_new_frame (read_register (FP_REGNUM), \ + read_pc ())); } + +/* NewsOS 3 apparently dies on large alloca's -- roland@ai.mit.edu. */ +#define BROKEN_LARGE_ALLOCA + +/* Make this macro from peep of core file. */ +#undef REGISTER_U_ADDR +#ifdef USE_PCB +#define REGISTER_U_ADDR(addr, blockend, regno) \ +{ blockend += 4; /* why? */ \ + if (regno <= FP_REGNUM) \ + addr = blockend + regno * 4; \ + else if (regno == SP_REGNUM) \ + addr = blockend - 4 - 4 * 4; \ + else if (regno <= PS_REGNUM) \ + addr = blockend - 4 + (regno - PS_REGNUM) * 4; \ + else if (regno < FPC_REGNUM) \ + addr = blockend + (14 + 1 + 3) * 4 + (regno - FP0_REGNUM) * 12; \ + else \ + addr = blockend + 15 * 4 + (regno - FPC_REGNUM) * 4; \ +} +#else +#define REGISTER_U_ADDR(addr, blockend, regno) \ +{ blockend += 4; /* why? */ \ + if (regno <= FP_REGNUM) \ + addr = blockend + regno * 4; \ + else if (regno == SP_REGNUM) \ + addr = blockend -4 - 4 * 4; \ + else if (regno <= PS_REGNUM) \ + addr = blockend - 4 + (regno - PS_REGNUM) * 4; \ + else if (regno < FPC_REGNUM) \ + addr = blockend + (14 + 1 + 3) * 4 + (regno - FP0_REGNUM) * 12; \ + else \ + addr = blockend + 15 * 4 + (regno - FPC_REGNUM) * 4; \ +} +#endif diff --git a/gdb/m-npl.h b/gdb/m-npl.h index d2ceef9e5d..3d98284f8d 100644 --- a/gdb/m-npl.h +++ b/gdb/m-npl.h @@ -1,25 +1,34 @@ /* Parameters for execution on a Gould NP1, for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 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. +This file is part of GDB. -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. +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. -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! */ +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 /* This code appears in libraries on Gould machines. Ignore it. */ #define IGNORE_SYMBOL(type) (type == N_ENTRY) +/* We don't want the extra gnu symbols on the machine; + they will interfere with the shared segment symbols. */ +#define NO_GNU_STABS + /* Macro for text-offset and data info (in NPL a.out format). */ #define TEXTINFO \ text_offset = N_TXTOFF (exec_coffhdr, exec_aouthdr); \ @@ -67,7 +76,9 @@ anyone else from sharing it farther. Help stamp out software hoarding! */ /* Define COFF and other symbolic names needed on NP1 */ #define NS32GMAGIC GNP1MAGIC #define NS32SMAGIC GPNMAGIC +#ifndef HAVE_VPRINTF #define vprintf printf +#endif /* not HAVE_VPRINTF */ /* Get rid of any system-imposed stack limit if possible. */ #define SET_STACK_LIMIT_HUGE diff --git a/gdb/m-pn.h b/gdb/m-pn.h index a5f7ea1fa1..ece16f4423 100644 --- a/gdb/m-pn.h +++ b/gdb/m-pn.h @@ -1,25 +1,34 @@ /* Parameters for execution on a Gould PN, for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 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. +This file is part of GDB. -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. +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. -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! */ +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 /* This code appears in libraries on Gould machines. Ignore it. */ #define IGNORE_SYMBOL(type) (type == N_ENTRY) +/* We don't want the extra gnu symbols on the machine; + they will interfere with the shared segment symbols. */ +#define NO_GNU_STABS + /* Macro for text-offset and data info (in PN a.out format). */ #define TEXTINFO \ text_offset = N_TXTOFF (exec_coffhdr); \ @@ -67,7 +76,9 @@ anyone else from sharing it farther. Help stamp out software hoarding! */ /* Define COFF and other symbolic names needed on NP1 */ #define NS32GMAGIC GDPMAGIC #define NS32SMAGIC PN_MAGIC +#ifndef HAVE_VPRINTF #define vprintf printf +#endif /* not HAVE_VPRINTF */ /* Get rid of any system-imposed stack limit if possible. */ #define SET_STACK_LIMIT_HUGE diff --git a/gdb/m-sparc.h b/gdb/m-sparc.h index 7cde3f1836..7615611a29 100644 --- a/gdb/m-sparc.h +++ b/gdb/m-sparc.h @@ -1,28 +1,34 @@ /* Parameters for execution on a Sun 4, for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@mcc.com) +This file is part of GDB. -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. +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. -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. +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. -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! -*/ +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. */ #ifndef sun4 #define sun4 #endif +/* Define the bit, byte, and word ordering of the machine. */ +#define BITS_BIG_ENDIAN +#define BYTES_BIG_ENDIAN +#define WORDS_BIG_ENDIAN + +/* Floating point is IEEE compatible. */ +#define IEEE_FLOAT + /* Get rid of any system-imposed stack limit if possible. */ #define SET_STACK_LIMIT_HUGE @@ -36,16 +42,16 @@ anyone else from sharing it farther. Help stamp out software hoarding! #define READ_DBX_FORMAT -/* Big or Little-Endian target machine - BITS: defined if bit #0 is the high-order bit of a byte. - BYTES:defined if byte#0 is the high-order byte of an int. - WORDS:defined if word#0 is the high-order word of a double. */ -#define BITS_BIG_ENDIAN -#define BYTES_BIG_ENDIAN -#define WORDS_BIG_ENDIAN +/* If Pcc says that a parameter is a short, it's a short. This is + because the parameter does get passed in in a register as an int, + but pcc puts it onto the stack frame as a short (not nailing + whatever else might be there. I'm not sure that I consider this + swift. Sigh.) -/* Floating point is IEEE compatible. */ -#define IEEE_FLOAT + No, don't do this. The problem here is that pcc says that the + argument is in the upper half of the word reserved on the stack, + but puts it in the lower half. */ +/* #define BELIEVE_PCC_PROMOTION 1 */ /* Offset from address of function to start of its code. Zero on most machines. */ @@ -73,10 +79,9 @@ anyone else from sharing it farther. Help stamp out software hoarding! #define SAVED_PC_AFTER_CALL(frame) PC_ADJUST (read_register (RP_REGNUM)) /* Address of end of stack space. */ - -#define STACK_END_ADDR 0xf8000000 - -/* Stack grows downward. */ +#include +#include +#define STACK_END_ADDR USRSTACK #define INNER_THAN < @@ -261,11 +266,6 @@ anyone else from sharing it farther. Help stamp out software hoarding! #define ATTACH_DETACH -/* It is safe to look for symsegs on a Sun, because Sun's ld - does not screw up with random garbage at end of file. */ - -#define READ_GDB_SYMSEGS - /* Describe the pointer in each stack frame to the previous stack frame (its caller). */ @@ -315,20 +315,19 @@ anyone else from sharing it farther. Help stamp out software hoarding! #define FRAME_CHAIN(thisframe) \ GET_RWINDOW_REG ((thisframe)->frame, rw_in[6]) -/* Avoid checking FRAME_SAVED_PC since that screws us due to - improperly set up saved PC on a signal trampoline call */ -#if 0 #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) -#else -#define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0) -#endif + (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) + /* Where is the PC for a specific frame */ #define FRAME_SAVED_PC(FRAME) frame_saved_pc (FRAME) @@ -375,8 +374,12 @@ anyone else from sharing it farther. Help stamp out software hoarding! FRAME fid = FRAME_INFO_ID (fi); \ if (!fid) fatal ("Bad frame info struct in FRAME_FIND_SAVED_REGS"); \ bzero (&(frame_saved_regs), sizeof (frame_saved_regs)); \ + /* Old test. \ if ((fi)->pc >= frame - CALL_DUMMY_LENGTH - 0x140 \ - && (fi)->pc <= frame) \ + && (fi)->pc <= frame) */ \ + if ((fi)->pc >= ((fi)->bottom ? (fi)->bottom : \ + read_register (SP_REGNUM)) \ + && (fi)->pc <= FRAME_FP(fi)) \ { \ for (regnum = 1; regnum < 8; regnum++) \ (frame_saved_regs).regs[regnum] = \ @@ -415,7 +418,7 @@ anyone else from sharing it farther. Help stamp out software hoarding! /* is accurate */ \ for (regnum = 30; regnum < 32; regnum++) \ (frame_saved_regs).regs[regnum] = frame + (regnum-16) * 4; \ - (frame_saved_regs).regs[SP_REGNUM] = frame; \ + (frame_saved_regs).regs[SP_REGNUM] = FRAME_FP (fi); \ (frame_saved_regs).regs[PC_REGNUM] = frame + 15*4; \ } diff --git a/gdb/m-sun2.h b/gdb/m-sun2.h index e42bc57d6c..97b18399c4 100644 --- a/gdb/m-sun2.h +++ b/gdb/m-sun2.h @@ -1,27 +1,31 @@ /* Parameters for execution on a Sun, for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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. */ #ifndef sun2 #define sun2 #endif +/* Define the bit, byte, and word ordering of the machine. */ +#define BITS_BIG_ENDIAN +#define BYTES_BIG_ENDIAN +#define WORDS_BIG_ENDIAN + /* Define this if the C compiler puts an underscore at the front of external names before giving them to the linker. */ @@ -229,15 +233,24 @@ read_memory_integer (read_register (SP_REGNUM), 4) /* In the case of the Sun, the frame's nominal address is the address of a 4-byte word containing the calling frame's address. */ -#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4)) +#define FRAME_CHAIN(thisframe) \ + (outside_startup_file ((thisframe)->pc) ? \ + read_memory_integer ((thisframe)->frame, 4) :\ + 0) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (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) @@ -368,7 +381,7 @@ read_memory_integer (read_register (SP_REGNUM), 4) movew ccr,-(sp) /..* The arguments are pushed at this point by GDB; no code is needed in the dummy for this. - The CALL_DUMMY_START_OFFSET gives the position of + The CALL_DUMMY_START_OFFSET gives the position of the following jsr instruction. *../ jsr @#32323232 addl #69696969,sp diff --git a/gdb/m-sun2os4.h b/gdb/m-sun2os4.h index 9a56ce51de..cb2f16fea3 100644 --- a/gdb/m-sun2os4.h +++ b/gdb/m-sun2os4.h @@ -1,2 +1,21 @@ +/* Macro definitions for a sun 2 running os 4. + 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-sun2.h" #define SUNOS4 diff --git a/gdb/m-sun3.h b/gdb/m-sun3.h index 1ac0ee1459..c6dee57f47 100644 --- a/gdb/m-sun3.h +++ b/gdb/m-sun3.h @@ -1,27 +1,31 @@ /* Parameters for execution on a Sun, for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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. */ #ifndef sun3 #define sun3 #endif +/* Define the bit, byte, and word ordering of the machine. */ +#define BITS_BIG_ENDIAN +#define BYTES_BIG_ENDIAN +#define WORDS_BIG_ENDIAN + /* Get rid of any system-imposed stack limit if possible. */ #define SET_STACK_LIMIT_HUGE @@ -45,9 +49,9 @@ anyone else from sharing it farther. Help stamp out software hoarding! #define SKIP_PROLOGUE(pc) \ { register int op = read_memory_integer (pc, 2); \ - if (op == 0047126) \ + if (op == 0047126) \ pc += 4; /* Skip link #word */ \ - else if (op == 0044016) \ + else if (op == 0044016) \ pc += 6; /* Skip link #long */ \ } @@ -78,8 +82,10 @@ read_memory_integer (read_register (SP_REGNUM), 4) #define DECR_PC_AFTER_BREAK 2 /* Nonzero if instruction at PC is a return instruction. */ +/* Allow any of the return instructions, including a trapv and a return + from interupt. */ -#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e75) +#define ABOUT_TO_RETURN(pc) ((read_memory_integer (pc, 2) & ~0x3) == 0x4e74) /* Return 1 if P points to an invalid floating point value. */ @@ -223,10 +229,6 @@ read_memory_integer (read_register (SP_REGNUM), 4) #define ATTACH_DETACH -/* It is safe to look for symsegs on a Sun, because Sun's ld - does not screw up with random garbage at end of file. */ - -#define READ_GDB_SYMSEGS /* Describe the pointer in each stack frame to the previous stack frame (its caller). */ @@ -244,15 +246,24 @@ read_memory_integer (read_register (SP_REGNUM), 4) /* In the case of the Sun, the frame's nominal address is the address of a 4-byte word containing the calling frame's address. */ -#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4)) +#define FRAME_CHAIN(thisframe) \ + (outside_startup_file ((thisframe)->pc) ? \ + read_memory_integer ((thisframe)->frame, 4) :\ + 0) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (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) @@ -382,29 +393,29 @@ read_memory_integer (read_register (SP_REGNUM), 4) restoring all saved registers. */ #define POP_FRAME \ -{ register FRAME frame = get_current_frame (); \ - register CORE_ADDR fp; \ - register int regnum; \ - struct frame_saved_regs fsr; \ - struct frame_info *fi; \ - char raw_buffer[12]; \ - fi = get_frame_info (frame); \ - fp = fi->frame; \ - get_frame_saved_regs (fi, &fsr); \ - for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \ - if (fsr.regs[regnum]) \ - { read_memory (fsr.regs[regnum], raw_buffer, 12); \ +{ register FRAME frame = get_current_frame (); \ + register CORE_ADDR fp; \ + register int regnum; \ + struct frame_saved_regs fsr; \ + struct frame_info *fi; \ + char raw_buffer[12]; \ + fi = get_frame_info (frame); \ + fp = fi->frame; \ + get_frame_saved_regs (fi, &fsr); \ + for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \ + if (fsr.regs[regnum]) \ + { read_memory (fsr.regs[regnum], raw_buffer, 12); \ write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\ - for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \ - if (fsr.regs[regnum]) \ + for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \ + if (fsr.regs[regnum]) \ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \ - if (fsr.regs[PS_REGNUM]) \ + if (fsr.regs[PS_REGNUM]) \ write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \ - write_register (FP_REGNUM, read_memory_integer (fp, 4)); \ - write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \ - write_register (SP_REGNUM, fp + 8); \ - flush_cached_frames (); \ - set_current_frame (create_new_frame (read_register (FP_REGNUM),\ + write_register (FP_REGNUM, read_memory_integer (fp, 4)); \ + write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \ + write_register (SP_REGNUM, fp + 8); \ + flush_cached_frames (); \ + set_current_frame (create_new_frame (read_register (FP_REGNUM), \ read_pc ())); } /* This sequence of words is the instructions diff --git a/gdb/m-sun3os4.h b/gdb/m-sun3os4.h index cd1821b990..cd9179abd9 100644 --- a/gdb/m-sun3os4.h +++ b/gdb/m-sun3os4.h @@ -1,3 +1,27 @@ +/* Macro definitions for a sun 3 running os 4. + 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-sun3.h" #define SUNOS4 #define FPU + +/* There is a bug which can cause alloca to fail to allocate large + areas of memory one time in every 4096 (we think). Hard to reproduce + so it will be hard to detect when this bug is fixed. */ +#define BROKEN_LARGE_ALLOCA diff --git a/gdb/m-sun4os4.h b/gdb/m-sun4os4.h index 3bed867583..c00ea13986 100644 --- a/gdb/m-sun4os4.h +++ b/gdb/m-sun4os4.h @@ -1,3 +1,24 @@ +/* Macro definitions for running gdb on a Sun 4 running sunos 4. + 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-sparc.h" +#undef STACK_END_ADDRESS +#define STACK_END_ADDRESS 0xf8000000 #define SUNOS4 #define FPU diff --git a/gdb/m-symmetry.h b/gdb/m-symmetry.h new file mode 100644 index 0000000000..1ebf54d682 --- /dev/null +++ b/gdb/m-symmetry.h @@ -0,0 +1,614 @@ +/* Definitions to make GDB run on a Sequent Symmetry under dynix 3.0, + with Weitek 1167 and i387 support. + 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. */ + +/* Symmetry version by Jay Vosburgh (uunet!sequent!fubar) */ + +#include + +#define SYMMETRY + +/* This machine doesn't have the siginterrupt call. */ +#define NO_SIGINTERRUPT + +#define HAVE_WAIT_STRUCT + +/* Define the bit, byte, and word ordering of the machine. */ +/* #define BITS_BIG_ENDIAN */ +/* #define BYTES_BIG_ENDIAN */ +/* #define WORDS_BIG_ENDIAN */ + +/* Define SFILE_FN_FLAGGED if the source file is flagged with an N_FN + symbol instead of an N_TEXT symbol. */ + +#define OFILE_FN_FLAGGED + +/* 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 + +/* Debugger information will be in DBX format. */ + +#define READ_DBX_FORMAT + +/* 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. From m-i386.h */ + +#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 (0x80000000 - (UPAGES * NBPG)) + +/* Address of end of stack space. */ + +#define STACK_END_ADDR (0x40000000 - (UPAGES * NBPG)) + +/* 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 0 + +/* Nonzero if instruction at PC is a return instruction. */ +/* For Symmetry, this is really the 'leave' instruction, which */ +/* is right before the ret */ + +#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0xc9) + +/* Return 1 if P points to an invalid floating point value. +*/ + +#define INVALID_FLOAT(p, len) (0) + +/* code for 80387 fpu. Functions are from i386-dep.c, copied into + * symm-dep.c. + */ +#define FLOAT_INFO { i386_float_info(); } + +/* largest int type */ +#define LONGEST long + +#define BUILTIN_TYPE_LONGEST builtin_type_long + + +/* Say how long (ordinary) registers are. */ + +#define REGISTER_TYPE long + +/* Number of machine registers */ +#define NUM_REGS 49 + +/* Initializer for an array of names of registers. + There should be NUM_REGS strings in this initializer. */ + +/* Symmetry registers are in this weird order to match the register + numbers in the symbol table entries. If you change the order, + things will probably break mysteriously for no apparent reason. + Also note that the st(0)...st(7) 387 registers are represented as + st0...st7. */ + +#define REGISTER_NAMES { "eax", "edx", "ecx", "st0", "st1", \ + "ebx", "esi", "edi", "st2", "st3", \ + "st4", "st5", "st6", "st7", "esp", \ + "ebp", "eip", "eflags", "fp1", "fp2", \ + "fp3", "fp4", "fp5", "fp6", "fp7", \ + "fp8", "fp9", "fp10", "fp11", "fp12", \ + "fp13", "fp14", "fp15", "fp16", "fp17", \ + "fp18", "fp19", "fp20", "fp21", "fp22", \ + "fp23", "fp24", "fp25", "fp26", "fp27", \ + "fp28", "fp29", "fp30", "fp31" } + +/* 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 FP1_REGNUM 18 /* first 1167 register */ +#define SP_REGNUM 14 /* Contains address of top of stack */ +#define FP_REGNUM 15 /* Contains address of executing stack frame */ +#define PC_REGNUM 16 /* Contains program counter */ +#define PS_REGNUM 17 /* Contains processor status */ + +/* The magic numbers below are offsets into u_ar0 in the user struct. + * They live in . Gdb calls this macro with blockend + * holding u.u_ar0 - KERNEL_U_ADDR. Only the registers listed are + * saved in the u area (along with a few others that aren't useful + * here. See ). + */ + +#define REGISTER_U_ADDR(addr, blockend, regno) \ +{ struct user foo; /* needed for finding fpu regs */ \ +switch (regno) { \ + case 0: \ + addr = blockend + EAX * sizeof(int); break; \ + case 1: \ + addr = blockend + EDX * sizeof(int); break; \ + case 2: \ + addr = blockend + ECX * sizeof(int); break; \ + case 3: /* st(0) */ \ + addr = blockend - \ + ((int)&foo.u_fpusave.fpu_stack[0][0] - (int)&foo); \ + break; \ + case 4: /* st(1) */ \ + addr = blockend - \ + ((int) &foo.u_fpusave.fpu_stack[1][0] - (int)&foo); \ + break; \ + case 5: \ + addr = blockend + EBX * sizeof(int); break; \ + case 6: \ + addr = blockend + ESI * sizeof(int); break; \ + case 7: \ + addr = blockend + EDI * sizeof(int); break; \ + case 8: /* st(2) */ \ + addr = blockend - \ + ((int) &foo.u_fpusave.fpu_stack[2][0] - (int)&foo); \ + break; \ + case 9: /* st(3) */ \ + addr = blockend - \ + ((int) &foo.u_fpusave.fpu_stack[3][0] - (int)&foo); \ + break; \ + case 10: /* st(4) */ \ + addr = blockend - \ + ((int) &foo.u_fpusave.fpu_stack[4][0] - (int)&foo); \ + break; \ + case 11: /* st(5) */ \ + addr = blockend - \ + ((int) &foo.u_fpusave.fpu_stack[5][0] - (int)&foo); \ + break; \ + case 12: /* st(6) */ \ + addr = blockend - \ + ((int) &foo.u_fpusave.fpu_stack[6][0] - (int)&foo); \ + break; \ + case 13: /* st(7) */ \ + addr = blockend - \ + ((int) &foo.u_fpusave.fpu_stack[7][0] - (int)&foo); \ + break; \ + case 14: \ + addr = blockend + ESP * sizeof(int); break; \ + case 15: \ + addr = blockend + EBP * sizeof(int); break; \ + case 16: \ + addr = blockend + EIP * sizeof(int); break; \ + case 17: \ + addr = blockend + FLAGS * sizeof(int); break; \ + case 18: /* fp1 */ \ + case 19: /* fp2 */ \ + case 20: /* fp3 */ \ + case 21: /* fp4 */ \ + case 22: /* fp5 */ \ + case 23: /* fp6 */ \ + case 24: /* fp7 */ \ + case 25: /* fp8 */ \ + case 26: /* fp9 */ \ + case 27: /* fp10 */ \ + case 28: /* fp11 */ \ + case 29: /* fp12 */ \ + case 30: /* fp13 */ \ + case 31: /* fp14 */ \ + case 32: /* fp15 */ \ + case 33: /* fp16 */ \ + case 34: /* fp17 */ \ + case 35: /* fp18 */ \ + case 36: /* fp19 */ \ + case 37: /* fp20 */ \ + case 38: /* fp21 */ \ + case 39: /* fp22 */ \ + case 40: /* fp23 */ \ + case 41: /* fp24 */ \ + case 42: /* fp25 */ \ + case 43: /* fp26 */ \ + case 44: /* fp27 */ \ + case 45: /* fp28 */ \ + case 46: /* fp29 */ \ + case 47: /* fp30 */ \ + case 48: /* fp31 */ \ + addr = blockend - \ + ((int) &foo.u_fpasave.fpa_regs[(regno)-18] - (int)&foo); \ + } \ +} + +/* Total amount of space needed to store our copies of the machine's + register state, the array `registers'. */ +/* 10 i386 registers, 8 i387 registers, and 31 Weitek 1167 registers */ +#define REGISTER_BYTES ((10 * 4) + (8 * 10) + (31 * 4)) + +/* Index within `registers' of the first byte of the space for + register N. */ + +#define REGISTER_BYTE(N) \ +((N < 3) ? (N * 4) : \ +(N < 5) ? (((N - 2) * 10) + 2) : \ +(N < 8) ? (((N - 5) * 4) + 32) : \ +(N < 14) ? (((N - 8) * 10) + 44) : \ + (((N - 14) * 4) + 104)) + +/* Number of bytes of storage in the actual machine representation + * for register N. All registers are 4 bytes, except 387 st(0) - st(7), + * which are 80 bits each. + */ + +#define REGISTER_RAW_SIZE(N) \ +((N < 3) ? 4 : \ +(N < 5) ? 10 : \ +(N < 8) ? 4 : \ +(N < 14) ? 10 : \ + 4) + +/* Number of bytes of storage in the program's representation + for register N. On the vax, all regs are 4 bytes. */ + +#define REGISTER_VIRTUAL_SIZE(N) 4 + +/* Largest value REGISTER_RAW_SIZE can have. */ + +#define MAX_REGISTER_RAW_SIZE 10 + +/* 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) \ +((N < 3) ? 0 : \ +(N < 5) ? 1 : \ +(N < 8) ? 0 : \ +(N < 14) ? 1 : \ + 0) + +/* Convert data from raw format for register REGNUM + to virtual format for register REGNUM. */ + +#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \ +((REGNUM < 3) ? bcopy ((FROM), (TO), 4) : \ +(REGNUM < 5) ? i387_to_double((FROM), (TO)) : \ +(REGNUM < 8) ? bcopy ((FROM), (TO), 4) : \ +(REGNUM < 14) ? i387_to_double((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) \ +((REGNUM < 3) ? bcopy ((FROM), (TO), 4) : \ +(REGNUM < 5) ? double_to_i387((FROM), (TO)) : \ +(REGNUM < 8) ? bcopy ((FROM), (TO), 4) : \ +(REGNUM < 14) ? double_to_i387((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) \ +((N < 3) ? builtin_type_int : \ +(N < 5) ? builtin_type_double : \ +(N < 8) ? builtin_type_int : \ +(N < 14) ? builtin_type_double : \ + builtin_type_int) + +/* from m-i386.h */ +/* 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)); \ + write_register(0, (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) \ + symmetry_extract_return_value(TYPE, REGBUF, VALBUF) + +/* 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)) + +/* Compensate for lack of `vprintf' function. */ +#ifndef HAVE_VPRINTF +#define vprintf(format, ap) _doprnt (format, ap, stdout) +#endif /* not HAVE_VPRINTF */ + +/* 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. */ + +/* On Symmetry, %ebp points to caller's %ebp, and the return address + is right on top of that. +*/ + +#define FRAME_CHAIN(thisframe) \ + (outside_startup_file ((thisframe)->pc) ? \ + read_memory_integer((thisframe)->frame, 4) :\ + 0) + +#define FRAME_CHAIN_VALID(chain, thisframe) \ + (chain != 0) + +#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(fi) (read_memory_integer((fi)->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. + + The weirdness in the "addl $imm8" case is due to gcc sometimes + issuing "addl $-int" after function call returns; this would + produce ridiculously huge arg counts. */ + +#define FRAME_NUM_ARGS(numargs, fi) \ +{ \ + int op = read_memory_integer(FRAME_SAVED_PC((fi)), 4); \ + int narg; \ + if ((op & 0xff) == 0x59) /* 0x59 'popl %ecx' */ \ + { \ + numargs = 1; \ + } \ + else if ((op & 0xffff) == 0xc483) /* 0xc483 'addl $imm8' */ \ + { \ + narg = ((op >> 16) & 0xff); \ + numargs = (narg >= 128) ? -1 : narg / 4; \ + } \ + else if ((op & 0xffff) == 0xc481) /* 0xc481 'addl $imm32' */ \ + { \ + narg = read_memory_integer(FRAME_SAVED_PC((fi))+2,4); \ + numargs = (narg < 0) ? -1 : narg / 4; \ + } \ + else \ + { \ + numargs = -1; \ + } \ +} + +/* 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. */ + +#define PUSH_DUMMY_FRAME \ +{ CORE_ADDR sp = read_register (SP_REGNUM); \ + int regnum; \ + sp = push_word (sp, read_register (PC_REGNUM)); \ + sp = push_word (sp, read_register (FP_REGNUM)); \ + write_register (FP_REGNUM, sp); \ + for (regnum = 0; regnum < NUM_REGS; regnum++) \ + sp = push_word (sp, read_register (regnum)); \ + write_register (SP_REGNUM, sp); \ +} + +#define POP_FRAME \ +{ \ + FRAME frame = get_current_frame (); \ + CORE_ADDR fp; \ + int regnum; \ + struct frame_saved_regs fsr; \ + struct frame_info *fi; \ + fi = get_frame_info (frame); \ + fp = fi->frame; \ + get_frame_saved_regs (fi, &fsr); \ + for (regnum = 0; regnum < NUM_REGS; regnum++) { \ + CORE_ADDR adr; \ + adr = fsr.regs[regnum]; \ + if (adr) \ + write_register (regnum, read_memory_integer (adr, 4)); \ + } \ + write_register (FP_REGNUM, read_memory_integer (fp, 4)); \ + write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \ + write_register (SP_REGNUM, fp + 8); \ + flush_cached_frames (); \ + set_current_frame ( create_new_frame (read_register (FP_REGNUM), \ + read_pc ())); \ +} + +/* from i386-dep.c, worked better than my original... */ +/* This sequence of words is the instructions + * call (32-bit offset) + * int 3 + * This is 6 bytes. + */ + +#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; \ +} + +/* Interface definitions for kernel debugger KDB. */ +/* This doesn't work... */ +/* 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, SIGKILL, SIGSEGV, 0, 0, 0, 0, 0, \ + 0, 0, SIGTRAP, SIGTRAP, 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) \ +{ asm (".globl end"); \ + asm ("movl $ end, %esp"); \ + asm ("movl %ebp, $0"); } + +/* Push the frame pointer register on the stack. */ +#define PUSH_FRAME_PTR \ + asm ("pushl %ebp"); + +/* Copy the top-of-stack to the frame pointer register. */ +#define POP_FRAME_PTR \ + asm ("movl (%esp), %ebp"); + +/* 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 \ +{ asm("pushad"); } +/* +{ asm("pushl %eax"); \ + asm("pushl %edx"); \ + asm("pushl %ecx"); \ + asm("pushl %st(0)"); \ + asm("pushl %st(1)"); \ + asm("pushl %ebx"); \ + asm("pushl %esi"); \ + asm("pushl %edi"); \ + asm("pushl %st(2)"); \ + asm("pushl %st(3)"); \ + asm("pushl %st(4)"); \ + asm("pushl %st(5)"); \ + asm("pushl %st(6)"); \ + asm("pushl %st(7)"); \ + asm("pushl %esp"); \ + asm("pushl %ebp"); \ + asm("pushl %eip"); \ + asm("pushl %eflags"); \ + asm("pushl %fp1"); \ + asm("pushl %fp2"); \ + asm("pushl %fp3"); \ + asm("pushl %fp4"); \ + asm("pushl %fp5"); \ + asm("pushl %fp6"); \ + asm("pushl %fp7"); \ + asm("pushl %fp8"); \ + asm("pushl %fp9"); \ + asm("pushl %fp10"); \ + asm("pushl %fp11"); \ + asm("pushl %fp12"); \ + asm("pushl %fp13"); \ + asm("pushl %fp14"); \ + asm("pushl %fp15"); \ + asm("pushl %fp16"); \ + asm("pushl %fp17"); \ + asm("pushl %fp18"); \ + asm("pushl %fp19"); \ + asm("pushl %fp20"); \ + asm("pushl %fp21"); \ + asm("pushl %fp22"); \ + asm("pushl %fp23"); \ + asm("pushl %fp24"); \ + asm("pushl %fp25"); \ + asm("pushl %fp26"); \ + asm("pushl %fp27"); \ + asm("pushl %fp28"); \ + asm("pushl %fp29"); \ + asm("pushl %fp30"); \ + asm("pushl %fp31"); \ +} +*/ +/* 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 \ +{ asm ("popad"); } diff --git a/gdb/m-umax.h b/gdb/m-umax.h index 2ef3965e12..6415d39879 100644 --- a/gdb/m-umax.h +++ b/gdb/m-umax.h @@ -1,22 +1,21 @@ /* Definitions to make GDB run on an encore under umax 4.2 - Copyright (C) 1987 Free Software Foundation, Inc. + Copyright (C) 1987, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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. */ #ifndef ns16000 #define ns16000 @@ -24,6 +23,11 @@ anyone else from sharing it farther. Help stamp out software hoarding! #define HAVE_WAIT_STRUCT +/* Define the bit, byte, and word ordering of the machine. */ +/* #define BITS_BIG_ENDIAN */ +/* #define BYTES_BIG_ENDIAN */ +/* #define WORDS_BIG_ENDIAN */ + /* Encore's modifications to ptrace format */ #define UMAX_PTRACE @@ -45,6 +49,9 @@ anyone else from sharing it farther. Help stamp out software hoarding! #define COFF_FORMAT +/* Doesn't have siginterupt. */ +#define NO_SIGINTERRUPT + /* Offset from address of function to start of its code. Zero on most machines. */ @@ -277,10 +284,13 @@ anyone else from sharing it farther. Help stamp out software hoarding! /* In the case of the ns32000 series, the frame's nominal address is the FP value, and at that address is saved previous FP value as a 4-byte word. */ -#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4)) +#define FRAME_CHAIN(thisframe) \ + (outside_startup_file ((thisframe)->pc) ? \ + read_memory_integer ((thisframe)->frame, 4) :\ + 0) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe)))) #define FRAME_CHAIN_COMBINE(chain, thisframe) (chain) @@ -386,8 +396,10 @@ extern CORE_ADDR ns32k_get_enter_addr (); } \ } -/* Compensate for lack of `vprintf' function. */ -#define vprintf(format, ap) _doprnt (format, ap, stdout) +/* Compensate for lack of `vprintf' function. */ +#ifndef HAVE_VPRINTF +#define vprintf(format, ap) _doprnt (format, ap, stdout) +#endif /* not HAVE_VPRINTF */ /* Things needed for making the inferior call functions. */ diff --git a/gdb/m-vax.h b/gdb/m-vax.h index 60595cfe58..906ed033ce 100644 --- a/gdb/m-vax.h +++ b/gdb/m-vax.h @@ -1,27 +1,52 @@ /* Definitions to make GDB run on a vax under 4.2bsd. - Copyright (C) 1986, 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! -*/ + 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. */ + +/* There is one known bug with VAX support that I don't know how to + fix: if you do a backtrace from a signal handler, you get something + like: +#0 0xbc in kill (592, 3) +#1 0x7f in hand (...) (...) +#2 0x7fffec7e in ?? (2, 0, 2147478112, 94) + ^^ GDB doesn't know about sigtramp +#3 0x7fffec70 in ?? (592, 2) + ^^^^^^^^^^ wrong address +#4 0xae in main (...) (...) + +when the correct backtrace (as given by adb) is: +_kill(250,3) from _hand+21 +_hand(2,0,7fffea60,5e) from 7fffec7e +sigtramp(2,0,7fffea60,5e) from _kill+4 +_kill(250,2) from _main+2e +_main(1,7fffeac4,7fffeacc) from start+3d + +If anyone knows enough about VAX BSD to fix this, please send the +fix to bug-gdb@prep.ai.mit.edu. */ #ifndef vax #define vax #endif +/* Define the bit, byte, and word ordering of the machine. */ +/* #define BITS_BIG_ENDIAN */ +/* #define BYTES_BIG_ENDIAN */ +/* #define WORDS_BIG_ENDIAN */ + /* Get rid of any system-imposed stack limit if possible. */ #define SET_STACK_LIMIT_HUGE @@ -218,7 +243,9 @@ anyone else from sharing it farther. Help stamp out software hoarding! #define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF)) /* Compensate for lack of `vprintf' function. */ +#ifndef HAVE_VPRINTF #define vprintf(format, ap) _doprnt (format, ap, stdout) +#endif /* not HAVE_VPRINTF */ /* Describe the pointer in each stack frame to the previous stack frame (its caller). */ @@ -236,15 +263,26 @@ anyone else from sharing it farther. Help stamp out software hoarding! /* In the case of the Vax, the frame's nominal address is the FP value, and 12 bytes later comes the saved previous FP value as a 4-byte word. */ -#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame + 12, 4)) +#define FRAME_CHAIN(thisframe) \ + (outside_startup_file ((thisframe)->pc) ? \ + read_memory_integer ((thisframe)->frame + 12, 4) :\ + 0) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (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. */ +/* On the vax, all functions have frames. */ +#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) {(FRAMELESS) = 0;} + +/* Saved Pc. */ + #define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 16, 4)) /* Cannot find the AP register value directly from the FP value. diff --git a/gdb/m68k-opcode.h b/gdb/m68k-opcode.h index 8f7c30ff9b..3fde5e2f47 100644 --- a/gdb/m68k-opcode.h +++ b/gdb/m68k-opcode.h @@ -1,4 +1,22 @@ -/* Opcode table for m68000/m68020 and m68881. */ +/* Opcode table for m68000/m68020 and m68881. + Copyright (C) 1989, Free Software Foundation. + +This file is part of GDB, the GNU Debugger and GAS, the GNU Assembler. + +Both GDB and GAS are free software; you can redistribute 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 and GAS are 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 or GAS; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + struct m68k_opcode { @@ -57,6 +75,7 @@ struct m68k_opcode coprocessor opcode can be skipped using the 'i' place, if needed. s System Control register for the floating point coprocessor. + S List of system control registers for floating point coprocessor. J Misc register for movec instruction, stored in 'j' format. Possible values: @@ -69,7 +88,14 @@ struct m68k_opcode 803 MSP Master Stack Pointer 804 ISP Interrupt Stack Pointer - These specify various classes of addressing modes. + L Register list of the type d0-d7/a0-a7 etc. + (New! Improved! Can also hold fp0-fp7, as well!) + The assembler tries to see if the registers match the insn by + looking at where the insn wants them stored. + + l Register list like L, but with all the bits reversed. + Used for going the other way. . . + They are all stored as 6 bits using an address mode and a register number; they differ in which addressing modes they match. @@ -77,14 +103,51 @@ struct m68k_opcode ~ alterable memory (modes 2-6,7.0,7.1)(not 0,1,7.~) % alterable (modes 0-6,7.0,7.1)(not 7.~) ; data (modes 0,2-6,7.*)(not 1) - @ data, but not immediate (modes 0,2-6,7.???)(not 1,7.?) This may really be ;, the 68020 book says it is + @ data, but not immediate (modes 0,2-6,7.? ? ?)(not 1,7.?) This may really be ;, the 68020 book says it is ! control (modes 2,5,6,7.*-)(not 0,1,3,4,7.4) - & alterable control (modes 2,5,6,7.0,7.1)(not 0,1,7.???) + & alterable control (modes 2,5,6,7.0,7.1)(not 0,1,7.? ? ?) $ alterable data (modes 0,2-6,7.0,7.1)(not 1,7.~) ? alterable control, or data register (modes 0,2,5,6,7.0,7.1)(not 1,3,4,7.~) / control, or data register (modes 0,2,5,6,7.0,7.1,7.2,7.3)(not 1,3,4,7.4) */ +/* JF: for the 68851 */ +/* + I didn't use much imagination in choosing the + following codes, so many of them aren't very + mnemonic. -rab + + P pmmu register + Possible values: + 000 TC Translation Control reg + 100 CAL Current Access Level + 101 VAL Validate Access Level + 110 SCC Stack Change Control + 111 AC Access Control + + W wide pmmu registers + Possible values: + 001 DRP Dma Root Pointer + 010 SRP Supervisor Root Pointer + 011 CRP Cpu Root Pointer + + f function code register + 0 SFC + 1 DFC + + V VAL register only + + X BADx, BACx + 100 BAD Breakpoint Acknowledge Data + 101 BAC Breakpoint Acknowledge Control + + Y PSR + Z PCSR + + | memory (modes 2-6, 7.*) + +*/ + /* Places to put an operand, for non-general operands: s source, low bits of first word. d dest, shifted 9 in first word @@ -130,10 +193,11 @@ struct m68k_opcode #define one(x) ((x) << 16) #define two(x, y) (((x) << 16) + y) -/* The assembler requires that this array be sorted as follows: - all instances of the same mnemonic must be consecutive. - All instances of the same mnemonic with the same number of operands - must be consecutive. +/* + *** DANGER WILL ROBINSON *** + + The assembler requires that all instances of the same mnemonic must be + consecutive. If they aren't, the assembler will bomb at runtime */ struct m68k_opcode m68k_opcodes[] = { @@ -150,20 +214,20 @@ struct m68k_opcode m68k_opcodes[] = {"addql", one(0050200), one(0170700), "Qd%l"}, {"addqw", one(0050100), one(0170700), "Qd%w"}, -{"addb", one(0003000), one(0177700), "#b$b"}, /* addi written as add */ {"addb", one(0050000), one(0170700), "Qd$b"}, /* addq written as add */ +{"addb", one(0003000), one(0177700), "#b$b"}, /* addi written as add */ {"addb", one(0150000), one(0170700), ";bDd"}, /* addb , Dd */ {"addb", one(0150400), one(0170700), "Dd~b"}, /* addb Dd, */ +{"addw", one(0050100), one(0170700), "Qd%w"}, /* addq written as add */ {"addw", one(0003100), one(0177700), "#w$w"}, /* addi written as add */ {"addw", one(0150300), one(0170700), "*wAd"}, /* adda written as add */ -{"addw", one(0050100), one(0170700), "Qd%w"}, /* addq written as add */ {"addw", one(0150100), one(0170700), "*wDd"}, /* addw , Dd */ {"addw", one(0150500), one(0170700), "Dd~w"}, /* addw Dd, */ +{"addl", one(0050200), one(0170700), "Qd%l"}, /* addq written as add */ {"addl", one(0003200), one(0177700), "#l$l"}, /* addi written as add */ {"addl", one(0150700), one(0170700), "*lAd"}, /* adda written as add */ -{"addl", one(0050200), one(0170700), "Qd%l"}, /* addq written as add */ {"addl", one(0150200), one(0170700), "*lDd"}, /* addl , Dd */ {"addl", one(0150600), one(0170700), "Dd~l"}, /* addl Dd, */ @@ -241,7 +305,10 @@ struct m68k_opcode m68k_opcodes[] = {"bkpt", one(0044110), one(0177770), "Qs"}, {"bra", one(0060000), one(0177400), "Bg"}, +{"bras", one(0060000), one(0177400), "Bg"}, {"bsr", one(0060400), one(0177400), "Bg"}, +{"bsrs", one(0060400), one(0177400), "Bg"}, + {"callm", one(0003300), one(0177700), "#b!s"}, {"cas2l", two(0007374, 0), two(0177777, 0107070), "D3D6D2D5R1R4"}, /* JF FOO this is really a 3 word ins */ {"cas2w", two(0006374, 0), two(0177777, 0107070), "D3D6D2D5R1R4"}, /* JF ditto */ @@ -359,23 +426,34 @@ struct m68k_opcode m68k_opcodes[] = {"moveal", one(0020100), one(0170700), "*lAd"}, {"moveaw", one(0030100), one(0170700), "*wAd"}, {"moveb", one(0010000), one(0170000), ";b$d"}, /* move */ +{"movel", one(0070000), one(0170400), "MsDd"}, /* moveq written as move */ +{"movel", one(0020000), one(0170000), "*l$d"}, +{"movel", one(0020100), one(0170700), "*lAd"}, +{"movel", one(0047140), one(0177770), "AsUd"}, /* move to USP */ +{"movel", one(0047150), one(0177770), "UdAs"}, /* move from USP */ {"movec", one(0047173), one(0177777), "R1Jj"}, {"movec", one(0047173), one(0177777), "R1#j"}, {"movec", one(0047172), one(0177777), "JjR1"}, {"movec", one(0047172), one(0177777), "#jR1"}, -{"movel", one(0020000), one(0170000), "*l$d"}, -{"movel", one(0020100), one(0170700), "*lAd"}, -{"movel", one(0047140), one(0177770), "AsUd"}, /* move to USP */ -{"movel", one(0047150), one(0177770), "UdAs"}, /* move from USP */ -{"movel", one(0070000), one(0170400), "MsDd"}, /* moveq written as move */ +/* JF added these next four for the assembler */ +{"moveml", one(0044300), one(0177700), "Lw&s"}, /* movem reg to mem. */ +{"moveml", one(0044340), one(0177770), "lw-s"}, /* movem reg to autodecrement. */ +{"moveml", one(0046300), one(0177700), "!sLw"}, /* movem mem to reg. */ +{"moveml", one(0046330), one(0177770), "+sLw"}, /* movem autoinc to reg. */ {"moveml", one(0044300), one(0177700), "#w&s"}, /* movem reg to mem. */ {"moveml", one(0044340), one(0177770), "#w-s"}, /* movem reg to autodecrement. */ {"moveml", one(0046300), one(0177700), "!s#w"}, /* movem mem to reg. */ {"moveml", one(0046330), one(0177770), "+s#w"}, /* movem autoinc to reg. */ +/* JF added these next four for the assembler */ +{"movemw", one(0044200), one(0177700), "Lw&s"}, /* movem reg to mem. */ +{"movemw", one(0044240), one(0177770), "lw-s"}, /* movem reg to autodecrement. */ +{"movemw", one(0046200), one(0177700), "!sLw"}, /* movem mem to reg. */ +{"movemw", one(0046230), one(0177770), "+sLw"}, /* movem autoinc to reg. */ + {"movemw", one(0044200), one(0177700), "#w&s"}, /* movem reg to mem. */ {"movemw", one(0044240), one(0177770), "#w-s"}, /* movem reg to autodecrement. */ {"movemw", one(0046200), one(0177700), "!s#w"}, /* movem mem to reg. */ @@ -501,27 +579,26 @@ struct m68k_opcode m68k_opcodes[] = {"subal", one(0110700), one(0170700), "*lAd"}, {"subaw", one(0110300), one(0170700), "*wAd"}, -{"subb", one(0002000), one(0177700), "#b$s"}, /* subi written as sub */ {"subb", one(0050400), one(0170700), "Qd%s"}, /* subq written as sub */ -{"subb", one(0110000), one(0170700), ";bDd"}, /* subb ??, Dd */ -{"subb", one(0110400), one(0170700), "Dd~s"}, /* subb Dd, ?? */ +{"subb", one(0002000), one(0177700), "#b$s"}, /* subi written as sub */ +{"subb", one(0110000), one(0170700), ";bDd"}, /* subb ? ?, Dd */ +{"subb", one(0110400), one(0170700), "Dd~s"}, /* subb Dd, ? ? */ {"subib", one(0002000), one(0177700), "#b$s"}, {"subil", one(0002200), one(0177700), "#l$s"}, {"subiw", one(0002100), one(0177700), "#w$s"}, -{"subl", one(0002200), one(0177700), "#l$s"}, {"subl", one(0050600), one(0170700), "Qd%s"}, +{"subl", one(0002200), one(0177700), "#l$s"}, +{"subl", one(0110700), one(0170700), "*lAd"}, {"subl", one(0110200), one(0170700), "*lDd"}, {"subl", one(0110600), one(0170700), "Dd~s"}, -{"subl", one(0110700), one(0170700), "*lAd"}, {"subqb", one(0050400), one(0170700), "Qd%s"}, {"subql", one(0050600), one(0170700), "Qd%s"}, {"subqw", one(0050500), one(0170700), "Qd%s"}, -{"subw", one(0002100), one(0177700), "#w$s"}, {"subw", one(0050500), one(0170700), "Qd%s"}, +{"subw", one(0002100), one(0177700), "#w$s"}, {"subw", one(0110100), one(0170700), "*wDd"}, {"subw", one(0110300), one(0170700), "*wAd"}, /* suba written as sub */ {"subw", one(0110500), one(0170700), "Dd~s"}, - {"subxb", one(0110400), one(0170770), "DsDd"}, /* subxb Ds, Dd */ {"subxb", one(0110410), one(0170770), "-s-d"}, /* subxb -(As), -(Ad) */ {"subxl", one(0110600), one(0170770), "DsDd"}, @@ -624,6 +701,7 @@ struct m68k_opcode m68k_opcodes[] = {"faddw", two(0xF000, 0x5022), two(0xF1C0, 0xFC7F), "Ii;wF7"}, {"faddx", two(0xF000, 0x0022), two(0xF1C0, 0xE07F), "IiF8F7"}, {"faddx", two(0xF000, 0x4822), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +/* {"faddx", two(0xF000, 0x0022), two(0xF1C0, 0xE07F), "IiFt"}, JF removed */ {"fasinb", two(0xF000, 0x580C), two(0xF1C0, 0xFC7F), "Ii;bF7"}, {"fasind", two(0xF000, 0x540C), two(0xF1C0, 0xFC7F), "Ii;FF7"}, @@ -696,6 +774,7 @@ struct m68k_opcode m68k_opcodes[] = {"fcmpw", two(0xF000, 0x5038), two(0xF1C0, 0xFC7F), "Ii;wF7"}, {"fcmpx", two(0xF000, 0x0038), two(0xF1C0, 0xE07F), "IiF8F7"}, {"fcmpx", two(0xF000, 0x4838), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +/* {"fcmpx", two(0xF000, 0x0038), two(0xF1C0, 0xE07F), "IiFt"}, JF removed */ {"fcosb", two(0xF000, 0x581D), two(0xF1C0, 0xFC7F), "Ii;bF7"}, {"fcosd", two(0xF000, 0x541D), two(0xF1C0, 0xFC7F), "Ii;FF7"}, @@ -758,6 +837,7 @@ struct m68k_opcode m68k_opcodes[] = {"fdivw", two(0xF000, 0x5020), two(0xF1C0, 0xFC7F), "Ii;wF7"}, {"fdivx", two(0xF000, 0x0020), two(0xF1C0, 0xE07F), "IiF8F7"}, {"fdivx", two(0xF000, 0x4820), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +/* {"fdivx", two(0xF000, 0x0020), two(0xF1C0, 0xE07F), "IiFt"}, JF */ {"fetoxb", two(0xF000, 0x5810), two(0xF1C0, 0xFC7F), "Ii;bF7"}, {"fetoxd", two(0xF000, 0x5410), two(0xF1C0, 0xFC7F), "Ii;FF7"}, @@ -867,6 +947,7 @@ struct m68k_opcode m68k_opcodes[] = {"fmodw", two(0xF000, 0x5021), two(0xF1C0, 0xFC7F), "Ii;wF7"}, {"fmodx", two(0xF000, 0x0021), two(0xF1C0, 0xE07F), "IiF8F7"}, {"fmodx", two(0xF000, 0x4821), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +/* {"fmodx", two(0xF000, 0x0021), two(0xF1C0, 0xE07F), "IiFt"}, JF */ {"fmoveb", two(0xF000, 0x5800), two(0xF1C0, 0xFC7F), "Ii;bF7"}, /* fmove from to fp */ {"fmoveb", two(0xF000, 0x7800), two(0xF1C0, 0xFC7F), "IiF7@b"}, /* fmove from fp to */ @@ -874,12 +955,19 @@ struct m68k_opcode m68k_opcodes[] = {"fmoved", two(0xF000, 0x7400), two(0xF1C0, 0xFC7F), "IiF7@F"}, /* fmove from fp to */ {"fmovel", two(0xF000, 0x4000), two(0xF1C0, 0xFC7F), "Ii;lF7"}, /* fmove from to fp */ {"fmovel", two(0xF000, 0x6000), two(0xF1C0, 0xFC7F), "IiF7@l"}, /* fmove from fp to */ - /* JF for the assembler */ -{"fmovel", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8%l"}, +/* Warning: The addressing modes on these are probably not right: + esp, Areg direct is only allowed for FPI */ + /* fmove.l from/to system control registers: */ +{"fmovel", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s"}, {"fmovel", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*ls8"}, -/* JF {"fmovep", two(0xF000, 0x4C00), two(0xF1C0, 0xFC7F), "Ii;pF7"}, /* fmove from to fp */ + +/* {"fmovel", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s"}, +{"fmovel", two(0xF000, 0x8000), two(0xF2C0, 0xE3FF), "Ii*ss8"}, */ + +{"fmovep", two(0xF000, 0x4C00), two(0xF1C0, 0xFC7F), "Ii;pF7"}, /* fmove from to fp */ {"fmovep", two(0xF000, 0x6C00), two(0xF1C0, 0xFC00), "IiF7@pkC"}, /* fmove.p with k-factors: */ {"fmovep", two(0xF000, 0x7C00), two(0xF1C0, 0xFC0F), "IiF7@pDk"}, /* fmove.p with k-factors: */ + {"fmoves", two(0xF000, 0x4400), two(0xF1C0, 0xFC7F), "Ii;fF7"}, /* fmove from to fp */ {"fmoves", two(0xF000, 0x6400), two(0xF1C0, 0xFC7F), "IiF7@f"}, /* fmove from fp to */ {"fmovew", two(0xF000, 0x5000), two(0xF1C0, 0xFC7F), "Ii;wF7"}, /* fmove from to fp */ @@ -887,35 +975,62 @@ struct m68k_opcode m68k_opcodes[] = {"fmovex", two(0xF000, 0x0000), two(0xF1C0, 0xE07F), "IiF8F7"}, /* fmove from to fp */ {"fmovex", two(0xF000, 0x4800), two(0xF1C0, 0xFC7F), "Ii;xF7"}, /* fmove from to fp */ {"fmovex", two(0xF000, 0x6800), two(0xF1C0, 0xFC7F), "IiF7@x"}, /* fmove from fp to */ - - /* fmove.l from/to system control registers: */ - -/* fmove.l and fmovem.l are the same instruction. fmovem.l makes sense in - more cases, so I've dumped fmove.l pro tem, but this is the wrong - way to solve the problem in the long run. Hmmm. */ -/* {"fmovel", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s"}, */ -/* {"fmovel", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii@ss8"}, */ +/* JF removed {"fmovex", two(0xF000, 0x0000), two(0xF1C0, 0xE07F), "IiFt"}, / * fmove from to fp */ {"fmovecrx", two(0xF000, 0x5C00), two(0xF1FF, 0xFC00), "Ii#CF7"}, /* fmovecr.x #ccc, FPn */ {"fmovecr", two(0xF000, 0x5C00), two(0xF1FF, 0xFC00), "Ii#CF7"}, +/* Other fmovemx. */ +{"fmovemx", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "IdL3-s"}, /* fmovem.x to autodecrement, static and dynamic */ {"fmovemx", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "Id#3-s"}, /* fmovem.x to autodecrement, static and dynamic */ + {"fmovemx", two(0xF020, 0xE800), two(0xF1F8, 0xFF8F), "IiDk-s"}, /* fmovem.x to autodecrement, static and dynamic */ {"fmovemx", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Id#3&s"}, /* fmovem.x to control, static and dynamic: */ {"fmovemx", two(0xF000, 0xF800), two(0xF1C0, 0xFF8F), "IiDk&s"}, /* fmovem.x to control, static and dynamic: */ +{"fmovemx", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&s#3"}, /* fmovem.x from control, static and dynamic: */ +{"fmovemx", two(0xF000, 0xD800), two(0xF1C0, 0xFF8F), "Ii&sDk"}, /* fmovem.x from control, static and dynamic: */ +{"fmovemx", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Idl3&s"}, /* fmovem.x to control, static and dynamic: */ +{"fmovemx", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&sl3"}, /* fmovem.x from control, static and dynamic: */ +{"fmovemx", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+sl3"}, /* fmovem.x from autoincrement, static and dynamic: */ {"fmovemx", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+s#3"}, /* fmovem.x from autoincrement, static and dynamic: */ {"fmovemx", two(0xF018, 0xD800), two(0xF1F8, 0xFF8F), "Ii+sDk"}, /* fmovem.x from autoincrement, static and dynamic: */ + +{"fmoveml", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "IiL8@s"}, +{"fmoveml", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Ii#8@s"}, +{"fmoveml", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s"}, + +{"fmoveml", two(0xF000, 0x8000), two(0xF2C0, 0xE3FF), "Ii*sL8"}, +{"fmoveml", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*s#8"}, +{"fmoveml", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*ss8"}, + +/* fmovemx with register lists */ +{"fmovem", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "IdL3-s"}, /* fmovem.x to autodecrement, static and dynamic */ +{"fmovem", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Idl3&s"}, /* fmovem.x to control, static and dynamic: */ +{"fmovem", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+sl3"}, /* fmovem.x from autoincrement, static and dynamic: */ +{"fmovem", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&sl3"}, /* fmovem.x from control, static and dynamic: */ + + /* Alternate mnemonics for GNU as and GNU CC */ +{"fmovem", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "Id#3-s"}, /* fmovem.x to autodecrement, static and dynamic */ +{"fmovem", two(0xF020, 0xE800), two(0xF1F8, 0xFF8F), "IiDk-s"}, /* fmovem.x to autodecrement, static and dynamic */ + +{"fmovem", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Id#3&s"}, /* fmovem.x to control, static and dynamic: */ +{"fmovem", two(0xF000, 0xF800), two(0xF1C0, 0xFF8F), "IiDk&s"}, /* fmovem.x to control, static and dynamic: */ + +{"fmovem", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+s#3"}, /* fmovem.x from autoincrement, static and dynamic: */ +{"fmovem", two(0xF018, 0xD800), two(0xF1F8, 0xFF8F), "Ii+sDk"}, /* fmovem.x from autoincrement, static and dynamic: */ -{"fmovemx", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&s#3"}, /* fmovem.x from control, static and dynamic: */ -{"fmovemx", two(0xF000, 0xD800), two(0xF1C0, 0xFF8F), "Ii&sDk"}, /* fmovem.x from control, static and dynamic: */ +{"fmovem", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&s#3"}, /* fmovem.x from control, static and dynamic: */ +{"fmovem", two(0xF000, 0xD800), two(0xF1C0, 0xFF8F), "Ii&sDk"}, /* fmovem.x from control, static and dynamic: */ -/* fmoveml and fmovel are the same instruction. This may cause some - confusion in the assembler. */ +/* fmoveml a FP-control register */ +{"fmovem", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s"}, +{"fmovem", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*ss8"}, -{"fmoveml", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Ii#8%s"}, /* fmovem.l to/from system control register(s): */ -{"fmoveml", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii%s#8"}, /* fmovem.l to/from system control register(s): */ +/* fmoveml a FP-control reglist */ +{"fmovem", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "IiL8@s"}, +{"fmovem", two(0xF000, 0x8000), two(0xF2C0, 0xE3FF), "Ii*sL8"}, {"fmulb", two(0xF000, 0x5823), two(0xF1C0, 0xFC7F), "Ii;bF7"}, {"fmuld", two(0xF000, 0x5423), two(0xF1C0, 0xFC7F), "Ii;FF7"}, @@ -925,6 +1040,7 @@ struct m68k_opcode m68k_opcodes[] = {"fmulw", two(0xF000, 0x5023), two(0xF1C0, 0xFC7F), "Ii;wF7"}, {"fmulx", two(0xF000, 0x0023), two(0xF1C0, 0xE07F), "IiF8F7"}, {"fmulx", two(0xF000, 0x4823), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +/* {"fmulx", two(0xF000, 0x0023), two(0xF1C0, 0xE07F), "IiFt"}, JF */ {"fnegb", two(0xF000, 0x581A), two(0xF1C0, 0xFC7F), "Ii;bF7"}, {"fnegd", two(0xF000, 0x541A), two(0xF1C0, 0xFC7F), "Ii;FF7"}, @@ -946,6 +1062,7 @@ struct m68k_opcode m68k_opcodes[] = {"fremw", two(0xF000, 0x5025), two(0xF1C0, 0xFC7F), "Ii;wF7"}, {"fremx", two(0xF000, 0x0025), two(0xF1C0, 0xE07F), "IiF8F7"}, {"fremx", two(0xF000, 0x4825), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +/* {"fremx", two(0xF000, 0x0025), two(0xF1C0, 0xE07F), "IiFt"}, JF */ {"frestore", one(0xF140), one(0xF1C0), "Id&s"}, {"frestore", one(0xF158), one(0xF1F8), "Id+s"}, @@ -969,6 +1086,7 @@ struct m68k_opcode m68k_opcodes[] = {"fscalew", two(0xF000, 0x5026), two(0xF1C0, 0xFC7F), "Ii;wF7"}, {"fscalex", two(0xF000, 0x0026), two(0xF1C0, 0xE07F), "IiF8F7"}, {"fscalex", two(0xF000, 0x4826), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +/* {"fscalex", two(0xF000, 0x0026), two(0xF1C0, 0xE07F), "IiFt"}, JF */ {"fseq", two(0xF040, 0x0001), two(0xF1C0, 0xFFFF), "Ii@s"}, {"fsf", two(0xF040, 0x0000), two(0xF1C0, 0xFFFF), "Ii@s"}, @@ -1011,6 +1129,7 @@ struct m68k_opcode m68k_opcodes[] = {"fsgldivw", two(0xF000, 0x5024), two(0xF1C0, 0xFC7F), "Ii;wF7"}, {"fsgldivx", two(0xF000, 0x0024), two(0xF1C0, 0xE07F), "IiF8F7"}, {"fsgldivx", two(0xF000, 0x4824), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fsgldivx", two(0xF000, 0x0024), two(0xF1C0, 0xE07F), "IiFt"}, {"fsglmulb", two(0xF000, 0x5827), two(0xF1C0, 0xFC7F), "Ii;bF7"}, {"fsglmuld", two(0xF000, 0x5427), two(0xF1C0, 0xFC7F), "Ii;FF7"}, @@ -1020,6 +1139,7 @@ struct m68k_opcode m68k_opcodes[] = {"fsglmulw", two(0xF000, 0x5027), two(0xF1C0, 0xFC7F), "Ii;wF7"}, {"fsglmulx", two(0xF000, 0x0027), two(0xF1C0, 0xE07F), "IiF8F7"}, {"fsglmulx", two(0xF000, 0x4827), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fsglmulx", two(0xF000, 0x0027), two(0xF1C0, 0xE07F), "IiFt"}, {"fsinb", two(0xF000, 0x580E), two(0xF1C0, 0xFC7F), "Ii;bF7"}, {"fsind", two(0xF000, 0x540E), two(0xF1C0, 0xFC7F), "Ii;FF7"}, @@ -1059,6 +1179,7 @@ struct m68k_opcode m68k_opcodes[] = {"fsubw", two(0xF000, 0x5028), two(0xF1C0, 0xFC7F), "Ii;wF7"}, {"fsubx", two(0xF000, 0x0028), two(0xF1C0, 0xE07F), "IiF8F7"}, {"fsubx", two(0xF000, 0x4828), two(0xF1C0, 0xFC7F), "Ii;xF7"}, +{"fsubx", two(0xF000, 0x0028), two(0xF1C0, 0xE07F), "IiFt"}, {"ftanb", two(0xF000, 0x580F), two(0xF1C0, 0xFC7F), "Ii;bF7"}, {"ftand", two(0xF000, 0x540F), two(0xF1C0, 0xFC7F), "Ii;FF7"}, @@ -1208,6 +1329,57 @@ struct m68k_opcode m68k_opcodes[] = {"ftwotoxx", two(0xF000, 0x4811), two(0xF1C0, 0xFC7F), "Ii;xF7"}, {"ftwotoxx", two(0xF000, 0x0011), two(0xF1C0, 0xE07F), "IiFt"}, + +{"fjeq", one(0xF081), one(0xF1FF), "IdBc"}, +{"fjf", one(0xF080), one(0xF1FF), "IdBc"}, +{"fjge", one(0xF093), one(0xF1FF), "IdBc"}, +{"fjgl", one(0xF096), one(0xF1FF), "IdBc"}, +{"fjgle", one(0xF097), one(0xF1FF), "IdBc"}, +{"fjgt", one(0xF092), one(0xF1FF), "IdBc"}, +{"fjle", one(0xF095), one(0xF1FF), "IdBc"}, +{"fjlt", one(0xF094), one(0xF1FF), "IdBc"}, +{"fjne", one(0xF08E), one(0xF1FF), "IdBc"}, +{"fjnge", one(0xF09C), one(0xF1FF), "IdBc"}, +{"fjngl", one(0xF099), one(0xF1FF), "IdBc"}, +{"fjngle", one(0xF098), one(0xF1FF), "IdBc"}, +{"fjngt", one(0xF09D), one(0xF1FF), "IdBc"}, +{"fjnle", one(0xF09A), one(0xF1FF), "IdBc"}, +{"fjnlt", one(0xF09B), one(0xF1FF), "IdBc"}, +{"fjoge", one(0xF083), one(0xF1FF), "IdBc"}, +{"fjogl", one(0xF086), one(0xF1FF), "IdBc"}, +{"fjogt", one(0xF082), one(0xF1FF), "IdBc"}, +{"fjole", one(0xF085), one(0xF1FF), "IdBc"}, +{"fjolt", one(0xF084), one(0xF1FF), "IdBc"}, +{"fjor", one(0xF087), one(0xF1FF), "IdBc"}, +{"fjseq", one(0xF091), one(0xF1FF), "IdBc"}, +{"fjsf", one(0xF090), one(0xF1FF), "IdBc"}, +{"fjsne", one(0xF09E), one(0xF1FF), "IdBc"}, +{"fjst", one(0xF09F), one(0xF1FF), "IdBc"}, +{"fjt", one(0xF08F), one(0xF1FF), "IdBc"}, +{"fjueq", one(0xF089), one(0xF1FF), "IdBc"}, +{"fjuge", one(0xF08B), one(0xF1FF), "IdBc"}, +{"fjugt", one(0xF08A), one(0xF1FF), "IdBc"}, +{"fjule", one(0xF08D), one(0xF1FF), "IdBc"}, +{"fjult", one(0xF08C), one(0xF1FF), "IdBc"}, +{"fjun", one(0xF088), one(0xF1FF), "IdBc"}, + +/* The assembler will ignore attempts to force a short offset */ + +{"bhis", one(0061000), one(0177400), "Bg"}, +{"blss", one(0061400), one(0177400), "Bg"}, +{"bccs", one(0062000), one(0177400), "Bg"}, +{"bcss", one(0062400), one(0177400), "Bg"}, +{"bnes", one(0063000), one(0177400), "Bg"}, +{"beqs", one(0063400), one(0177400), "Bg"}, +{"bvcs", one(0064000), one(0177400), "Bg"}, +{"bvss", one(0064400), one(0177400), "Bg"}, +{"bpls", one(0065000), one(0177400), "Bg"}, +{"bmis", one(0065400), one(0177400), "Bg"}, +{"bges", one(0066000), one(0177400), "Bg"}, +{"blts", one(0066400), one(0177400), "Bg"}, +{"bgts", one(0067000), one(0177400), "Bg"}, +{"bles", one(0067400), one(0177400), "Bg"}, + /* Alternate mnemonics for SUN */ {"jbsr", one(0060400), one(0177400), "Bg"}, @@ -1230,24 +1402,55 @@ struct m68k_opcode m68k_opcodes[] = {"jgt", one(0067000), one(0177400), "Bg"}, {"jle", one(0067400), one(0177400), "Bg"}, +/* Short offsets are ignored */ + +{"jbsrs", one(0060400), one(0177400), "Bg"}, +{"jras", one(0060000), one(0177400), "Bg"}, +{"jhis", one(0061000), one(0177400), "Bg"}, +{"jlss", one(0061400), one(0177400), "Bg"}, +{"jccs", one(0062000), one(0177400), "Bg"}, +{"jcss", one(0062400), one(0177400), "Bg"}, +{"jnes", one(0063000), one(0177400), "Bg"}, +{"jeqs", one(0063400), one(0177400), "Bg"}, +{"jvcs", one(0064000), one(0177400), "Bg"}, +{"jvss", one(0064400), one(0177400), "Bg"}, +{"jpls", one(0065000), one(0177400), "Bg"}, +{"jmis", one(0065400), one(0177400), "Bg"}, +{"jges", one(0066000), one(0177400), "Bg"}, +{"jlts", one(0066400), one(0177400), "Bg"}, +{"jgts", one(0067000), one(0177400), "Bg"}, +{"jles", one(0067400), one(0177400), "Bg"}, + {"movql", one(0070000), one(0170400), "MsDd"}, {"moveql", one(0070000), one(0170400), "MsDd"}, {"moval", one(0020100), one(0170700), "*lAd"}, {"movaw", one(0030100), one(0170700), "*wAd"}, {"movb", one(0010000), one(0170000), ";b$d"}, /* mov */ +{"movl", one(0070000), one(0170400), "MsDd"}, /* movq written as mov */ {"movl", one(0020000), one(0170000), "*l$d"}, {"movl", one(0020100), one(0170700), "*lAd"}, {"movl", one(0047140), one(0177770), "AsUd"}, /* mov to USP */ {"movl", one(0047150), one(0177770), "UdAs"}, /* mov from USP */ -{"movl", one(0070000), one(0170400), "MsDd"}, /* movq written as mov */ +{"movc", one(0047173), one(0177777), "R1Jj"}, +{"movc", one(0047173), one(0177777), "R1#j"}, +{"movc", one(0047172), one(0177777), "JjR1"}, +{"movc", one(0047172), one(0177777), "#jR1"}, {"movml", one(0044300), one(0177700), "#w&s"}, /* movm reg to mem. */ {"movml", one(0044340), one(0177770), "#w-s"}, /* movm reg to autodecrement. */ {"movml", one(0046300), one(0177700), "!s#w"}, /* movm mem to reg. */ {"movml", one(0046330), one(0177770), "+s#w"}, /* movm autoinc to reg. */ +{"movml", one(0044300), one(0177700), "Lw&s"}, /* movm reg to mem. */ +{"movml", one(0044340), one(0177770), "lw-s"}, /* movm reg to autodecrement. */ +{"movml", one(0046300), one(0177700), "!sLw"}, /* movm mem to reg. */ +{"movml", one(0046330), one(0177770), "+sLw"}, /* movm autoinc to reg. */ {"movmw", one(0044200), one(0177700), "#w&s"}, /* movm reg to mem. */ {"movmw", one(0044240), one(0177770), "#w-s"}, /* movm reg to autodecrement. */ {"movmw", one(0046200), one(0177700), "!s#w"}, /* movm mem to reg. */ {"movmw", one(0046230), one(0177770), "+s#w"}, /* movm autoinc to reg. */ +{"movmw", one(0044200), one(0177700), "Lw&s"}, /* movm reg to mem. */ +{"movmw", one(0044240), one(0177770), "lw-s"}, /* movm reg to autodecrement. */ +{"movmw", one(0046200), one(0177700), "!sLw"}, /* movm mem to reg. */ +{"movmw", one(0046230), one(0177770), "+sLw"}, /* movm autoinc to reg. */ {"movpl", one(0000510), one(0170770), "dsDd"}, /* memory to register */ {"movpl", one(0000710), one(0170770), "Ddds"}, /* register to memory */ {"movpw", one(0000410), one(0170770), "dsDd"}, /* memory to register */ @@ -1259,7 +1462,6 @@ struct m68k_opcode m68k_opcodes[] = {"movw", one(0041300), one(0177700), "Cs$s"}, /* Move from ccr */ {"movw", one(0042300), one(0177700), ";wCd"}, /* mov to ccr */ {"movw", one(0043300), one(0177700), ";wSd"}, /* mov to sr */ -/* movc not done*/ {"movsb", two(0007000, 0), two(0177700, 07777), "~sR1"}, {"movsb", two(0007000, 04000), two(0177700, 07777), "R1~s"}, @@ -1267,8 +1469,209 @@ struct m68k_opcode m68k_opcodes[] = {"movsl", two(0007200, 04000), two(0177700, 07777), "R1~s"}, {"movsw", two(0007100, 0), two(0177700, 07777), "~sR1"}, {"movsw", two(0007100, 04000), two(0177700, 07777), "R1~s"}, + +#ifdef m68851 + /* name */ /* opcode */ /* match */ /* args */ + +{"pbac", one(0xf0c7), one(0xffbf), "Bc"}, +{"pbacw", one(0xf087), one(0xffbf), "Bc"}, +{"pbas", one(0xf0c6), one(0xffbf), "Bc"}, +{"pbasw", one(0xf086), one(0xffbf), "Bc"}, +{"pbbc", one(0xf0c1), one(0xffbf), "Bc"}, +{"pbbcw", one(0xf081), one(0xffbf), "Bc"}, +{"pbbs", one(0xf0c0), one(0xffbf), "Bc"}, +{"pbbsw", one(0xf080), one(0xffbf), "Bc"}, +{"pbcc", one(0xf0cf), one(0xffbf), "Bc"}, +{"pbccw", one(0xf08f), one(0xffbf), "Bc"}, +{"pbcs", one(0xf0ce), one(0xffbf), "Bc"}, +{"pbcsw", one(0xf08e), one(0xffbf), "Bc"}, +{"pbgc", one(0xf0cd), one(0xffbf), "Bc"}, +{"pbgcw", one(0xf08d), one(0xffbf), "Bc"}, +{"pbgs", one(0xf0cc), one(0xffbf), "Bc"}, +{"pbgsw", one(0xf08c), one(0xffbf), "Bc"}, +{"pbic", one(0xf0cb), one(0xffbf), "Bc"}, +{"pbicw", one(0xf08b), one(0xffbf), "Bc"}, +{"pbis", one(0xf0ca), one(0xffbf), "Bc"}, +{"pbisw", one(0xf08a), one(0xffbf), "Bc"}, +{"pblc", one(0xf0c3), one(0xffbf), "Bc"}, +{"pblcw", one(0xf083), one(0xffbf), "Bc"}, +{"pbls", one(0xf0c2), one(0xffbf), "Bc"}, +{"pblsw", one(0xf082), one(0xffbf), "Bc"}, +{"pbsc", one(0xf0c5), one(0xffbf), "Bc"}, +{"pbscw", one(0xf085), one(0xffbf), "Bc"}, +{"pbss", one(0xf0c4), one(0xffbf), "Bc"}, +{"pbssw", one(0xf084), one(0xffbf), "Bc"}, +{"pbwc", one(0xf0c9), one(0xffbf), "Bc"}, +{"pbwcw", one(0xf089), one(0xffbf), "Bc"}, +{"pbws", one(0xf0c8), one(0xffbf), "Bc"}, +{"pbwsw", one(0xf088), one(0xffbf), "Bc"}, + + +{"pdbac", two(0xf048, 0x0007), two(0xfff8, 0xffff), "DsBw"}, +{"pdbas", two(0xf048, 0x0006), two(0xfff8, 0xffff), "DsBw"}, +{"pdbbc", two(0xf048, 0x0001), two(0xfff8, 0xffff), "DsBw"}, +{"pdbbs", two(0xf048, 0x0000), two(0xfff8, 0xffff), "DsBw"}, +{"pdbcc", two(0xf048, 0x000f), two(0xfff8, 0xffff), "DsBw"}, +{"pdbcs", two(0xf048, 0x000e), two(0xfff8, 0xffff), "DsBw"}, +{"pdbgc", two(0xf048, 0x000d), two(0xfff8, 0xffff), "DsBw"}, +{"pdbgs", two(0xf048, 0x000c), two(0xfff8, 0xffff), "DsBw"}, +{"pdbic", two(0xf048, 0x000b), two(0xfff8, 0xffff), "DsBw"}, +{"pdbis", two(0xf048, 0x000a), two(0xfff8, 0xffff), "DsBw"}, +{"pdblc", two(0xf048, 0x0003), two(0xfff8, 0xffff), "DsBw"}, +{"pdbls", two(0xf048, 0x0002), two(0xfff8, 0xffff), "DsBw"}, +{"pdbsc", two(0xf048, 0x0005), two(0xfff8, 0xffff), "DsBw"}, +{"pdbss", two(0xf048, 0x0004), two(0xfff8, 0xffff), "DsBw"}, +{"pdbwc", two(0xf048, 0x0009), two(0xfff8, 0xffff), "DsBw"}, +{"pdbws", two(0xf048, 0x0008), two(0xfff8, 0xffff), "DsBw"}, + +{"pflusha", two(0xf000, 0x2400), two(0xffff, 0xffff), "" }, + +{"pflush", two(0xf000, 0x3010), two(0xffc0, 0xfe10), "T3T9" }, +{"pflush", two(0xf000, 0x3810), two(0xffc0, 0xfe10), "T3T9&s" }, +{"pflush", two(0xf000, 0x3008), two(0xffc0, 0xfe18), "D3T9" }, +{"pflush", two(0xf000, 0x3808), two(0xffc0, 0xfe18), "D3T9&s" }, +{"pflush", two(0xf000, 0x3000), two(0xffc0, 0xfe1e), "f3T9" }, +{"pflush", two(0xf000, 0x3800), two(0xffc0, 0xfe1e), "f3T9&s" }, + +{"pflushs", two(0xf000, 0x3410), two(0xfff8, 0xfe10), "T3T9" }, +{"pflushs", two(0xf000, 0x3c00), two(0xfff8, 0xfe00), "T3T9&s" }, +{"pflushs", two(0xf000, 0x3408), two(0xfff8, 0xfe18), "D3T9" }, +{"pflushs", two(0xf000, 0x3c08), two(0xfff8, 0xfe18), "D3T9&s" }, +{"pflushs", two(0xf000, 0x3400), two(0xfff8, 0xfe1e), "f3T9" }, +{"pflushs", two(0xf000, 0x3c00), two(0xfff8, 0xfe1e), "f3T9&s"}, + +{"pflushr", two(0xf000, 0xa000), two(0xffc0, 0xffff), "|s" }, + +{"ploadr", two(0xf000, 0x2210), two(0xffc0, 0xfff0), "T3&s" }, +{"ploadr", two(0xf000, 0x2208), two(0xffc0, 0xfff8), "D3&s" }, +{"ploadr", two(0xf000, 0x2200), two(0xffc0, 0xfffe), "f3&s" }, +{"ploadw", two(0xf000, 0x2010), two(0xffc0, 0xfff0), "T3&s" }, +{"ploadw", two(0xf000, 0x2008), two(0xffc0, 0xfff8), "D3&s" }, +{"ploadw", two(0xf000, 0x2000), two(0xffc0, 0xfffe), "f3&s" }, + +/* TC, CRP, DRP, SRP, CAL, VAL, SCC, AC */ +{"pmove", two(0xf000, 0x4000), two(0xffc0, 0xe3ff), "*sP8" }, +{"pmove", two(0xf000, 0x4200), two(0xffc0, 0xe3ff), "P8%s" }, +{"pmove", two(0xf000, 0x4000), two(0xffc0, 0xe3ff), "|sW8" }, +{"pmove", two(0xf000, 0x4200), two(0xffc0, 0xe3ff), "W8~s" }, + +/* BADx, BACx */ +{"pmove", two(0xf000, 0x6200), two(0xffc0, 0xe3e3), "*sX3" }, +{"pmove", two(0xf000, 0x6000), two(0xffc0, 0xe3e3), "X3%s" }, + +/* PSR, PCSR */ +/* {"pmove", two(0xf000, 0x6100), two(oxffc0, oxffff), "*sZ8" }, */ +{"pmove", two(0xf000, 0x6000), two(0xffc0, 0xffff), "*sY8" }, +{"pmove", two(0xf000, 0x6200), two(0xffc0, 0xffff), "Y8%s" }, +{"pmove", two(0xf000, 0x6600), two(0xffc0, 0xffff), "Z8%s" }, + +{"prestore", one(0xf140), one(0xffc0), "&s"}, +{"prestore", one(0xf158), one(0xfff8), "+s"}, +{"psave", one(0xf100), one(0xffc0), "&s"}, +{"psave", one(0xf100), one(0xffc0), "+s"}, + +{"psac", two(0xf040, 0x0007), two(0xffc0, 0xffff), "@s"}, +{"psas", two(0xf040, 0x0006), two(0xffc0, 0xffff), "@s"}, +{"psbc", two(0xf040, 0x0001), two(0xffc0, 0xffff), "@s"}, +{"psbs", two(0xf040, 0x0000), two(0xffc0, 0xffff), "@s"}, +{"pscc", two(0xf040, 0x000f), two(0xffc0, 0xffff), "@s"}, +{"pscs", two(0xf040, 0x000e), two(0xffc0, 0xffff), "@s"}, +{"psgc", two(0xf040, 0x000d), two(0xffc0, 0xffff), "@s"}, +{"psgs", two(0xf040, 0x000c), two(0xffc0, 0xffff), "@s"}, +{"psic", two(0xf040, 0x000b), two(0xffc0, 0xffff), "@s"}, +{"psis", two(0xf040, 0x000a), two(0xffc0, 0xffff), "@s"}, +{"pslc", two(0xf040, 0x0003), two(0xffc0, 0xffff), "@s"}, +{"psls", two(0xf040, 0x0002), two(0xffc0, 0xffff), "@s"}, +{"pssc", two(0xf040, 0x0005), two(0xffc0, 0xffff), "@s"}, +{"psss", two(0xf040, 0x0004), two(0xffc0, 0xffff), "@s"}, +{"pswc", two(0xf040, 0x0009), two(0xffc0, 0xffff), "@s"}, +{"psws", two(0xf040, 0x0008), two(0xffc0, 0xffff), "@s"}, + +{"ptestr", two(0xf000, 0x8210), two(0xffc0, 0xe3f0), "T3&sQ8" }, +{"ptestr", two(0xf000, 0x8310), two(0xffc0, 0xe310), "T3&sQ8A9" }, +{"ptestr", two(0xf000, 0x8208), two(0xffc0, 0xe3f8), "D3&sQ8" }, +{"ptestr", two(0xf000, 0x8308), two(0xffc0, 0xe318), "D3&sQ8A9" }, +{"ptestr", two(0xf000, 0x8200), two(0xffc0, 0xe3fe), "f3&sQ8" }, +{"ptestr", two(0xf000, 0x8300), two(0xffc0, 0xe31e), "f3&sQ8A9" }, + +{"ptestw", two(0xf000, 0x8010), two(0xffc0, 0xe3f0), "T3&sQ8" }, +{"ptestw", two(0xf000, 0x8110), two(0xffc0, 0xe310), "T3&sQ8A9" }, +{"ptestw", two(0xf000, 0x8008), two(0xffc0, 0xe3f8), "D3&sQ8" }, +{"ptestw", two(0xf000, 0x8108), two(0xffc0, 0xe318), "D3&sQ8A9" }, +{"ptestw", two(0xf000, 0x8000), two(0xffc0, 0xe3fe), "f3&sQ8" }, +{"ptestw", two(0xf000, 0x8100), two(0xffc0, 0xe31e), "f3&sQ8A9" }, + +{"ptrapacw", two(0xf07a, 0x0007), two(0xffff, 0xffff), "#w"}, +{"ptrapacl", two(0xf07b, 0x0007), two(0xffff, 0xffff), "#l"}, +{"ptrapac", two(0xf07c, 0x0007), two(0xffff, 0xffff), ""}, + +{"ptrapasw", two(0xf07a, 0x0006), two(0xffff, 0xffff), "#w"}, +{"ptrapasl", two(0xf07b, 0x0006), two(0xffff, 0xffff), "#l"}, +{"ptrapas", two(0xf07c, 0x0006), two(0xffff, 0xffff), ""}, + +{"ptrapbcw", two(0xf07a, 0x0001), two(0xffff, 0xffff), "#w"}, +{"ptrapbcl", two(0xf07b, 0x0001), two(0xffff, 0xffff), "#l"}, +{"ptrapbc", two(0xf07c, 0x0001), two(0xffff, 0xffff), ""}, + +{"ptrapbsw", two(0xf07a, 0x0000), two(0xffff, 0xffff), "#w"}, +{"ptrapbsl", two(0xf07b, 0x0000), two(0xffff, 0xffff), "#l"}, +{"ptrapbs", two(0xf07c, 0x0000), two(0xffff, 0xffff), ""}, + +{"ptrapccw", two(0xf07a, 0x000f), two(0xffff, 0xffff), "#w"}, +{"ptrapccl", two(0xf07b, 0x000f), two(0xffff, 0xffff), "#l"}, +{"ptrapcc", two(0xf07c, 0x000f), two(0xffff, 0xffff), ""}, + +{"ptrapcsw", two(0xf07a, 0x000e), two(0xffff, 0xffff), "#w"}, +{"ptrapcsl", two(0xf07b, 0x000e), two(0xffff, 0xffff), "#l"}, +{"ptrapcs", two(0xf07c, 0x000e), two(0xffff, 0xffff), ""}, + +{"ptrapgcw", two(0xf07a, 0x000d), two(0xffff, 0xffff), "#w"}, +{"ptrapgcl", two(0xf07b, 0x000d), two(0xffff, 0xffff), "#l"}, +{"ptrapgc", two(0xf07c, 0x000d), two(0xffff, 0xffff), ""}, + +{"ptrapgsw", two(0xf07a, 0x000c), two(0xffff, 0xffff), "#w"}, +{"ptrapgsl", two(0xf07b, 0x000c), two(0xffff, 0xffff), "#l"}, +{"ptrapgs", two(0xf07c, 0x000c), two(0xffff, 0xffff), ""}, + +{"ptrapicw", two(0xf07a, 0x000b), two(0xffff, 0xffff), "#w"}, +{"ptrapicl", two(0xf07b, 0x000b), two(0xffff, 0xffff), "#l"}, +{"ptrapic", two(0xf07c, 0x000b), two(0xffff, 0xffff), ""}, + +{"ptrapisw", two(0xf07a, 0x000a), two(0xffff, 0xffff), "#w"}, +{"ptrapisl", two(0xf07b, 0x000a), two(0xffff, 0xffff), "#l"}, +{"ptrapis", two(0xf07c, 0x000a), two(0xffff, 0xffff), ""}, + +{"ptraplcw", two(0xf07a, 0x0003), two(0xffff, 0xffff), "#w"}, +{"ptraplcl", two(0xf07b, 0x0003), two(0xffff, 0xffff), "#l"}, +{"ptraplc", two(0xf07c, 0x0003), two(0xffff, 0xffff), ""}, + +{"ptraplsw", two(0xf07a, 0x0002), two(0xffff, 0xffff), "#w"}, +{"ptraplsl", two(0xf07b, 0x0002), two(0xffff, 0xffff), "#l"}, +{"ptrapls", two(0xf07c, 0x0002), two(0xffff, 0xffff), ""}, + +{"ptrapscw", two(0xf07a, 0x0005), two(0xffff, 0xffff), "#w"}, +{"ptrapscl", two(0xf07b, 0x0005), two(0xffff, 0xffff), "#l"}, +{"ptrapsc", two(0xf07c, 0x0005), two(0xffff, 0xffff), ""}, + +{"ptrapssw", two(0xf07a, 0x0004), two(0xffff, 0xffff), "#w"}, +{"ptrapssl", two(0xf07b, 0x0004), two(0xffff, 0xffff), "#l"}, +{"ptrapss", two(0xf07c, 0x0004), two(0xffff, 0xffff), ""}, + +{"ptrapwcw", two(0xf07a, 0x0009), two(0xffff, 0xffff), "#w"}, +{"ptrapwcl", two(0xf07b, 0x0009), two(0xffff, 0xffff), "#l"}, +{"ptrapwc", two(0xf07c, 0x0009), two(0xffff, 0xffff), ""}, + +{"ptrapwsw", two(0xf07a, 0x0008), two(0xffff, 0xffff), "#w"}, +{"ptrapwsl", two(0xf07b, 0x0008), two(0xffff, 0xffff), "#l"}, +{"ptrapws", two(0xf07c, 0x0008), two(0xffff, 0xffff), ""}, + +{"pvalid", two(0xf000, 0x2800), two(0xffc0, 0xffff), "Vs&s"}, +{"pvalid", two(0xf000, 0x2c00), two(0xffc0, 0xfff8), "A3&s" }, + +#endif /* m68851 */ + }; int numopcodes=sizeof(m68k_opcodes)/sizeof(m68k_opcodes[0]); -struct m68k_opcode *endop = m68k_opcodes+sizeof(m68k_opcodes)/sizeof(m68k_opcodes[0]);; +struct m68k_opcode *endop = m68k_opcodes+sizeof(m68k_opcodes)/sizeof(m68k_opcodes[0]); diff --git a/gdb/m68k-pinsn.c b/gdb/m68k-pinsn.c index c9e8af66f9..6a67431533 100644 --- a/gdb/m68k-pinsn.c +++ b/gdb/m68k-pinsn.c @@ -1,25 +1,27 @@ /* Print m68k instructions for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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 +#include +#include + #include "defs.h" #include "param.h" #include "symtab.h" @@ -118,11 +120,11 @@ print_insn (memaddr, stream) /* Handle undefined instructions. */ if (best < 0) { - fprintf (stream, "0%o", (buffer[0] << 8) + buffer[1]); + fprintf_filtered (stream, "0%o", (buffer[0] << 8) + buffer[1]); return 2; } - fprintf (stream, "%s", m68k_opcodes[best].name); + fprintf_filtered (stream, "%s", m68k_opcodes[best].name); /* Point at first word of argument data, and at descriptor for first argument. */ @@ -142,19 +144,21 @@ print_insn (memaddr, stream) p = buffer + 4; if (d[1] >= '4' && d[1] <= '6' && p - buffer < 6) p = buffer + 6; + if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4) + p = buffer + 4; } d = m68k_opcodes[best].args; if (*d) - fputc (' ', stream); + fputs_filtered (" ", stream); while (*d) { p = print_insn_arg (d, buffer, p, memaddr + p - buffer, stream); d += 2; if (*d && *(d - 2) != 'I' && *d != 'k') - fprintf (stream, ","); + fputs_filtered (",", stream); } return p - buffer; } @@ -178,15 +182,15 @@ print_insn_arg (d, buffer, p, addr, stream) switch (*d) { case 'C': - fprintf (stream, "ccr"); + fprintf_filtered (stream, "ccr"); break; case 'S': - fprintf (stream, "sr"); + fprintf_filtered (stream, "sr"); break; case 'U': - fprintf (stream, "usp"); + fprintf_filtered (stream, "usp"); break; case 'J': @@ -200,73 +204,76 @@ print_insn_arg (d, buffer, p, addr, stream) for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--) if (names[regno].value == val) { - fprintf (stream, names[regno].name); + fprintf_filtered (stream, names[regno].name); break; } if (regno < 0) - fprintf (stream, "%d", val); + fprintf_filtered (stream, "%d", val); } break; case 'Q': val = fetch_arg (buffer, place, 3); if (val == 0) val = 8; - fprintf (stream, "#%d", val); + fprintf_filtered (stream, "#%d", val); break; case 'M': val = fetch_arg (buffer, place, 8); if (val & 0x80) val = val - 0x100; - fprintf (stream, "#%d", val); + fprintf_filtered (stream, "#%d", val); break; case 'T': val = fetch_arg (buffer, place, 4); - fprintf (stream, "#%d", val); + fprintf_filtered (stream, "#%d", val); break; case 'D': - fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 3)]); + fprintf_filtered (stream, "%s", reg_names[fetch_arg (buffer, place, 3)]); break; case 'A': - fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 3) + 010]); + fprintf_filtered (stream, "%s", + reg_names[fetch_arg (buffer, place, 3) + 010]); break; case 'R': - fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 4)]); + fprintf_filtered (stream, "%s", reg_names[fetch_arg (buffer, place, 4)]); break; case 'F': - fprintf (stream, "fp%d", fetch_arg (buffer, place, 3)); + fprintf_filtered (stream, "fp%d", fetch_arg (buffer, place, 3)); break; case 'O': val = fetch_arg (buffer, place, 6); if (val & 0x20) - fprintf (stream, "%s", reg_names [val & 7]); + fprintf_filtered (stream, "%s", reg_names [val & 7]); else - fprintf (stream, "%d", val); + fprintf_filtered (stream, "%d", val); break; case '+': - fprintf (stream, "(%s)+", reg_names[fetch_arg (buffer, place, 3) + 8]); + fprintf_filtered (stream, "%s@+", + reg_names[fetch_arg (buffer, place, 3) + 8]); break; case '-': - fprintf (stream, "-(%s)", reg_names[fetch_arg (buffer, place, 3) + 8]); + fprintf_filtered (stream, "%s@-", + reg_names[fetch_arg (buffer, place, 3) + 8]); break; case 'k': if (place == 'k') - fprintf (stream, "{%s}", reg_names[fetch_arg (buffer, place, 3)]); + fprintf_filtered (stream, "{%s}", reg_names[fetch_arg (buffer, place, 3)]); else if (place == 'C') { val = fetch_arg (buffer, place, 7); if ( val > 63 ) /* This is a signed constant. */ val -= 128; - fprintf (stream, "{#%d}", val); + fprintf_filtered (stream, "{#%d}", val); } else error ("Invalid arg format in opcode table: \"%c%c\".", @@ -274,7 +281,8 @@ print_insn_arg (d, buffer, p, addr, stream) break; case '#': - p1 = buffer + 2; + case '^': + p1 = buffer + (*d == '#' ? 2 : 4); if (place == 's') val = fetch_arg (buffer, place, 4); else if (place == 'C') @@ -292,26 +300,7 @@ print_insn_arg (d, buffer, p, addr, stream) else error ("Invalid arg format in opcode table: \"%c%c\".", *d, place); - fprintf (stream, "#%d", val); - break; - - case '^': - if (place == 's') - val = fetch_arg (buffer, place, 4); - else if (place == 'C') - val = fetch_arg (buffer, place, 7); - else if (place == '8') - val = fetch_arg (buffer, place, 3); - else if (place == 'b') - val = NEXTBYTE (p); - else if (place == 'w') - val = NEXTWORD (p); - else if (place == 'l') - val = NEXTLONG (p); - else - error ("Invalid arg format in opcode table: \"%c%c\".", - *d, place); - fprintf (stream, "#%d", val); + fprintf_filtered (stream, "#%d", val); break; case 'B': @@ -345,17 +334,19 @@ print_insn_arg (d, buffer, p, addr, stream) case 'd': val = NEXTWORD (p); - fprintf (stream, "%d(%s)", val, reg_names[fetch_arg (buffer, place, 3)]); + fprintf_filtered (stream, "%s@(%d)", + reg_names[fetch_arg (buffer, place, 3)], val); break; case 's': - fprintf (stream, "%s", fpcr_names[fetch_arg (buffer, place, 3)]); + fprintf_filtered (stream, "%s", + fpcr_names[fetch_arg (buffer, place, 3)]); break; case 'I': val = fetch_arg (buffer, 'd', 3); /* Get coprocessor ID... */ if (val != 1) /* Unusual coprocessor ID? */ - fprintf (stream, "(cpid=%d) ", val); + fprintf_filtered (stream, "(cpid=%d) ", val); if (place == 'i') p += 2; /* Skip coprocessor extended operands */ break; @@ -385,28 +376,28 @@ print_insn_arg (d, buffer, p, addr, stream) switch (val >> 3) { case 0: - fprintf (stream, "%s", reg_names[val]); + fprintf_filtered (stream, "%s", reg_names[val]); break; case 1: - fprintf (stream, "%s", regname); + fprintf_filtered (stream, "%s", regname); break; case 2: - fprintf (stream, "(%s)", regname); + fprintf_filtered (stream, "%s@", regname); break; case 3: - fprintf (stream, "(%s)+", regname); + fprintf_filtered (stream, "%s@+", regname); break; case 4: - fprintf (stream, "-(%s)", regname); + fprintf_filtered (stream, "%s@-", regname); break; case 5: val = NEXTWORD (p); - fprintf (stream, "%d(%s)", val, regname); + fprintf_filtered (stream, "%s@(%d)", regname, val); break; case 6: @@ -418,13 +409,13 @@ print_insn_arg (d, buffer, p, addr, stream) { case 0: val = NEXTWORD (p); - fprintf (stream, "@#"); + fprintf_filtered (stream, "@#"); print_address (val, stream); break; case 1: val = NEXTLONG (p); - fprintf (stream, "@#"); + fprintf_filtered (stream, "@#"); print_address (val, stream); break; @@ -477,17 +468,96 @@ print_insn_arg (d, buffer, p, addr, stream) *d, place); } if ( flt_p ) /* Print a float? */ - fprintf (stream, "#%g", flval); + fprintf_filtered (stream, "#%g", flval); else - fprintf (stream, "#%d", val); + fprintf_filtered (stream, "#%d", val); break; default: - fprintf (stream, "", val); + fprintf_filtered (stream, "", val); } } break; + case 'L': + case 'l': + if (place == 'w') + { + char doneany; + p1 = buffer + 2; + val = NEXTWORD (p1); + /* Move the pointer ahead if this point is farther ahead + than the last. */ + p = p1 > p ? p1 : p; + if (val == 0) + { + fputs_filtered ("#0", stream); + break; + } + if (*d == 'l') + { + register int newval = 0; + for (regno = 0; regno < 16; ++regno) + if (val & (0x8000 >> regno)) + newval |= 1 << regno; + val = newval; + } + val &= 0xffff; + doneany = 0; + for (regno = 0; regno < 16; ++regno) + if (val & (1 << regno)) + { + int first_regno; + if (doneany) + fputs_filtered ("/", stream); + doneany = 1; + fprintf_filtered (stream, "%s", reg_names[regno]); + first_regno = regno; + while (val & (1 << (regno + 1))) + ++regno; + if (regno > first_regno) + fprintf_filtered (stream, "-%s", reg_names[regno]); + } + } + else if (place == '3') + { + /* `fmovem' insn. */ + char doneany; + val = fetch_arg (buffer, place, 8); + if (val == 0) + { + fputs_filtered ("#0", stream); + break; + } + if (*d == 'l') + { + register int newval = 0; + for (regno = 0; regno < 8; ++regno) + if (val & (0x80 >> regno)) + newval |= 1 << regno; + val = newval; + } + val &= 0xff; + doneany = 0; + for (regno = 0; regno < 8; ++regno) + if (val & (1 << regno)) + { + int first_regno; + if (doneany) + fputs_filtered ("/", stream); + doneany = 1; + fprintf_filtered (stream, "fp%d", regno); + first_regno = regno; + while (val & (1 << (regno + 1))) + ++regno; + if (regno > first_regno) + fprintf_filtered (stream, "-fp%d", regno); + } + } + else + abort (); + break; + default: error ("Invalid arg format in opcode table: \"%c\".", *d); } @@ -629,7 +699,7 @@ print_indexed (basereg, p, addr, stream) ((word & 0x80) ? word | 0xff00 : word & 0xff) + ((basereg == -1) ? addr : 0), stream); - fprintf (stream, "%s", buf); + fputs_filtered (buf, stream); return p; } @@ -657,7 +727,7 @@ print_indexed (basereg, p, addr, stream) if ((word & 7) == 0) { print_base (basereg, base_disp, stream); - fprintf (stream, "%s", buf); + fputs_filtered (buf, stream); return p; } @@ -673,15 +743,15 @@ print_indexed (basereg, p, addr, stream) outer_disp = NEXTLONG (p); } - fprintf (stream, "%d(", outer_disp); + fprintf_filtered (stream, "%d(", outer_disp); print_base (basereg, base_disp, stream); /* If postindexed, print the closeparen before the index. */ if (word & 4) - fprintf (stream, ")%s", buf); + fprintf_filtered (stream, ")%s", buf); /* If preindexed, print the closeparen after the index. */ else - fprintf (stream, "%s)", buf); + fprintf_filtered (stream, "%s)", buf); return p; } @@ -696,13 +766,15 @@ print_base (regno, disp, stream) FILE *stream; { if (regno == -2) - fprintf (stream, "%d", disp); + fprintf_filtered (stream, "%d", disp); else if (regno == -1) - fprintf (stream, "0x%x", disp); + fprintf_filtered (stream, "0x%x", disp); else - fprintf (stream, "%d(%s)", disp, reg_names[regno]); + fprintf_filtered (stream, "%d(%s)", disp, reg_names[regno]); } +static int have_fpu = 1; + /* This is not part of insn printing, but it is machine-specific, so this is a convenient place to put it. @@ -714,12 +786,17 @@ convert_from_68881 (from, to) char *from; double *to; { -#ifdef USG_SGS_ASM + if (!have_fpu) + { + *to = 0.0; + return; + } +#ifdef HPUX_ASM asm ("mov.l 8(%a6),%a0"); asm ("mov.l 12(%a6),%a1"); asm ("fmove.x (%a0),%fp0"); asm ("fmove.d %fp0,(%a1)"); -#else /* not USG_SGS_ASM */ +#else /* not HPUX_ASM */ #if 0 asm ("movl a6@(8),a0"); asm ("movl a6@(12),a1"); @@ -735,7 +812,7 @@ convert_from_68881 (from, to) asm (".long 0xf2104800"); asm (".long 0xf2117400"); #endif -#endif /* not USG_SGS_ASM */ +#endif /* not HPUX_ASM */ } /* The converse: convert the double *FROM to an extended float @@ -745,12 +822,14 @@ convert_to_68881 (from, to) double *from; char *to; { -#ifdef USG_SGS_ASM + if (!have_fpu) + return; +#ifdef HPUX_ASM asm ("mov.l 8(%a6),%a0"); asm ("mov.l 12(%a6),%a1"); asm ("fmove.d (%a0),%fp0"); asm ("fmove.x %fp0,(%a1)"); -#else /* not USG_SGS_ASM */ +#else /* not HPUX_ASM */ #if 0 asm ("movl a6@(8),a0"); asm ("movl a6@(12),a1"); @@ -765,5 +844,37 @@ convert_to_68881 (from, to) asm (".long 0xf2105400"); asm (".long 0xf2116800"); #endif -#endif /* not USG_SGS_ASM */ +#endif /* not HPUX_ASM */ +} + +static jmp_buf fpu_check; + +void +sigemt() +{ + have_fpu = 0; + longjmp (fpu_check, 1); +} + +void +_initialize_pinsn() +{ + /* Want to figure out if we've got a coprocessor. The idea is to catch the + signal that gets delivered if no coprocessor is around (SIGEMT) then + execute a coprocessor instruction and see what happens. have_fpu is set + to zero if the EMT signal arrives. Else it is left at 1. */ + /* If this turns out not to be portable to all 68k machines, we'll + have to move it to the dep files. */ + void (*emthandler) (); + + emthandler = (void (*) ()) signal (SIGEMT, sigemt); + if (!setjmp (fpu_check)) + { +#if defined(HPUX_ASM) + asm (" long 0xf2000600"); /* fmovel fp0, d0 */ +#else + asm(".long 0xf2000600"); /* fmovel fp0, d0 */ +#endif + } + signal(SIGEMT, emthandler); } diff --git a/gdb/main.c b/gdb/main.c index 5cd5e80904..ee923c4e45 100644 --- a/gdb/main.c +++ b/gdb/main.c @@ -1,22 +1,22 @@ /* Top level for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1988 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! -*/ + 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 "command.h" #include "param.h" @@ -31,14 +31,24 @@ anyone else from sharing it farther. Help stamp out software hoarding! #include #include #include +#include #ifdef SET_STACK_LIMIT_HUGE #include #include +#include int original_stack_limit; #endif +/* If this definition isn't overridden by the header files, assume + that isatty and fileno exist on this system. */ +#ifndef ISATTY +#define ISATTY(FP) (isatty (fileno (FP))) +#endif + +extern void free (); + /* Version number of GDB, as a string. */ extern char *version; @@ -75,6 +85,14 @@ struct cmd_list_element *enablebreaklist; struct cmd_list_element *setlist; +/* Chain containing all defined \"set history\". */ + +struct cmd_list_element *sethistlist; + +/* Chain containing all defined \"unset history\". */ + +struct cmd_list_element *unsethistlist; + /* stdio stream that command input is being read from. */ FILE *instream; @@ -86,6 +104,10 @@ char *current_directory; /* The directory name is actually stored here (usually). */ static char dirbuf[MAXPATHLEN]; +/* The number of lines on a page, and the number of spaces + in a line. */ +int linesize, pagesize; + /* Nonzero if we should refrain from using an X window. */ int inhibit_windows = 0; @@ -97,14 +119,20 @@ int inhibit_windows = 0; void (*window_hook) (); extern int frame_file_full_name; +int xgdb_verbose; void free_command_lines (); -char *gdb_read_line (); -static void init_main (); -static void init_cmd_lists (); +char *gdb_readline (); +char *command_line_input (); +static void initialize_main (); +static void initialize_cmd_lists (); void command_loop (); static void source_command (); static void print_gdb_version (); +static void float_handler (); +static void cd_command (); + +char *getenv (); /* gdb prints this when reading a command interactively */ static char *prompt; @@ -114,6 +142,15 @@ static char *prompt; char *line; int linesize; + + +/* Signal to catch ^Z typed while reading a command: SIGTSTP or SIGCONT. */ + +#ifndef STOP_SIGNAL +#ifdef SIGTSTP +#define STOP_SIGNAL SIGTSTP +#endif +#endif /* This is how `error' returns to command level. */ @@ -126,7 +163,7 @@ return_to_top_level () immediate_quit = 0; clear_breakpoint_commands (); clear_momentary_breakpoints (); - delete_current_display (); + disable_current_display (); do_cleanups (0); longjmp (to_top_level, 1); } @@ -196,7 +233,6 @@ main (argc, argv, envp) char **argv; char **envp; { - extern void request_quit (); int count; int inhibit_gdbinit = 0; int quiet = 0; @@ -238,20 +274,18 @@ main (argc, argv, envp) batch = 1, quiet = 1; else if (!strcmp (argv[i], "-fullname")) frame_file_full_name = 1; + else if (!strcmp (argv[i], "-xgdb_verbose")) + xgdb_verbose = 1; else if (argv[i][0] == '-') i++; } /* Run the init function of each source file */ - init_cmd_lists (); /* This needs to be done first */ - init_all_files (); - init_main (); /* But that omits this file! Do it now */ - - signal (SIGINT, request_quit); - signal (SIGQUIT, SIG_IGN); - if (signal (SIGHUP, SIG_IGN) != SIG_IGN) - signal (SIGHUP, disconnect); + initialize_cmd_lists (); /* This needs to be done first */ + initialize_all_files (); + initialize_main (); /* But that omits this file! Do it now */ + initialize_signals (); if (!quiet) print_gdb_version (); @@ -272,7 +306,8 @@ main (argc, argv, envp) if (!strcmp (arg, "-q") || !strcmp (arg, "-nx") || !strcmp (arg, "-quiet") || !strcmp (arg, "-batch") - || !strcmp (arg, "-fullname")) + || !strcmp (arg, "-fullname") || !strcmp (arg, "-nw") + || !strcmp (arg, "-xgdb_verbose")) /* Already processed above */ continue; @@ -306,11 +341,7 @@ main (argc, argv, envp) GDB remembers the precise string FOO as the dirname. */ else if (!strcmp (arg, "-cd")) { - int len = strlen (argv[i]); - current_directory = argv[i]; - if (len > 1 && current_directory[len - 1] == '/') - current_directory = savestring (current_directory, len-1); - chdir (current_directory); + cd_command (argv[i], 0); init_source_path (); } /* -t /def/ttyp1: use /dev/ttyp1 for inferior I/O. */ @@ -345,25 +376,54 @@ main (argc, argv, envp) } } - /* Read init file, if it exists in home directory */ - if (getenv ("HOME")) - { - char *s; - s = (char *) xmalloc (strlen (getenv ("HOME")) + 10); - strcpy (s, getenv ("HOME")); - strcat (s, "/.gdbinit"); - if (!inhibit_gdbinit && access (s, R_OK) == 0) - if (!setjmp (to_top_level)) - source_command (s); - } + { + struct stat homebuf, cwdbuf; + char *homedir, *homeinit; - /* Read init file, if it exists in current directory. */ - if (!inhibit_gdbinit && access (".gdbinit", R_OK) == 0) - if (!setjmp (to_top_level)) - source_command (".gdbinit"); + /* Read init file, if it exists in home directory */ + homedir = getenv ("HOME"); + if (homedir) + { + homeinit = (char *) alloca (strlen (getenv ("HOME")) + 10); + strcpy (homeinit, getenv ("HOME")); + strcat (homeinit, "/.gdbinit"); + if (!inhibit_gdbinit && access (homeinit, R_OK) == 0) + if (!setjmp (to_top_level)) + source_command (homeinit); + + /* Do stats; no need to do them elsewhere since we'll only + need them if homedir is set. Make sure that they are + zero in case one of them fails (guarantees that they + won't match if either exits). */ + + bzero (&homebuf, sizeof (struct stat)); + bzero (&cwdbuf, sizeof (struct stat)); + + stat (homeinit, &homebuf); + stat ("./.gdbinit", &cwdbuf); /* We'll only need this if + homedir was set. */ + } + + /* Read the input file in the current directory, *if* it isn't + the same file (it should exist, also). */ + + if (!homedir + || bcmp ((char *) &homebuf, + (char *) &cwdbuf, + sizeof (struct stat))) + if (!inhibit_gdbinit && access (".gdbinit", R_OK) == 0) + if (!setjmp (to_top_level)) + source_command (".gdbinit"); + } if (batch) - fatal ("Attempt to read commands from stdin in batch mode."); + { +#if 0 + fatal ("Attempt to read commands from stdin in batch mode."); +#endif + /* We have hit the end of the batch file. */ + exit (0); + } if (!quiet) printf ("Type \"help\" for a list of commands.\n"); @@ -393,7 +453,7 @@ execute_command (p, from_tty) while (*p == ' ' || *p == '\t') p++; if (*p) { - c = lookup_cmd (&p, cmdlist, "", 0); + c = lookup_cmd (&p, cmdlist, "", 0, 1); if (c->function == 0) error ("That is not a command, just a help topic."); else if (c->class == (int) class_user) @@ -441,8 +501,10 @@ command_loop () (*window_hook) (instream, prompt); quit_flag = 0; + if (instream == stdin && ISATTY (stdin)) + reinitialize_more_filter (); old_chain = make_cleanup (do_nothing, 0); - execute_command (gdb_read_line (instream == stdin ? prompt : 0, + execute_command (command_line_input (instream == stdin ? prompt : 0, instream == stdin), instream == stdin); /* Do any commands attached to breakpoint we stopped at. */ @@ -451,102 +513,448 @@ command_loop () } } -#ifdef SIGTSTP +/* Commands call this if they do not want to be repeated by null lines. */ + +void +dont_repeat () +{ + /* If we aren't reading from standard input, we are saving the last + thing read from stdin in line and don't want to delete it. Null lines + won't repeat here in any case. */ + if (instream == stdin) + *line = 0; +} + +/* Read a line from the stream "instream" without command line editing. + + It prints PROMPT once at the start. + + If RETURN_RESULT is set it allocates + space for whatever the user types and returns the result. + If not, it just discards what the user types. */ +char * +gdb_readline (prompt, return_result) + char *prompt; + int return_result; +{ + int c; + char *result; + int input_index = 0; + int result_size = 80; + + if (prompt) + { + printf (prompt); + fflush (stdout); + } + + if (return_result) + result = (char *) xmalloc (result_size); + + while (1) + { + c = fgetc (instream); + if (c == -1 || c == '\n') + break; + if (return_result) + { + result[input_index++] = c; + while (input_index >= result_size) + { + result_size *= 2; + result = (char *) xrealloc (result, result_size); + } + } + } + if (return_result) + { + result[input_index++] = '\0'; + return result; + } + else + return (char *) 0; +} + +/* Declaration for fancy readline with command line editing. */ +char *readline (); + +/* Variables which control command line editing and history + substitution. These variables are given default values at the end + of this file. */ +static int command_editing_p; +static int history_expansion_p; +static int write_history_p; +static int history_size; +static char *history_filename; + +/* Variables which are necessary for fancy command line editing. */ +char *gdb_completer_word_break_characters = + " \t\n!@#$%^&*()-+=|~`}{[]\"';:?/>.<,"; + +/* Functions that are used as part of the fancy command line editing. */ + +/* Generate symbol names one by one for the completer. If STATE is + zero, then we need to initialize, otherwise the initialization has + already taken place. TEXT is what we expect the symbol to start + with. RL_LINE_BUFFER is available to be looked at; it contains the + entire text of the line. RL_POINT is the offset in that line of + the cursor. You should pretend that the line ends at RL_POINT. */ +char * +symbol_completion_function (text, state) + char *text; + int state; +{ + char **make_symbol_completion_list (); + static char **list = (char **)NULL; + static int index; + char *output; + extern char *rl_line_buffer; + extern int rl_point; + char *tmp_command, *p; + struct cmd_list_element *c, *result_list; + + if (!state) + { + /* Free the storage used by LIST, but not by the strings inside. This is + because rl_complete_internal () frees the strings. */ + if (list) + free (list); + list = 0; + index = 0; + + /* Decide whether to complete on a list of gdb commands or on + symbols. */ + tmp_command = (char *) alloca (rl_point + 1); + p = tmp_command; + + strncpy (tmp_command, rl_line_buffer, rl_point); + tmp_command[rl_point] = '\0'; + + if (rl_point == 0) + { + /* An empty line we want to consider ambiguous; that is, + it could be any command. */ + c = (struct cmd_list_element *) -1; + result_list = 0; + } + else + c = lookup_cmd_1 (&p, cmdlist, &result_list, 1); + + /* Move p up to the next interesting thing. */ + while (*p == ' ' || *p == '\t') + p++; + + if (!c) + /* He's typed something unrecognizable. Sigh. */ + list = (char **) 0; + else if (c == (struct cmd_list_element *) -1) + { + if (p + strlen(text) != tmp_command + rl_point) + error ("Unrecognized command."); + + /* He's typed something ambiguous. This is easier. */ + if (result_list) + list = complete_on_cmdlist (*result_list->prefixlist, text); + else + list = complete_on_cmdlist (cmdlist, text); + } + else + { + /* If we've gotten this far, gdb has recognized a full + command. There are several possibilities: + + 1) We need to complete on the command. + 2) We need to complete on the possibilities coming after + the command. + 2) We need to complete the text of what comes after the + command. */ + + if (!*p && *text) + /* Always (might be longer versions of thie command). */ + list = complete_on_cmdlist (result_list, text); + else if (!*p && !*text) + { + if (c->prefixlist) + list = complete_on_cmdlist (*c->prefixlist, ""); + else + list = make_symbol_completion_list (""); + } + else + { + if (c->prefixlist && !c->allow_unknown) + { + *p = '\0'; + error ("\"%s\" command requires a subcommand.", + tmp_command); + } + else + list = make_symbol_completion_list (text); + } + } + } + + /* If the debugged program wasn't compiled with symbols, or if we're + clearly completing on a command and no command matches, return + NULL. */ + if (!list) + return ((char *)NULL); + + output = list[index]; + if (output) + index++; + + return (output); +} + +#ifdef STOP_SIGNAL static void stop_sig () { +#if STOP_SIGNAL == SIGTSTP signal (SIGTSTP, SIG_DFL); sigsetmask (0); kill (getpid (), SIGTSTP); signal (SIGTSTP, stop_sig); +#else + signal (STOP_SIGNAL, stop_sig); +#endif printf ("%s", prompt); fflush (stdout); /* Forget about any previous command -- null line now will do nothing. */ - *line = 0; + dont_repeat (); } -#endif /* SIGTSTP */ +#endif /* STOP_SIGNAL */ + +#if 0 +Writing the history file upon a terminating signal is not useful, + because the info is rarely relevant and is in the core dump anyway. + It is an annoyance to have the file cluttering up the place. +/* The list of signals that would terminate us if not caught. + We catch them, but just so that we can write the history file, + and so forth. */ +int terminating_signals[] = { + SIGHUP, SIGINT, SIGILL, SIGTRAP, SIGIOT, + SIGEMT, SIGFPE, SIGKILL, SIGBUS, SIGSEGV, SIGSYS, + SIGPIPE, SIGALRM, SIGTERM, +#ifdef SIGXCPU + SIGXCPU, +#endif +#ifdef SIGXFSZ + SIGXFSZ, +#endif +#ifdef SIGVTALRM + SIGVTALRM, +#endif +#ifdef SIGPROF + SIGPROF, +#endif +#ifdef SIGLOST + SIGLOST, +#endif +#ifdef SIGUSR1 + SIGUSR1, SIGUSR2 +#endif + }; -/* Commands call this if they do not want to be repeated by null lines. */ +#define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (int)) -void -dont_repeat () +static void +catch_termination (sig) + int sig; { - *line = 0; + /* We are probably here because GDB has a bug. Write out the history + so that we might have a better chance of reproducing it. */ + /* Tell the user what we are doing so he can delete the file if + it is unwanted. */ + write_history (history_filename); + printf ("\n%s written.\n", history_filename); + signal (sig, SIG_DFL); + kill (getpid (), sig); } +#endif + +/* Initialize signal handlers. */ +initialize_signals () +{ + extern void request_quit (); +#if 0 + register int i; + + for (i = 0; i < TERMSIGS_LENGTH; i++) + signal (terminating_signals[i], catch_termination); +#endif + + signal (SIGINT, request_quit); + /* If we initialize SIGQUIT to SIG_IGN, then the SIG_IGN will get + passed to the inferior, which we don't want. It would be + possible to do a "signal (SIGQUIT, SIG_DFL)" after we fork, but + on BSD4.3 systems using vfork, that will (apparently) affect the + GDB process as well as the inferior (the signal handling tables + being shared between the two, apparently). Since we establish + a handler for SIGQUIT, when we call exec it will set the signal + to SIG_DFL for us. */ + signal (SIGQUIT, do_nothing); + if (signal (SIGHUP, do_nothing) != SIG_IGN) + signal (SIGHUP, disconnect); + signal (SIGFPE, float_handler); +} + /* Read one line from the command input stream `instream' - into the buffer `line' (whose current length is `linesize'). + into the local static buffer `linebuffer' (whose current length + is `linelength'). The buffer is made bigger as necessary. - Returns the address of the start of the line. */ + Returns the address of the start of the line. + + *If* the instream == stdin & stdin is a terminal, the line read + is copied into the file line saver (global var char *line, + length linesize) so that it can be duplicated. + + This routine either uses fancy command line editing or + simple input as the user has requested. */ char * -gdb_read_line (prompt, repeat) +command_line_input (prompt, repeat) char *prompt; int repeat; { - register char *p = line; - register char *p1; + static char *linebuffer = 0; + static int linelength = 0; + register char *p; + register char *p1, *rl; + char *local_prompt = prompt; register int c; char *nline; + if (linebuffer == 0) + { + linelength = 80; + linebuffer = (char *) xmalloc (linelength); + } + + p = linebuffer; + /* Control-C quits instantly if typed while in this loop since it should not wait until the user types a newline. */ immediate_quit++; -#ifdef SIGTSTP - signal (SIGTSTP, stop_sig); +#ifdef STOP_SIGNAL + signal (STOP_SIGNAL, stop_sig); #endif - if (prompt) - { - printf (prompt); - fflush (stdout); - } - while (1) { - c = fgetc (instream); - if (c == -1 || c == '\n') - break; - /* Ignore backslash-newline; keep adding to the same line. */ - else if (c == '\\') - { - int c1 = fgetc (instream); - if (c1 == '\n') - continue; - else - ungetc (c1, instream); - } + /* Don't use fancy stuff if not talking to stdin. */ + if (command_editing_p && instream == stdin + && ISATTY (instream)) + rl = readline (local_prompt); + else + rl = gdb_readline (local_prompt, 1); - if (p - line == linesize - 1) + if (!rl || rl == (char *) EOF) break; + if (strlen(rl) + 1 + (p - linebuffer) > linelength) { - linesize *= 2; - nline = (char *) xrealloc (line, linesize); - p += nline - line; - line = nline; + linelength = strlen(rl) + 1 + (p - linebuffer); + nline = (char *) xrealloc (linebuffer, linelength); + p += nline - linebuffer; + linebuffer = nline; } - *p++ = c; - } + p1 = rl; + /* Copy line. Don't copy null at end. (Leaves line alone + if this was just a newline) */ + while (*p1) + *p++ = *p1++; -#ifdef SIGTSTP + free (rl); /* Allocated in readline. */ + + if (p == linebuffer || *(p - 1) != '\\') + break; + + p--; /* Put on top of '\'. */ + local_prompt = (char *) 0; + } + +#ifdef STOP_SIGNAL signal (SIGTSTP, SIG_DFL); #endif immediate_quit--; + /* Do history expansion if that is wished. */ + if (history_expansion_p && instream == stdin + && ISATTY (instream)) + { + char *history_value; + int expanded; + + *p = '\0'; /* Insert null now. */ + expanded = history_expand (linebuffer, &history_value); + if (expanded) + { + /* Print the changes. */ + printf ("%s\n", history_value); + + /* If there was an error, call this function again. */ + if (expanded < 0) + { + free (history_value); + return command_line_input (prompt, repeat); + } + if (strlen (history_value) > linelength) + { + linelength = strlen (history_value) + 1; + linebuffer = (char *) xrealloc (linebuffer, linelength); + } + strcpy (linebuffer, history_value); + p = linebuffer + strlen(linebuffer); + free (history_value); + } + } + /* If we just got an empty line, and that is supposed - to repeat the previous command, leave the last input unchanged. */ - if (p == line && repeat) - return line; + to repeat the previous command, return the value in the + global buffer. */ + if (repeat) + { + if (p == linebuffer) + return line; + p1 = linebuffer; + while (*p1 == ' ' || *p1 == '\t') + p1++; + if (!*p1) + return line; + } + + *p = 0; + + /* Add line to history if appropriate. */ + if (instream == stdin + && ISATTY (stdin) && *linebuffer) + add_history (linebuffer); /* If line is a comment, clear it out. */ - p1 = line; + /* Note: comments are added to the command history. + This is useful when you type a command, and then realize + you don't want to execute it quite yet. You can comment out the + command and then later fetch it from the value history and + remove the '#'. */ + p1 = linebuffer; while ((c = *p1) == ' ' || c == '\t') p1++; if (c == '#') - p = line; + *linebuffer = 0; - *p = 0; + /* Save into global buffer if appropriate. */ + if (repeat) + { + if (linelength > linesize) + { + line = xrealloc (line, linelength); + linesize = linelength; + } + strcpy (line, linebuffer); + return line; + } - return line; + return linebuffer; } /* Read lines from the input stream @@ -564,7 +972,7 @@ read_command_lines () while (1) { dont_repeat (); - p = gdb_read_line (0, 1); + p = command_line_input (0, instream == stdin); /* Remove leading and trailing blanks. */ while (*p == ' ' || *p == '\t') p++; p1 = p + strlen (p); @@ -723,7 +1131,7 @@ define_command (comname, from_tty) validate_comname (comname); - c = lookup_cmd (&tem, cmdlist, "", -1); + c = lookup_cmd (&tem, cmdlist, "", -1, 1); if (c) { if (c->class == (int) class_user || c->class == (int) class_alias) @@ -763,7 +1171,7 @@ document_command (comname, from_tty) validate_comname (comname); - c = lookup_cmd (&tem, cmdlist, "", 0); + c = lookup_cmd (&tem, cmdlist, "", 0, 1); if (c->class != (int) class_user) error ("Command \"%s\" is built-in.", comname); @@ -798,192 +1206,9 @@ End with a line saying just \"end\".\n", comname); } static void -copying_info () -{ - immediate_quit++; - printf (" GDB GENERAL PUBLIC LICENSE\n\ - (Clarified 11 Feb 1988)\n\ -\n\ - Copyright (C) 1988 Richard M. Stallman\n\ - Everyone is permitted to copy and distribute verbatim copies\n\ - of this license, but changing it is not allowed.\n\ - You can also use this wording to make the terms for other programs.\n\ -\n\ - The license agreements of most software companies keep you at the\n\ -mercy of those companies. By contrast, our general public license is\n\ -intended to give everyone the right to share GDB. To make sure that\n\ -you get the rights we want you to have, we need to make restrictions\n\ -that forbid anyone to deny you these rights or to ask you to surrender\n\ -the rights. Hence this license agreement.\n\ -\n\ - Specifically, we want to make sure that you have the right to give\n\ -away copies of GDB, that you receive source code or else can get it\n\ -if you want it, that you can change GDB or use pieces of it in new\n\ -free programs, and that you know you can do these things.\n\ ---Type Return to print more--"); - fflush (stdout); - gdb_read_line (0, 0); - - printf ("\ - To make sure that everyone has such rights, we have to forbid you to\n\ -deprive anyone else of these rights. For example, if you distribute\n\ -copies of GDB, you must give the recipients all the rights that you\n\ -have. You must make sure that they, too, receive or can get the\n\ -source code. And you must tell them their rights.\n\ -\n\ - Also, for our own protection, we must make certain that everyone\n\ -finds out that there is no warranty for GDB. If GDB is modified by\n\ -someone else and passed on, we want its recipients to know that what\n\ -they have is not what we distributed, so that any problems introduced\n\ -by others will not reflect on our reputation.\n\ -\n\ - Therefore we (Richard Stallman and the Free Software Foundation,\n\ -Inc.) make the following terms which say what you must do to be\n\ -allowed to distribute or change GDB.\n\ ---Type Return to print more--"); - fflush (stdout); - gdb_read_line (0, 0); - - printf ("\ - COPYING POLICIES\n\ -\n\ - 1. You may copy and distribute verbatim copies of GDB source code as\n\ -you receive it, in any medium, provided that you conspicuously and\n\ -appropriately publish on each copy a valid copyright notice \"Copyright\n\ -\(C) 1988 Free Software Foundation, Inc.\" (or with whatever year is\n\ -appropriate); keep intact the notices on all files that refer\n\ -to this License Agreement and to the absence of any warranty; and give\n\ -any other recipients of the GDB program a copy of this License\n\ -Agreement along with the program. You may charge a distribution fee\n\ -for the physical act of transferring a copy.\n\ -\n\ - 2. You may modify your copy or copies of GDB or any portion of it,\n\ -and copy and distribute such modifications under the terms of\n\ -Paragraph 1 above, provided that you also do the following:\n\ -\n\ - a) cause the modified files to carry prominent notices stating\n\ - that you changed the files and the date of any change; and\n\ ---Type Return to print more--"); - fflush (stdout); - gdb_read_line (0, 0); - - printf ("\ - b) cause the whole of any work that you distribute or publish,\n\ - that in whole or in part contains or is a derivative of GDB\n\ - or any part thereof, to be licensed to all third parties on terms\n\ - identical to those contained in this License Agreement (except that\n\ - you may choose to grant more extensive warranty protection to some\n\ - or all third parties, at your option).\n\ -\n"); - printf ("\ - c) if the modified program serves as a debugger, cause it\n\ - when started running in the simplest and usual way, to print\n\ - an announcement including a valid copyright notice\n\ - \"Copyright (C) 1988 Free Software Foundation, Inc.\" (or with\n\ - the year that is appropriate), saying that there is no warranty\n\ - (or else, saying that you provide a warranty) and that users may\n\ - redistribute the program under these conditions, and telling the user\n\ - how to view a copy of this License Agreement.\n\ -\n\ - d) You may charge a distribution fee for the physical act of\n\ - transferring a copy, and you may at your option offer warranty\n\ - protection in exchange for a fee.\n\ -\n\ -Mere aggregation of another unrelated program with this program (or its\n\ -derivative) on a volume of a storage or distribution medium does not bring\n\ -the other program under the scope of these terms.\n\ ---Type Return to print more--"); - fflush (stdout); - gdb_read_line (0, 0); - - printf ("\ - 3. You may copy and distribute GDB (or a portion or derivative of it,\n\ -under Paragraph 2) in object code or executable form under the terms of\n\ -Paragraphs 1 and 2 above provided that you also do one of the following:\n\ -\n\ - a) accompany it with the complete corresponding machine-readable\n\ - source code, which must be distributed under the terms of\n\ - Paragraphs 1 and 2 above; or,\n\ -\n\ - b) accompany it with a written offer, valid for at least three\n\ - years, to give any third party free (except for a nominal\n\ - shipping charge) a complete machine-readable copy of the\n\ - corresponding source code, to be distributed under the terms of\n\ - Paragraphs 1 and 2 above; or,\n\n"); - - printf ("\ - c) accompany it with the information you received as to where the\n\ - corresponding source code may be obtained. (This alternative is\n\ - allowed only for noncommercial distribution and only if you\n\ - received the program in object code or executable form alone.)\n\ -\n\ -For an executable file, complete source code means all the source code for\n\ -all modules it contains; but, as a special exception, it need not include\n\ -source code for modules which are standard libraries that accompany the\n\ -operating system on which the executable file runs.\n\ ---Type Return to print more--"); - fflush (stdout); - gdb_read_line (0, 0); - - printf ("\ - 4. You may not copy, sublicense, distribute or transfer GDB\n\ -except as expressly provided under this License Agreement. Any attempt\n\ -otherwise to copy, sublicense, distribute or transfer GDB is void and\n\ -your rights to use the program under this License agreement shall be\n\ -automatically terminated. However, parties who have received computer\n\ -software programs from you with this License Agreement will not have\n\ -their licenses terminated so long as such parties remain in full compliance.\n\ -\n\ -"); - printf ("\ - 5. If you wish to incorporate parts of GDB into other free\n\ -programs whose distribution conditions are different, write to the Free\n\ -Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet\n\ -worked out a simple rule that can be stated here, but we will often permit\n\ -this. We will be guided by the two goals of preserving the free status of\n\ -all derivatives of our free software and of promoting the sharing and reuse\n\ -of software.\n\ -\n\ -In other words, go ahead and share GDB, but don't try to stop\n\ -anyone else from sharing it farther. Help stamp out software hoarding!\n\ -"); - immediate_quit--; -} - -static void -warranty_info () -{ - immediate_quit++; - printf (" NO WARRANTY\n\ -\n\ - BECAUSE GDB IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO\n\ -WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT\n\ -WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,\n\ -RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE GDB \"AS IS\" WITHOUT\n\ -WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT\n\ -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n\ -A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND\n\ -PERFORMANCE OF GDB IS WITH YOU. SHOULD GDB PROVE DEFECTIVE, YOU\n\ -ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n"); - - printf ("\ - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.\n\ -STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY\n\ -WHO MAY MODIFY AND REDISTRIBUTE GDB, BE LIABLE TO\n\ -YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER\n\ -SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR\n\ -INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA\n\ -BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A\n\ -FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GDB, EVEN\n\ -IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR\n\ -ANY CLAIM BY ANY OTHER PARTY.\n"); - immediate_quit--; -} - -static void print_gdb_version () { - printf ("GDB %s, Copyright (C) 1988 Free Software Foundation, Inc.\n\ + printf ("GDB %s, Copyright (C) 1989 Free Software Foundation, Inc.\n\ There is ABSOLUTELY NO WARRANTY for GDB; type \"info warranty\" for details.\n\ GDB is free software and you are welcome to distribute copies of it\n\ under certain conditions; type \"info copying\" to see the conditions.\n", @@ -1062,6 +1287,9 @@ quit_command () else error ("Not confirmed."); } + /* Save the history information if it is appropriate to do so. */ + if (write_history_p && history_filename) + write_history (history_filename); exit (0); } @@ -1097,6 +1325,9 @@ cd_command (dir, from_tty) if (dir == 0) error_no_arg ("new working directory"); + dir = tilde_expand (dir); + make_cleanup (free, dir); + len = strlen (dir); dir = savestring (dir, len - (len > 1 && dir[len-1] == '/')); if (dir[0] == '/') @@ -1144,14 +1375,20 @@ cd_command (dir, from_tty) } static void -source_command (file) - char *file; +source_command (arg, from_tty) + char *arg; + int from_tty; { FILE *stream; struct cleanup *cleanups; + char *file = arg; if (file == 0) - error_no_arg ("file to read commands from"); + /* Let source without arguments read .gdbinit. */ + file = ".gdbinit"; + + file = tilde_expand (file); + make_cleanup (free, file); stream = fopen (file, "r"); if (stream == 0) @@ -1201,9 +1438,238 @@ dump_me_command () kill (getpid (), SIGQUIT); } } + +int +parse_binary_operation (caller, arg) + char *caller, *arg; +{ + int length; + + if (!arg || !*arg) + return 1; + + length = strlen (arg); + + while (arg[length - 1] == ' ' || arg[length - 1] == '\t') + length--; + + if (!strncmp (arg, "on", length) + || !strncmp (arg, "1", length) + || !strncmp (arg, "yes", length)) + return 1; + else + if (!strncmp (arg, "off", length) + || !strncmp (arg, "0", length) + || !strncmp (arg, "no", length)) + return 0; + else + error ("\"%s\" not given a binary valued argument.", caller); +} + +/* Functions to manipulate command line editing control variables. */ + +static void +set_editing (arg, from_tty) + char *arg; + int from_tty; +{ + command_editing_p = parse_binary_operation ("set command-editing", arg); +} + +/* Number of commands to print in each call to editing_info. */ +#define Hist_print 10 +static void +editing_info (arg, from_tty) + char *arg; + int from_tty; +{ + /* Index for history commands. Relative to history_base. */ + int offset; + + /* Number of the history entry which we are planning to display next. + Relative to history_base. */ + static int num = 0; + + /* The first command in the history which doesn't exist (i.e. one more + than the number of the last command). Relative to history_base. */ + int hist_len; + + struct _hist_entry { + char *line; + char *data; + } *history_get(); + extern int history_base; + + printf_filtered ("Interactive command editing is %s.\n", + command_editing_p ? "on" : "off"); + + printf_filtered ("History expansion of command input is %s.\n", + history_expansion_p ? "on" : "off"); + printf_filtered ("Writing of a history record upon exit is %s.\n", + write_history_p ? "enabled" : "disabled"); + printf_filtered ("The size of the history list (number of stored commands) is %d.\n", + history_size); + printf_filtered ("The name of the history record is \"%s\".\n\n", + history_filename ? history_filename : ""); + + /* Print out some of the commands from the command history. */ + /* First determine the length of the history list. */ + hist_len = history_size; + for (offset = 0; offset < history_size; offset++) + { + if (!history_get (history_base + offset)) + { + hist_len = offset; + break; + } + } + + if (arg) + { + if (arg[0] == '+' && arg[1] == '\0') + /* "info editing +" should print from the stored position. */ + ; + else + /* "info editing " should print around command number . */ + num = (parse_and_eval_address (arg) - history_base) - Hist_print / 2; + } + /* "info editing" means print the last Hist_print commands. */ + else + { + num = hist_len - Hist_print; + } + + if (num < 0) + num = 0; + + /* If there are at least Hist_print commands, we want to display the last + Hist_print rather than, say, the last 6. */ + if (hist_len - num < Hist_print) + { + num = hist_len - Hist_print; + if (num < 0) + num = 0; + } + + if (num == hist_len - Hist_print) + printf_filtered ("The list of the last %d commands is:\n\n", Hist_print); + else + printf_filtered ("Some of the stored commands are:\n\n"); + + for (offset = num; offset < num + Hist_print && offset < hist_len; offset++) + { + printf_filtered ("%5d %s\n", history_base + offset, + (history_get (history_base + offset))->line); + } + + /* The next command we want to display is the next one that we haven't + displayed yet. */ + num += Hist_print; + + /* If the user repeats this command with return, it should do what + "info editing +" does. This is unnecessary if arg is null, + because "info editing +" is not useful after "info editing". */ + if (from_tty && arg) + { + arg[0] = '+'; + arg[1] = '\0'; + } +} + +static void +set_history_expansion (arg, from_tty) + char *arg; + int from_tty; +{ + history_expansion_p = parse_binary_operation ("set history expansion", arg); +} + +static void +set_history_write (arg, from_tty) + char *arg; + int from_tty; +{ + write_history_p = parse_binary_operation ("set history write", arg); +} + +static void +set_history (arg, from_tty) + char *arg; + int from_tty; +{ + printf ("\"set history\" must be followed by the name of a history subcommand.\n"); + help_list (sethistlist, "set history ", -1, stdout); +} + +static void +set_history_size (arg, from_tty) + char *arg; + int from_tty; +{ + if (!*arg) + error_no_arg ("set history size"); + + history_size = atoi (arg); +} + +static void +set_history_filename (arg, from_tty) + char *arg; + int from_tty; +{ + int i; + + if (!arg) + error_no_arg ("history file name"); + + arg = tilde_expand (arg); + make_cleanup (free, arg); + + i = strlen (arg) - 1; + + free (history_filename); + + while (i > 0 && (arg[i] == ' ' || arg[i] == '\t')) + i--; + + if (!*arg) + history_filename = (char *) 0; + else + history_filename = savestring (arg, i + 1); + history_filename[i] = '\0'; +} + +int info_verbose; + +static void +set_verbose_command (arg, from_tty) + char *arg; + int from_tty; +{ + info_verbose = parse_binary_operation ("set verbose", arg); +} + +static void +verbose_info (arg, from_tty) + char *arg; + int from_tty; +{ + if (arg) + error ("\"info verbose\" does not take any arguments.\n"); + + printf ("Verbose printing of information is %s.\n", + info_verbose ? "on" : "off"); +} + +static void +float_handler () +{ + error ("Invalid floating value encountered or computed."); +} + static void -init_cmd_lists () +initialize_cmd_lists () { cmdlist = (struct cmd_list_element *) 0; infolist = (struct cmd_list_element *) 0; @@ -1212,13 +1678,49 @@ init_cmd_lists () deletelist = (struct cmd_list_element *) 0; enablebreaklist = (struct cmd_list_element *) 0; setlist = (struct cmd_list_element *) 0; + sethistlist = (struct cmd_list_element *) 0; + unsethistlist = (struct cmd_list_element *) 0; } static void -init_main () +initialize_main () { + char *tmpenv; + /* Command line editing externals. */ + extern int (*rl_completion_entry_function)(); + extern char *rl_completer_word_break_characters; + + /* Set default verbose mode on. */ + info_verbose = 1; + prompt = savestring ("(gdb) ", 6); + /* Set the important stuff up for command editing. */ + command_editing_p = 1; + history_expansion_p = 0; + write_history_p = 0; + + if (tmpenv = getenv ("HISTSIZE")) + history_size = atoi (tmpenv); + else + history_size = 256; + + stifle_history (history_size); + + if (tmpenv = getenv ("GDBHISTFILE")) + history_filename = savestring (tmpenv, strlen(tmpenv)); + else + /* We include the current directory so that if the user changes + directories the file written will be the same as the one + that was read. */ + history_filename = concat (current_directory, "/.gdb_history", ""); + + read_history (history_filename); + + /* Setup important stuff for command line editing. */ + rl_completion_entry_function = (int (*)()) symbol_completion_function; + rl_completer_word_break_characters = gdb_completer_word_break_characters; + /* Define the classes of commands. They will appear in the help list in the reverse of this order. */ @@ -1280,15 +1782,47 @@ when gdb is started."); add_com_alias ("q", "quit", class_support, 1); add_com_alias ("h", "help", class_support, 1); + add_cmd ("verbose", class_support, set_verbose_command, + "Change the number of informational messages gdb prints.", + &setlist); + add_info ("verbose", verbose_info, + "Status of gdb's verbose printing option.\n"); + add_com ("dump-me", class_obscure, dump_me_command, "Get fatal error; make debugger dump its core."); + add_cmd ("editing", class_support, set_editing, + "Enable or disable command line editing.\n\ +Use \"on\" to enable to enable the editing, and \"off\" to disable it.\n\ +Without an argument, command line editing is enabled.", &setlist); + + add_prefix_cmd ("history", class_support, set_history, + "Generic command for setting command history parameters.", + &sethistlist, "set history ", 0, &setlist); + + add_cmd ("expansion", no_class, set_history_expansion, + "Enable or disable history expansion on command input.\n\ +Without an argument, history expansion is enabled.", &sethistlist); + + add_cmd ("write", no_class, set_history_write, + "Enable or disable saving of the history record on exit.\n\ +Use \"on\" to enable to enable the saving, and \"off\" to disable it.\n\ +Without an argument, saving is enabled.", &sethistlist); + + add_cmd ("size", no_class, set_history_size, + "Set the size of the command history, \n\ +ie. the number of previous commands to keep a record of.", &sethistlist); + + add_cmd ("filename", no_class, set_history_filename, + "Set the filename in which to record the command history\n\ + (the list of previous commands of which a record is kept).", &sethistlist); + add_prefix_cmd ("info", class_info, info_command, "Generic command for printing status.", &infolist, "info ", 0, &cmdlist); add_com_alias ("i", "info", class_info, 1); - add_info ("copying", copying_info, "Conditions for redistributing copies of GDB."); - add_info ("warranty", warranty_info, "Various kinds of warranty you do not have."); + add_info ("editing", editing_info, "Status of command editor."); + add_info ("version", version_info, "Report what version of GDB this is."); } diff --git a/gdb/malloc.c b/gdb/malloc.c index 2099f0a069..2363e7bc08 100644 --- a/gdb/malloc.c +++ b/gdb/malloc.c @@ -142,8 +142,9 @@ what you give them. Help stamp out software-hoarding! */ */ #ifdef emacs +/* config.h specifies which kind of system this is. */ #include "config.h" -#endif /* emacs */ +#else /* Determine which kind of system this is. */ #include @@ -155,21 +156,27 @@ what you give them. Help stamp out software-hoarding! */ #endif /* not VMS */ #else /* SIGTSTP */ #ifdef SIGIO -#define BSD42 +#define BSD4_2 #endif /* SIGIO */ #endif /* SIGTSTP */ +#if defined(hpux) +#define USG +#endif + +#endif /* not emacs */ + /* Define getpagesize () if the system does not. */ #include "getpagesize.h" -#ifndef BSD42 +#ifndef BSD4_2 #ifndef USG #include /* warn the user when near the end */ #endif /* not USG */ -#else /* if BSD42 */ +#else /* if BSD4_2 */ #include #include -#endif /* BSD42 */ +#endif /* BSD4_2 */ extern char *start_of_data (); @@ -318,6 +325,7 @@ morecore (nu) /* ask system for more memory */ #ifdef BSD #ifndef BSD4_1 + /* ?? There was a suggestion not to block SIGILL, somehow for GDB's sake. */ oldmask = sigsetmask (-1); #endif #endif @@ -344,8 +352,6 @@ morecore (nu) /* ask system for more memory */ */ cp = sbrk (0); siz = cp - data_space_start; - malloc_sbrk_used = siz; - malloc_sbrk_unused = lim_data - siz; if (warnfunction) switch (warnlevel) @@ -384,7 +390,17 @@ morecore (nu) /* ask system for more memory */ nblks = 1 << ((siz = 8) - nu); if ((cp = sbrk (1 << (siz + 3))) == (char *) -1) - return; /* no more room! */ + { +#ifdef BSD +#ifndef BSD4_1 + sigsetmask (oldmask); +#endif +#endif + return; /* no more room! */ + } + malloc_sbrk_used = siz; + malloc_sbrk_unused = lim_data - siz; + #ifndef VMS if ((int) cp & 7) { /* shouldn't happen, but just in case */ @@ -461,8 +477,10 @@ malloc (n) /* get a block */ register int nunits = 0; /* Figure out how many bytes are required, rounding up to the nearest - multiple of 4, then figure out which nextf[] area to use */ - nbytes = (n + sizeof *p + EXTRA + 3) & ~3; + multiple of 8, then figure out which nestf[] area to use. + Both the beginning of the header and the beginning of the + block should be on an eight byte boundary. */ + nbytes = (n + ((sizeof *p + 7) & ~7) + EXTRA + 7) & ~7; { register unsigned int shiftr = (nbytes - 1) >> 2; @@ -507,7 +525,8 @@ malloc (n) /* get a block */ p -> mh_nbytes = n; p -> mh_magic4 = MAGIC4; { - register char *m = (char *) (p + 1) + n; + /* Get the location n after the beginning of the user's space. */ + register char *m = (char *) p + ((sizeof *p + 7) & ~7) + n; *m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1; } @@ -518,7 +537,7 @@ malloc (n) /* get a block */ nmalloc[nunits]++; nmal++; #endif /* MSTATS */ - return (char *) (p + 1); + return (char *) p + ((sizeof *p + 7) & ~7); } free (mem) @@ -531,18 +550,18 @@ free (mem) if (ap == 0) return; - p = (struct mhead *) ap - 1; + p = (struct mhead *) (ap - ((sizeof *p + 7) & ~7)); if (p -> mh_alloc == ISMEMALIGN) { ap -= p->mh_size; - p = (struct mhead *) ap - 1; + p = (struct mhead *) (ap - ((sizeof *p + 7) & ~7)); } #ifndef rcheck if (p -> mh_alloc != ISALLOC) abort (); -#else rcheck +#else /* rcheck */ if (p -> mh_alloc != ISALLOC) { if (p -> mh_alloc == ISFREE) @@ -587,9 +606,9 @@ realloc (mem, n) register unsigned int nbytes; register int nunits; - if ((p = (struct mhead *) mem) == 0) + if (mem == 0) return malloc (n); - p--; + p = (struct mhead *) (mem - ((sizeof *p + 7) & ~7)); nunits = p -> mh_index; ASSERT (p -> mh_alloc == ISALLOC); #ifdef rcheck @@ -601,13 +620,13 @@ realloc (mem, n) } #else /* not rcheck */ if (p -> mh_index >= 13) - tocopy = (1 << (p -> mh_index + 3)) - sizeof *p; + tocopy = (1 << (p -> mh_index + 3)) - ((sizeof *p + 7) & ~7); else tocopy = p -> mh_size; #endif /* not rcheck */ /* See if desired size rounds to same power of 2 as actual size. */ - nbytes = (n + sizeof *p + EXTRA + 7) & ~7; + nbytes = (n + ((sizeof *p + 7) & ~7) + EXTRA + 7) & ~7; /* If ok, use the same block, just marking its size as changed. */ if (nbytes > (4 << nunits) && nbytes <= (8 << nunits)) @@ -663,7 +682,7 @@ memalign (alignment, size) return aligned; } -#ifndef HPUX +#ifndef hpux /* This runs into trouble with getpagesize on HPUX. Patching out seems cleaner than the ugly fix needed. */ char * @@ -671,7 +690,7 @@ valloc (size) { return memalign (getpagesize (), size); } -#endif /* not HPUX */ +#endif /* not hpux */ #endif /* not VMS */ #ifdef MSTATS @@ -772,14 +791,14 @@ get_lim_data () } #else /* not USG */ -#ifndef BSD42 +#ifndef BSD4_2 get_lim_data () { lim_data = vlimit (LIM_DATA, -1); } -#else /* BSD42 */ +#else /* BSD4_2 */ get_lim_data () { @@ -793,7 +812,7 @@ get_lim_data () #endif } -#endif /* BSD42 */ +#endif /* BSD4_2 */ #endif /* not USG */ #ifdef VMS diff --git a/gdb/munch b/gdb/munch index daecee45de..eef3927fd1 100755 --- a/gdb/munch +++ b/gdb/munch @@ -1,14 +1,17 @@ #! /bin/sh # create an initialization procedure from a list of .o files -# Look in object files, find symbols including the string _initialize_, -# and call each one as a function. echo '/* Do not modify this file. It is created automatically by "munch". */' -echo 'void init_all_files () {' +echo 'void initialize_all_files () {' -nm $* | egrep '_initialize_' | \ - sed -e 's/^.*\(initialize_[a-zA-Z_0-9]*\).*$/ _\1 ();/' | \ - sort -u +if test "$1" = "-DSYSV" ; then + shift; + nm $* | egrep '^(.*[^a-zA-Z_]_|_)initialize_' | \ + sed -e 's/^.*\(_initialize_[a-zA-Z0-9_]*\)[^a-zA-Z0-9_].*$/ \1 ();/' +else + nm -p $* | egrep 'T *__initialize_' | \ + sed -e 's/^.*T *_*\(.*\)/ _\1 ();/' +fi echo '}' diff --git a/gdb/news-dep.c b/gdb/news-dep.c index fabaeaed2f..ff4397cfbc 100644 --- a/gdb/news-dep.c +++ b/gdb/news-dep.c @@ -1,22 +1,21 @@ /* Low level interface to ptrace, for GDB when running under Unix. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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" @@ -101,8 +100,12 @@ fetch_inferior_registers () register int i; struct user u; +#ifdef USE_PCB + unsigned int offset = (char *) &u.u_pcb.pcb_d0 - (char *) &u; +#else unsigned int offset = (char *) &u.u_ar0 - (char *) &u; offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR; +#endif for (regno = 0; regno < NUM_REGS; regno++) { @@ -125,34 +128,71 @@ store_inferior_registers (regno) { register unsigned int regaddr; char buf[80]; + extern char registers[]; struct user u; +#ifdef USE_PCB + unsigned int offset = (char *) &u.u_pcb.pcb_d0 - (char *) &u; +#else unsigned int offset = (char *) &u.u_ar0 - (char *) &u; offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR; +#endif +#ifdef PTRACE_BUG + if (regno >= FP0_REGNUM) + printf ("warning: floating register num %d not written due to OS bug.\n", + regno); + else +#endif if (regno >= 0) { + int i; + int *p = (int *) ®isters[REGISTER_BYTE (regno)]; + +#ifdef PTRACE_BUG + if (regno == FP_REGNUM) + printf ("warning: ptrace bug for writing register number fp(a6).\n"); +#endif + regaddr = register_addr (regno, offset); - errno = 0; - ptrace (6, inferior_pid, regaddr, read_register (regno)); - if (errno != 0) + for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int)) { - sprintf (buf, "writing register number %d", regno); - perror_with_name (buf); + errno = 0; + ptrace (6, inferior_pid, regaddr, *p++); + if (errno != 0) + { + sprintf (buf, "writing register number %d[%d]", regno, i); + perror_with_name (buf); + } + regaddr += sizeof (int); } } - /* Ptrace News OS cannot write floating register now(7/2/88), so - avoid the writing them. */ - else for (regno = 0; regno < FP0_REGNUM; regno++) + else { - regaddr = register_addr (regno, offset); - errno = 0; - ptrace (6, inferior_pid, regaddr, read_register (regno)); - if (errno != 0) +#ifdef PTRACE_BUG + for (regno = 0; regno < FP0_REGNUM; regno++) +#else + for (regno = 0; regno < NUM_REGS; regno++) +#endif { - sprintf (buf, "writing register number %d", regno); - perror_with_name (buf); + int i; + int *p = (int *) ®isters[REGISTER_BYTE (regno)]; + regaddr = register_addr (regno, offset); + for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int)) + { + errno = 0; + ptrace (6, inferior_pid, regaddr, *p++); + if (errno != 0) + { + sprintf (buf, "writing register number %d[%d]", regno, i); + perror_with_name (buf); + } + regaddr += sizeof (int); + } } +#ifdef PTRACE_BUG + printf ("warning: ptrace bug for writing floating registers(no write).\n"); +#endif } } @@ -262,11 +302,6 @@ write_inferior_memory (memaddr, myaddr, len) /* Work with core dump and executable files, for GDB. This code would be in core.c if it weren't machine-dependent. */ -/* Recognize COFF format systems because a.out.h defines AOUTHDR. */ -#ifdef AOUTHDR -#define COFF_FORMAT -#endif - #ifndef N_TXTADDR #define N_TXTADDR(hdr) 0 #endif /* no N_TXTADDR */ @@ -283,8 +318,10 @@ write_inferior_memory (memaddr, myaddr, len) #endif #ifndef COFF_FORMAT +#ifndef AOUTHDR #define AOUTHDR struct exec #endif +#endif extern char *sys_siglist[]; @@ -388,6 +425,9 @@ core_file_command (filename, from_tty) 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); @@ -476,6 +516,9 @@ exec_file_command (filename, from_tty) if (filename) { + filename = tilde_expand (filename); + make_cleanup (free, filename); + execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, &execfile); if (execchan < 0) @@ -545,3 +588,50 @@ exec_file_command (filename, from_tty) if (exec_file_display_hook) (*exec_file_display_hook) (filename); } + +#ifdef __GNUC__ +/* Bad implement execle(3). It's depend for "/bin/cc". + + main() + { + printf("execle:\n"); + execle(FILE, ARGS, envp); + exit(1); + } + + GCC: + link a6,#0 + pea LC5 ; call printf + jbsr _printf + ; ; (not popd stack) + pea _envp ; call execle + clrl sp@- + pea LC4 + pea LC4 + pea LC4 + pea LC3 + pea LC6 + jbsr _execle + addw #32,sp ; delayed pop !! + + /bin/cc: + link.l fp,#L23 + movem.l #L24,(sp) + pea L26 ; call printf + jbsr _printf + addq.l #4,sp ; <--- popd stack !! + pea _envp ; call execle + clr.l -(sp) + pea L32 + + */ + +execle(name, args) + char *name, *args; +{ + register char **env = &args; + while (*env++) + ; + execve(name, (char **)&args, (char **)*env); +} +#endif diff --git a/gdb/npl-opcode.h b/gdb/npl-opcode.h index a0421bbe75..f18982b843 100644 --- a/gdb/npl-opcode.h +++ b/gdb/npl-opcode.h @@ -1,22 +1,21 @@ /* Print GOULD NPL instructions for GDB, the GNU debugger. - Copyright (C) 1986, 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! -*/ + 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. */ struct gld_opcode { diff --git a/gdb/ns32k-opcode.h b/gdb/ns32k-opcode.h index f72d013c23..3679ef1a3f 100644 --- a/gdb/ns32k-opcode.h +++ b/gdb/ns32k-opcode.h @@ -19,6 +19,25 @@ struct not /* ns32k opcode text */ struct not_wot detail; /* rest of opcode table [datum] */ }; +/* Instructions look like this: + + basic instruction--1, 2, or 3 bytes + index byte for operand A, if operand A is indexed--1 byte + index byte for operand B, if operand B is indexed--1 byte + addressing extension for operand A + addressing extension for operand B + implied operands + + Operand A is the operand listed first in the following opcode table. + Operand B is the operand listed second in the following opcode table. + All instructions have at most 2 general operands, so this is enough. + The implied operands are associated with operands other than A and B. + + Each operand has a digit and a letter. + + The digit gives the position in the assembly language. The letter, + one of the following, tells us what kind of operand it is. */ + /* F : 32 bit float * L : 64 bit float * B : byte @@ -229,7 +248,7 @@ notstrs[] = { "notd", 14,24, 0x274e, "1D2D" }, { "orb", 6,16, 0x18, "1B1B" }, { "orw", 6,16, 0x19, "1W1W" }, - { "ord", 6,16, 0x1b, "1D1D" }, + { "ord", 6,16, 0x1b, "1D2D" }, { "quob", 14,24, 0x30ce, "1B2B" }, { "quow", 14,24, 0x31ce, "1W2W" }, { "quod", 14,24, 0x33ce, "1D2D" }, diff --git a/gdb/ns32k-pinsn.c b/gdb/ns32k-pinsn.c index 3247edb6f5..655c8991bb 100644 --- a/gdb/ns32k-pinsn.c +++ b/gdb/ns32k-pinsn.c @@ -116,6 +116,24 @@ flip_bytes (ptr, count) count -= 2; } } + +/* Given a character C, does it represent a general addressing mode? */ +#define Is_gen(c) \ + ((c) == 'F' || (c) == 'L' || (c) == 'B' \ + || (c) == 'W' || (c) == 'D' || (c) == 'A') + +/* Adressing modes. */ +#define Adrmod_index_byte 0x1c +#define Adrmod_index_word 0x1d +#define Adrmod_index_doubleword 0x1e +#define Adrmod_index_quadword 0x1f + +/* Is MODE an indexed addressing mode? */ +#define Adrmod_is_index(mode) \ + (mode == Adrmod_index_byte \ + || mode == Adrmod_index_word \ + || mode == Adrmod_index_doubleword \ + || mode == Adrmod_index_quadword) /* Print the 32000 instruction at address MEMADDR in debugged memory, @@ -123,8 +141,8 @@ flip_bytes (ptr, count) int print_insn (memaddr, stream) -CORE_ADDR memaddr; -FILE *stream; + CORE_ADDR memaddr; + FILE *stream; { unsigned char buffer[MAXLEN]; register int i; @@ -161,9 +179,44 @@ FILE *stream; if (*d) { + /* Offset in bits of the first thing beyond each index byte. + Element 0 is for operand A and element 1 is for operand B. + The rest are irrelevant, but we put them here so we don't + index outside the array. */ + int index_offset[MAX_ARGS]; + + /* 0 for operand A, 1 for operand B, greater for other args. */ + int whicharg = 0; + fputc ('\t', stream); maxarg = 0; + + /* First we have to find and keep track of the index bytes, + if we are using scaled indexed addressing mode, since the index + bytes occur right after the basic instruction, not as part + of the addressing extension. */ + if (Is_gen(d[1])) + { + int addr_mode = bit_extract (buffer, ioffset - 5, 5); + + if (Adrmod_is_index (addr_mode)) + { + aoffset += 8; + index_offset[0] = aoffset; + } + } + if (d[2] && Is_gen(d[3])) + { + int addr_mode = bit_extract (buffer, ioffset - 10, 5); + + if (Adrmod_is_index (addr_mode)) + { + aoffset += 8; + index_offset[1] = aoffset; + } + } + while (*d) { argnum = *d - '1'; @@ -171,8 +224,10 @@ FILE *stream; if (argnum > maxarg && argnum < MAX_ARGS) maxarg = argnum; ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer, - memaddr, arg_bufs[argnum]); + memaddr, arg_bufs[argnum], + index_offset[whicharg]); d++; + whicharg++; } for (argnum = 0; argnum <= maxarg; argnum++) { @@ -200,12 +255,23 @@ FILE *stream; return aoffset / 8; } -print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result) +/* Print an instruction operand of category given by d. IOFFSET is + the bit position below which small (<1 byte) parts of the operand can + be found (usually in the basic instruction, but for indexed + addressing it can be in the index byte). AOFFSETP is a pointer to the + bit position of the addressing extension. BUFFER contains the + instruction. ADDR is where BUFFER was read from. Put the disassembled + version of the operand in RESULT. INDEX_OFFSET is the bit position + of the index byte (it contains garbage if this operand is not a + general operand using scaled indexed addressing mode). */ + +print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset) char d; int ioffset, *aoffsetp; char *buffer; CORE_ADDR addr; char *result; + int index_offset; { int addr_mode; float Fvalue; @@ -328,16 +394,15 @@ print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result) case 0x1d: case 0x1e: case 0x1f: - index = bit_extract (buffer, *aoffsetp, 8); - *aoffsetp += 8; - print_insn_arg (d, *aoffsetp, aoffsetp, buffer, addr, - result); + index = bit_extract (buffer, index_offset - 8, 3); + print_insn_arg (d, index_offset, aoffsetp, buffer, addr, + result, 0); { static char *ind[] = {"b", "w", "d", "q"}; char *off; off = result + strlen (result); - sprintf (off, "[r%d:%s]", index & 7, + sprintf (off, "[r%d:%s]", index, ind[addr_mode & 3]); } break; diff --git a/gdb/obstack.c b/gdb/obstack.c index 4379911fb0..6f4b282d1e 100644 --- a/gdb/obstack.c +++ b/gdb/obstack.c @@ -1,101 +1,19 @@ /* obstack.c - subroutines used implicitly by object stack macros Copyright (C) 1988 Free Software Foundation, Inc. - NO WARRANTY - - BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY -NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT -WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, -RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS 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. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. -STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY -WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE -LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR -OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR -DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR -A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS -PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. - - GENERAL PUBLIC LICENSE TO COPY - - 1. You may copy and distribute verbatim copies of this source file -as you receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy a valid copyright notice "Copyright - (C) 1988 Free Software Foundation, Inc."; and include following the -copyright notice a verbatim copy of the above disclaimer of warranty -and of this License. You may charge a distribution fee for the -physical act of transferring a copy. - - 2. You may modify your copy or copies of this source file 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 or is a derivative of this - program or any part thereof, to be licensed at no charge to all - third parties on terms identical to those contained in this - License Agreement (except that you may choose to grant more extensive - warranty protection to some or all third parties, at your option). - - c) You may charge a distribution 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 unrelated program with this program (or its -derivative) on a volume of a storage or distribution medium does not bring -the other program under the scope of these terms. - - 3. You may copy and distribute this program or any portion of it in -compiled, executable or object code form under the terms of Paragraphs -1 and 2 above provided that you do 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 - shipping charge) 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.) - -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. - - 4. You may not copy, sublicense, distribute or transfer this program -except as expressly provided under this License Agreement. Any attempt -otherwise to copy, sublicense, distribute or transfer this program is void and -your rights to use the program under this License agreement shall be -automatically terminated. However, parties who have received computer -software programs from you with this License Agreement will not have -their licenses terminated so long as such parties remain in full compliance. - - 5. If you wish to incorporate parts of this program into other free -programs whose distribution conditions are different, write to the Free -Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet -worked out a simple rule that can be stated here, but we will often permit -this. We will be guided by the two goals of preserving the free status of -all derivatives our free software and of promoting the sharing and reuse of -software. +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. @@ -239,13 +157,12 @@ _obstack_allocated_p (h, obj) void #ifdef __STDC__ #undef obstack_free -obstack_free (h, obj) - +obstack_free (struct obstack *h, POINTER obj) #else _obstack_free (h, obj) -#endif 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 */ @@ -267,6 +184,18 @@ _obstack_free (h, obj) /* 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 diff --git a/gdb/obstack.h b/gdb/obstack.h index 7ebb19c810..27c017e2f2 100644 --- a/gdb/obstack.h +++ b/gdb/obstack.h @@ -1,101 +1,19 @@ /* obstack.h - object stack macros Copyright (C) 1988 Free Software Foundation, Inc. - NO WARRANTY - - BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY -NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT -WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, -RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS 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. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. -STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY -WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE -LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR -OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR -DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR -A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS -PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. - - GENERAL PUBLIC LICENSE TO COPY - - 1. You may copy and distribute verbatim copies of this source file -as you receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy a valid copyright notice "Copyright - (C) 1988 Free Software Foundation, Inc."; and include following the -copyright notice a verbatim copy of the above disclaimer of warranty -and of this License. You may charge a distribution fee for the -physical act of transferring a copy. - - 2. You may modify your copy or copies of this source file 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 or is a derivative of this - program or any part thereof, to be licensed at no charge to all - third parties on terms identical to those contained in this - License Agreement (except that you may choose to grant more extensive - warranty protection to some or all third parties, at your option). - - c) You may charge a distribution 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 unrelated program with this program (or its -derivative) on a volume of a storage or distribution medium does not bring -the other program under the scope of these terms. - - 3. You may copy and distribute this program or any portion of it in -compiled, executable or object code form under the terms of Paragraphs -1 and 2 above provided that you do 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 - shipping charge) 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.) - -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. - - 4. You may not copy, sublicense, distribute or transfer this program -except as expressly provided under this License Agreement. Any attempt -otherwise to copy, sublicense, distribute or transfer this program is void and -your rights to use the program under this License agreement shall be -automatically terminated. However, parties who have received computer -software programs from you with this License Agreement will not have -their licenses terminated so long as such parties remain in full compliance. - - 5. If you wish to incorporate parts of this program into other free -programs whose distribution conditions are different, write to the Free -Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet -worked out a simple rule that can be stated here, but we will often permit -this. We will be guided by the two goals of preserving the free status of -all derivatives our free software and of promoting the sharing and reuse of -software. +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. diff --git a/gdb/opcode.h b/gdb/opcode.h deleted file mode 120000 index 0ec9873cad..0000000000 --- a/gdb/opcode.h +++ /dev/null @@ -1 +0,0 @@ -sparc-opcode.h \ No newline at end of file diff --git a/gdb/param.h b/gdb/param.h deleted file mode 120000 index 4b050ebf9e..0000000000 --- a/gdb/param.h +++ /dev/null @@ -1 +0,0 @@ -m-sparc.h \ No newline at end of file diff --git a/gdb/pinsn.c b/gdb/pinsn.c deleted file mode 120000 index b7ac88a1bb..0000000000 --- a/gdb/pinsn.c +++ /dev/null @@ -1 +0,0 @@ -sparc-pinsn.c \ No newline at end of file diff --git a/gdb/pn-opcode.h b/gdb/pn-opcode.h index cdd6280cdb..fb3ded84fe 100644 --- a/gdb/pn-opcode.h +++ b/gdb/pn-opcode.h @@ -1,22 +1,21 @@ /* Print PN instructions for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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. */ struct gld_opcode { diff --git a/gdb/printcmd.c b/gdb/printcmd.c index 67b93a8cb1..6a6cd3424b 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -1,22 +1,21 @@ /* Print values for GNU debugger GDB. - Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1988, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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 #include "defs.h" @@ -70,6 +69,9 @@ void print_scalar_formatted (); /* Decode a format specification. *STRING_PTR should point to it. OFORMAT and OSIZE are used as defaults for the format and size if none are given in the format specification. + If OSIZE is zero, then the size field of the returned value + should be set only if a size is explicitly specified by the + user. The structure returned describes all the data found in the specification. In addition, *STRING_PTR is advanced past the specification and past all whitespace following it. */ @@ -83,8 +85,8 @@ decode_format (string_ptr, oformat, osize) struct format_data val; register char *p = *string_ptr; - val.format = oformat; - val.size = osize; + val.format = '?'; + val.size = '?'; val.count = 1; if (*p >= '0' && *p <= '9') @@ -120,6 +122,46 @@ decode_format (string_ptr, oformat, osize) while (*p == ' ' || *p == '\t') p++; *string_ptr = p; + /* Set defaults for format and size if not specified. */ + if (val.format == '?') + { + if (val.size == '?') + { + /* Neither has been specified. */ + val.format = oformat; + val.size = osize; + } + else + /* If a size is specified, any format makes a reasonable + default except 'i'. */ + val.format = oformat == 'i' ? 'x' : oformat; + } + else if (val.size == '?') + switch (val.format) + { + case 'a': + case 's': + /* Addresses must be words. */ + val.size = osize ? 'w' : osize; + break; + case 'f': + /* Floating point has to be word or giantword. */ + if (osize == 'w' || osize == 'g') + val.size = osize; + else + /* Default it to giantword if the last used size is not + appropriate. */ + val.size = osize ? 'g' : osize; + break; + case 'c': + /* Characters default to one byte. */ + val.size = osize ? 'b' : osize; + break; + default: + /* The default is the size most recently specified. */ + val.size = osize; + } + return val; } @@ -144,7 +186,7 @@ print_formatted (val, format, size) { case 's': next_address = VALUE_ADDRESS (val) - + value_print (value_addr (val), stdout, 0); + + value_print (value_addr (val), stdout, 0, Val_pretty_default); break; case 'i': @@ -158,7 +200,7 @@ print_formatted (val, format, size) || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_STRUCT || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_UNION || VALUE_REPEATED (val)) - value_print (val, stdout, format); + value_print (val, stdout, format, Val_pretty_default); else print_scalar_formatted (VALUE_CONTENTS (val), VALUE_TYPE (val), format, size, stdout); @@ -200,11 +242,11 @@ print_scalar_formatted (valaddr, type, format, size, stream) v1 = v2; v2 = tmp; #endif - + switch (format) { case 'x': - fprintf (stream, "0x%08x%08x", v1, v2); + fprintf_filtered (stream, "0x%08x%08x", v1, v2); break; default: error ("Output size \"g\" unimplemented for format \"%c\".", @@ -235,17 +277,17 @@ print_scalar_formatted (valaddr, type, format, size, stream) switch (size) { case 'b': - fprintf (stream, "0x%02llx", val_long); + fprintf_filtered (stream, "0x%02llx", val_long); break; case 'h': - fprintf (stream, "0x%04llx", val_long); + fprintf_filtered (stream, "0x%04llx", val_long); break; case 0: /* no size specified, like in print */ case 'w': - fprintf (stream, "0x%08llx", val_long); + fprintf_filtered (stream, "0x%08llx", val_long); break; case 'g': - fprintf (stream, "0x%16llx", val_long); + fprintf_filtered (stream, "0x%016llx", val_long); break; default: error ("Undefined output size \"%c\".", size); @@ -254,17 +296,17 @@ print_scalar_formatted (valaddr, type, format, size, stream) switch (size) { case 'b': - fprintf (stream, "0x%02x", val_long); + fprintf_filtered (stream, "0x%02x", val_long); break; case 'h': - fprintf (stream, "0x%04x", val_long); + fprintf_filtered (stream, "0x%04x", val_long); break; case 0: /* no size specified, like in print */ case 'w': - fprintf (stream, "0x%08x", val_long); + fprintf_filtered (stream, "0x%08x", val_long); break; case 'g': - fprintf (stream, "0x%16x", val_long); + fprintf_filtered (stream, "0x%o16x", val_long); break; default: error ("Undefined output size \"%c\".", size); @@ -274,29 +316,29 @@ print_scalar_formatted (valaddr, type, format, size, stream) case 'd': #ifdef LONG_LONG - fprintf (stream, "%lld", val_long); + fprintf_filtered (stream, "%lld", val_long); #else - fprintf (stream, "%d", val_long); + fprintf_filtered (stream, "%d", val_long); #endif break; case 'u': #ifdef LONG_LONG - fprintf (stream, "%llu", val_long); + fprintf_filtered (stream, "%llu", val_long); #else - fprintf (stream, "%u", val_long); + fprintf_filtered (stream, "%u", val_long); #endif break; case 'o': if (val_long) #ifdef LONG_LONG - fprintf (stream, "0%llo", val_long); + fprintf_filtered (stream, "0%llo", val_long); #else - fprintf (stream, "0%o", val_long); + fprintf_filtered (stream, "0%o", val_long); #endif else - fprintf (stream, "0"); + fprintf_filtered (stream, "0"); break; case 'a': @@ -304,7 +346,8 @@ print_scalar_formatted (valaddr, type, format, size, stream) break; case 'c': - value_print (value_from_long (builtin_type_char, val_long), stream, 0); + value_print (value_from_long (builtin_type_char, val_long), stream, 0, + Val_pretty_default); break; case 'f': @@ -312,24 +355,22 @@ print_scalar_formatted (valaddr, type, format, size, stream) type = builtin_type_float; else if (len == sizeof (double)) type = builtin_type_double; - else abort(); - #ifdef IEEE_FLOAT - if (is_nan (valaddr, len)) + if (is_nan (type, valaddr)) { - fprintf (stream, "NaN"); + fprintf_filtered (stream, "Nan"); break; } #endif { double doub; int inv; - + doub = unpack_double (type, valaddr, &inv); if (inv) - fprintf (stream, "Invalid float value"); - else - fprintf (stream, len > 4? "%.16g": "%.6g", doub); + fprintf_filtered (stream, "Invalid float value"); + else + fprintf_filtered (stream, len > 4 ? "%.16g" : "%.6g", doub); } break; @@ -364,37 +405,24 @@ print_address (addr, stream) CORE_ADDR addr; FILE *stream; { - register int i; - struct symbol *fs; + register int i = 0; + register char *format; + register struct symbol *fs; char *name; int name_location; - fprintf (stream, "0x%x", addr); - - fs = find_pc_function (addr); - - if (!fs) - { - i = find_pc_misc_function (addr); - - if (i < 0) return; /* If nothing comes through, don't - print anything symbolic */ + i = find_pc_partial_function (addr, &name, &name_location); - name = misc_function_vector[i].name; - name_location = misc_function_vector[i].address; - } + /* If nothing comes out, don't print anything symbolic. */ + + if (i == 0) + format = "0x%x"; + else if (addr - name_location) + format = "0x%x <%s+%d>"; else - { - name = fs->name; - name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (fs)); - } + format = "0x%x <%s>"; - if (addr - name_location) - fprintf (stream, " <%s+%d>", - name, - addr - name_location); - else - fprintf (stream, " <%s>", name); + fprintf_filtered (stream, format, addr, name, addr - name_location); } /* Examine data at address ADDR in format FMT. @@ -449,19 +477,19 @@ do_examine (fmt, addr) while (count > 0) { print_address (next_address, stdout); - fputc (':', stdout); + printf_filtered (":"); for (i = maxelts; i > 0 && count > 0; i--, count--) { - fputc ('\t', stdout); + printf_filtered ("\t"); /* Note that print_formatted sets next_address for the next object. */ last_examine_address = next_address; last_examine_value = value_at (val_type, next_address); print_formatted (last_examine_value, format, size); } - fputc ('\n', stdout); + printf_filtered ("\n"); fflush (stdout); } } @@ -512,10 +540,10 @@ print_command (exp) val = access_value_history (0); histindex = record_latest_value (val); - if (histindex >= 0) printf ("$%d = ", histindex); + if (histindex >= 0) printf_filtered ("$%d = ", histindex); print_formatted (val, format, fmt.size); - printf ("\n"); + printf_filtered ("\n"); if (cleanup) do_cleanups (old_chain); @@ -580,7 +608,7 @@ address_info (exp) if (is_a_field_of_this) { - printf("Symbol \"%s\" is a field of the local class variable `this'\n", exp); + printf ("Symbol \"%s\" is a field of the local class variable `this'\n", exp); return; } @@ -630,6 +658,10 @@ address_info (exp) printf ("a local variable at frame offset %d", val); break; + case LOC_REF_ARG: + printf ("a reference argument at offset %d", val); + break; + case LOC_TYPEDEF: printf ("a typedef"); break; @@ -650,6 +682,7 @@ x_command (exp, from_tty) struct expression *expr; struct format_data fmt; struct cleanup *old_chain; + struct value *val; fmt.format = last_format; fmt.size = last_size; @@ -674,7 +707,13 @@ x_command (exp, from_tty) if (from_tty) *exp = 0; old_chain = make_cleanup (free_current_contents, &expr); - next_address = (CORE_ADDR) value_as_long (evaluate_expression (expr)); + val = evaluate_expression (expr); + if (last_format == 'i' + && TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_PTR + && VALUE_LVAL (val) == lval_memory) + next_address = VALUE_ADDRESS (val); + else + next_address = (CORE_ADDR) value_as_long (val); do_cleanups (old_chain); } @@ -712,9 +751,12 @@ whatis_command (exp) else val = access_value_history (0); - printf ("type = "); - type_print (VALUE_TYPE (val), "", stdout, 1); - printf ("\n"); + printf_filtered ("type = "); + /* Most of the time users do not want to see all the fields + in a structure. If they do they can use the "ptype" command. + Hence the "-1" below. */ + type_print (VALUE_TYPE (val), "", stdout, -1); + printf_filtered ("\n"); if (exp) do_cleanups (old_chain); @@ -753,28 +795,28 @@ ptype_command (typename) = lookup_symbol (typename, b, STRUCT_NAMESPACE, 0); if (sym == 0) error ("No type named %s.", typename); - printf ("No type named %s, but there is a ", + printf_filtered ("No type named %s, but there is a ", typename); switch (TYPE_CODE (SYMBOL_TYPE (sym))) { case TYPE_CODE_STRUCT: - printf ("struct"); + printf_filtered ("struct"); break; case TYPE_CODE_UNION: - printf ("union"); + printf_filtered ("union"); break; case TYPE_CODE_ENUM: - printf ("enum"); + printf_filtered ("enum"); } - printf (" %s. Type \"help ptype\".\n", typename); + printf_filtered (" %s. Type \"help ptype\".\n", typename); type = SYMBOL_TYPE (sym); } } type_print (type, "", stdout, 1); - printf ("\n"); + printf_filtered ("\n"); } enum display_status {disabled, enabled}; @@ -972,21 +1014,21 @@ do_one_display (d) current_display_number = d->number; - printf ("%d: ", d->number); + printf_filtered ("%d: ", d->number); if (d->format.size) { - printf ("x/"); + printf_filtered ("x/"); if (d->format.count != 1) - printf ("%d", d->format.count); - printf ("%c", d->format.format); + printf_filtered ("%d", d->format.count); + printf_filtered ("%c", d->format.format); if (d->format.format != 'i' && d->format.format != 's') - printf ("%c", d->format.size); - printf (" "); + printf_filtered ("%c", d->format.size); + printf_filtered (" "); print_expression (d->exp, stdout); if (d->format.count != 1) - printf ("\n"); + printf_filtered ("\n"); else - printf (" "); + printf_filtered (" "); do_examine (d->format, (CORE_ADDR) value_as_long (evaluate_expression (d->exp))); @@ -994,12 +1036,12 @@ do_one_display (d) else { if (d->format.format) - printf ("/%c ", d->format.format); + printf_filtered ("/%c ", d->format.format); print_expression (d->exp, stdout); - printf (" = "); + printf_filtered (" = "); print_formatted (evaluate_expression (d->exp), d->format.format, d->format.size); - printf ("\n"); + printf_filtered ("\n"); } fflush (stdout); @@ -1022,12 +1064,27 @@ do_displays () This is done when there is an error or a signal. */ void -delete_current_display () +disable_display (num) + int num; +{ + register struct display *d; + + for (d = display_chain; d; d = d->next) + if (d->number == num) + { + d->status = disabled; + return; + } + printf ("No display number %d.\n", num); +} + +void +disable_current_display () { if (current_display_number >= 0) { - delete_display (current_display_number); - fprintf (stderr, "Deleting display %d to avoid infinite recursion.\n", + disable_display (current_display_number); + fprintf (stderr, "Disabling display %d to avoid infinite recursion.\n", current_display_number); } current_display_number = -1; @@ -1041,21 +1098,21 @@ display_info () if (!display_chain) printf ("There are no auto-display expressions now.\n"); else - printf ("Auto-display expressions now in effect:\n\ + printf_filtered ("Auto-display expressions now in effect:\n\ Num Enb Expression\n"); for (d = display_chain; d; d = d->next) { - printf ("%d: %c ", d->number, "ny"[(int)d->status]); + printf_filtered ("%d: %c ", d->number, "ny"[(int)d->status]); if (d->format.size) - printf ("/%d%c%c ", d->format.count, d->format.size, + printf_filtered ("/%d%c%c ", d->format.count, d->format.size, d->format.format); else if (d->format.format) - printf ("/%c ", d->format.format); + printf_filtered ("/%c ", d->format.format); print_expression (d->exp, stdout); if (d->block && !contained_in (get_selected_block (), d->block)) - printf (" (cannot be evaluated in the current context)"); - printf ("\n"); + printf_filtered (" (cannot be evaluated in the current context)"); + printf_filtered ("\n"); fflush (stdout); } } @@ -1071,7 +1128,7 @@ enable_display (args) if (p == 0) { - for (d = display_chain; d; d->next) + for (d = display_chain; d; d = d->next) d->status = enabled; } else @@ -1100,8 +1157,9 @@ enable_display (args) } void -disable_display (args) +disable_display_command (args, from_tty) char *args; + int from_tty; { register char *p = args; register char *p1; @@ -1110,7 +1168,7 @@ disable_display (args) if (p == 0) { - for (d = display_chain; d; d->next) + for (d = display_chain; d; d = d->next) d->status = disabled; } else @@ -1124,14 +1182,8 @@ disable_display (args) num = atoi (p); - for (d = display_chain; d; d = d->next) - if (d->number == num) - { - d->status = disabled; - goto win; - } - printf ("No display number %d.\n", num); - win: + disable_display (atoi (p)); + p = p1; while (*p == ' ' || *p == '\t') p++; @@ -1149,7 +1201,14 @@ print_variable_value (var, frame, stream) FILE *stream; { value val = read_var_value (var, frame); - value_print (val, stream, 0); + value_print (val, stream, 0, Val_pretty_default); +} + +static int +compare_ints (i, j) + int *i, *j; +{ + return *i - *j; } /* Print the arguments of a stack frame, given the function FUNC @@ -1169,10 +1228,10 @@ print_frame_args (func, fi, num, stream) int nsyms = 0; int first = 1; register int i; - register int last_offset = FRAME_ARGS_SKIP; register int last_regparm = 0; register struct symbol *lastsym, *sym, *nextsym; register value val; + CORE_ADDR highest_offset = 0; register CORE_ADDR addr = FRAME_ARGS_ADDRESS (fi); if (func) @@ -1181,72 +1240,66 @@ print_frame_args (func, fi, num, stream) nsyms = BLOCK_NSYMS (b); } - lastsym = 0; - while (1) + for (i = 0; i < nsyms; i++) { - /* Find first arg that is not before LAST_OFFSET. */ - nextsym = 0; - for (i = 0; i < nsyms; i++) - { - QUIT; - sym = BLOCK_SYM (b, i); - if (SYMBOL_CLASS (sym) == LOC_ARG) - { - if (SYMBOL_VALUE (sym) >= last_offset - && (nextsym == 0 - || SYMBOL_VALUE (sym) < SYMBOL_VALUE (nextsym))) - nextsym = sym; - } - else if (SYMBOL_CLASS (sym) == LOC_REGPARM) - { - /* This shouldn't be sorted by number. Since we can't - find nameless args with register parameters, print - this out in order by .stabs. */ - if (sym > lastsym && nextsym == 0) - nextsym = sym; - } - } - if (nextsym == 0) - break; - sym = nextsym; - /* Print any nameless args between the last arg printed - and the next arg. */ - if (SYMBOL_CLASS (sym) == LOC_ARG - && last_offset != (SYMBOL_VALUE (sym) / sizeof (int)) * sizeof (int)) - { - print_frame_nameless_args (addr, last_offset, SYMBOL_VALUE (sym), - stream); - first = 0; - } + QUIT; + sym = BLOCK_SYM (b, i); + + if (SYMBOL_CLASS (sym) != LOC_REGPARM + && SYMBOL_CLASS (sym) != LOC_ARG + && SYMBOL_CLASS (sym) != LOC_REF_ARG) + continue; + /* Print the next arg. */ if (SYMBOL_CLASS (sym) == LOC_REGPARM) val = value_from_register (SYMBOL_TYPE (sym), SYMBOL_VALUE (sym), FRAME_INFO_ID (fi)); else - val = value_at (SYMBOL_TYPE (sym), addr + SYMBOL_VALUE (sym)); + { + int current_offset = SYMBOL_VALUE (sym); + int arg_size = TYPE_LENGTH (SYMBOL_TYPE (sym)); + + if (SYMBOL_CLASS (sym) == LOC_REF_ARG) + val = value_at (SYMBOL_TYPE (sym), + read_memory_integer (addr + current_offset, + sizeof (CORE_ADDR))); + else + val = value_at (SYMBOL_TYPE (sym), addr + current_offset); + + /* Round up address of next arg to multiple of size of int. */ + current_offset + = (((current_offset + sizeof (int) - 1) / sizeof (int)) + * sizeof (int)); + + if ((current_offset + + (arg_size - sizeof (int) + 3) / (sizeof (int))) + > highest_offset) + highest_offset = current_offset; + } if (! first) - fprintf (stream, ", "); - fprintf (stream, "%s=", SYMBOL_NAME (sym)); - value_print (val, stream, 0); + fprintf_filtered (stream, ", "); + fputs_filtered (SYMBOL_NAME (sym), stream); + fputs_filtered ("=", stream); + value_print (val, stream, 0, Val_no_prettyprint); first = 0; - if (SYMBOL_CLASS (sym) == LOC_ARG) - last_offset = SYMBOL_VALUE (sym) + TYPE_LENGTH (SYMBOL_TYPE (sym)); - else - { - last_regparm = SYMBOL_VALUE (sym) + 1; - last_offset += TYPE_LENGTH (SYMBOL_TYPE (sym)); - } - - /* Round up address of next arg to multiple of size of int. */ - last_offset - = ((last_offset + sizeof (int) - 1) / sizeof (int)) * sizeof (int); - lastsym = sym; } - if (num >= 0 && num * sizeof (int) + FRAME_ARGS_SKIP > last_offset) - print_frame_nameless_args (addr, last_offset, - num * sizeof (int) + FRAME_ARGS_SKIP, stream); + + /* Don't print nameless args in situations where we don't know + enough about the stack to find them. */ + if (num != -1) + { + if (i && num * sizeof (int) + FRAME_ARGS_SKIP > highest_offset) + print_frame_nameless_args (addr, + highest_offset + sizeof (int), + num * sizeof (int) + FRAME_ARGS_SKIP, + stream); + else + print_frame_nameless_args (addr, FRAME_ARGS_SKIP, + num * sizeof (int) + FRAME_ARGS_SKIP, + stream); + } } static void @@ -1260,9 +1313,16 @@ print_frame_nameless_args (argsaddr, start, end, stream) { QUIT; if (start != FRAME_ARGS_SKIP) - fprintf (stream, ", "); - fprintf (stream, "%d", + fprintf_filtered (stream, ", "); +#ifndef PRINT_TYPELESS_INTEGER + fprintf_filtered (stream, "%d", read_memory_integer (argsaddr + start, sizeof (int))); +#else + PRINT_TYPELESS_INTEGER (stream, builtin_type_int, + (LONGEST) + read_memory_integer (argsaddr + start, + sizeof (int))); +#endif start += sizeof (int); } } @@ -1278,10 +1338,6 @@ printf_command (arg) int nargs = 0; int allocated_args = 20; char *arg_bytes; - char *argclass; - int i; - int argindex; - int nargs_wanted; val_args = (value *) xmalloc (allocated_args * sizeof (value)); @@ -1348,113 +1404,217 @@ printf_command (arg) if (*s == ',') s++; while (*s == ' ' || *s == '\t') s++; - /* Now scan the string for %-specs and see what kinds of args they want. - argclass[I] is set to 1 if the Ith arg should be a string. - It's set to 2 if the Ith arg should be floating point. */ - - argclass = (char *) alloca (strlen (s)); - nargs_wanted = 0; - f = string; - while (*f) - if (*f++ == '%') + { + /* Now scan the string for %-specs and see what kinds of args they want. + argclass[I] classifies the %-specs so we can give vprintf something + of the right size. */ + + enum argclass {int_arg, string_arg, double_arg, long_long_arg}; + enum argclass *argclass; + int nargs_wanted; + int argindex; + int lcount; + int i; + + argclass = (enum argclass *) alloca (strlen (s) * sizeof *argclass); + nargs_wanted = 0; + f = string; + while (*f) + if (*f++ == '%') + { + lcount = 0; + while (index ("0123456789.hlL-+ #", *f)) + { + if (*f == 'l' || *f == 'L') + lcount++; + f++; + } + if (*f == 's') + argclass[nargs_wanted++] = string_arg; + else if (*f == 'e' || *f == 'f' || *f == 'g') + argclass[nargs_wanted++] = double_arg; + else if (lcount > 1) + argclass[nargs_wanted++] = long_long_arg; + else if (*f != '%') + argclass[nargs_wanted++] = int_arg; + f++; + } + + /* Now, parse all arguments and evaluate them. + Store the VALUEs in VAL_ARGS. */ + + while (*s != '\0') { - while (index ("0123456789.hlL-+ #", *f)) f++; - if (*f == 's') - argclass[nargs_wanted++] = 1; - else if (*f == 'e' || *f == 'f' || *f == 'g') - argclass[nargs_wanted++] = 2; - else if (*f != '%') - argclass[nargs_wanted++] = 0; - f++; + char *s1; + if (nargs == allocated_args) + val_args = (value *) xrealloc (val_args, + (allocated_args *= 2) + * sizeof (value)); + s1 = s; + val_args[nargs] = parse_to_comma_and_eval (&s1); + + /* If format string wants a float, unchecked-convert the value to + floating point of the same size */ + + if (argclass[nargs] == double_arg) + { + if (TYPE_LENGTH (VALUE_TYPE (val_args[nargs])) == sizeof (float)) + VALUE_TYPE (val_args[nargs]) = builtin_type_float; + if (TYPE_LENGTH (VALUE_TYPE (val_args[nargs])) == sizeof (double)) + VALUE_TYPE (val_args[nargs]) = builtin_type_double; + } + nargs++; + s = s1; + if (*s == ',') + s++; + } + + if (nargs != nargs_wanted) + error ("Wrong number of arguments for specified format-string"); + + /* Now lay out an argument-list containing the arguments + as doubles, integers and C pointers. */ + + arg_bytes = (char *) alloca (sizeof (double) * nargs); + argindex = 0; + for (i = 0; i < nargs; i++) + { + if (argclass[i] == string_arg) + { + char *str; + int tem, j; + tem = value_as_long (val_args[i]); + + /* This is a %s argument. Find the length of the string. */ + for (j = 0; ; j++) + { + char c; + QUIT; + read_memory (tem + j, &c, 1); + if (c == 0) + break; + } + + /* Copy the string contents into a string inside GDB. */ + str = (char *) alloca (j + 1); + read_memory (tem, str, j); + str[j] = 0; + + /* Pass address of internal copy as the arg to vprintf. */ + *((int *) &arg_bytes[argindex]) = (int) str; + argindex += sizeof (int); + } + else if (VALUE_TYPE (val_args[i])->code == TYPE_CODE_FLT) + { + *((double *) &arg_bytes[argindex]) = value_as_double (val_args[i]); + argindex += sizeof (double); + } + else +#ifdef LONG_LONG + if (argclass[i] == long_long_arg) + { + *(long long *) &arg_bytes[argindex] = value_as_long (val_args[i]); + argindex += sizeof (long long); + } + else +#endif + { + *((int *) &arg_bytes[argindex]) = value_as_long (val_args[i]); + argindex += sizeof (int); + } } + } + vprintf (string, arg_bytes); +} + +/* Helper function for asdump_command. Finds the bounds of a function + for a specified section of text. PC is an address within the + function which you want bounds for; *LOW and *HIGH are set to the + beginning (inclusive) and end (exclusive) of the function. This + function returns 1 on success and 0 on failure. */ + +static int +containing_function_bounds (pc, low, high) + CORE_ADDR pc, *low, *high; +{ + int scan; - /* Now, parse all arguments and evaluate them. - Store the VALUEs in VAL_ARGS. */ + if (!find_pc_partial_function (pc, 0, low)) + return 0; - while (*s != '\0') - { - char *s1; - if (nargs == allocated_args) - val_args = (value *) xrealloc (val_args, - (allocated_args *= 2) - * sizeof (value)); - s1 = s; - val_args[nargs] = parse_to_comma_and_eval (&s1); - - /* If format string wants a float, unchecked-convert the value to - floating point of the same size */ - - if (argclass[nargs] == 2) - { - argclass[nargs] = 0; - if (TYPE_LENGTH (VALUE_TYPE (val_args[nargs])) == sizeof (float)) - VALUE_TYPE (val_args[nargs]) = builtin_type_float; - if (TYPE_LENGTH (VALUE_TYPE (val_args[nargs])) == sizeof (double)) - VALUE_TYPE (val_args[nargs]) = builtin_type_double; - } - nargs++; - s = s1; - if (*s == ',') - s++; - } + scan = *low; + do { + scan++; + if (!find_pc_partial_function (scan, 0, high)) + return 0; + } while (*low == *high); - if (nargs != nargs_wanted) - error ("Wrong number of arguments for specified format-string"); + return 1; +} - /* Now lay out an argument-list containing the arguments - as doubles, integers and C pointers. */ +/* Dump a specified section of assembly code. With no command line + arguments, this command will dump the assembly code for the + function surrounding the pc value in the selected frame. With one + argument, it will dump the assembly code surrounding that pc value. + Two arguments are interpeted as bounds within which to dump + assembly. */ - arg_bytes = (char *) alloca (sizeof (double) * nargs); - argindex = 0; - for (i = 0; i < nargs; i++) - { - if (argclass[i]) - { - char *str; - int tem, j; - tem = value_as_long (val_args[i]); +static void +disassemble_command (arg, from_tty) + char *arg; + int from_tty; +{ + CORE_ADDR low, high; + CORE_ADDR pc; + char *space_index; - /* This is a %s argument. Find the length of the string. */ - for (j = 0; ; j++) - { - char c; - QUIT; - read_memory (tem + j, &c, 1); - if (c == 0) - break; - } + if (!arg) + { + if (!selected_frame) + error ("No frame selected.\n"); - /* Copy the string contents into a string inside GDB. */ - str = (char *) alloca (j + 1); - read_memory (tem, str, j); - str[j] = 0; + pc = get_frame_pc (selected_frame); + if (!containing_function_bounds (pc, &low, &high)) + error ("No function contains pc specified by selected frame.\n"); + } + else if (!(space_index = (char *) index (arg, ' '))) + { + /* One argument. */ + pc = parse_and_eval_address (arg); + if (!containing_function_bounds (pc, &low, &high)) + error ("No function contains specified pc.\n"); + } + else + { + /* Two arguments. */ + *space_index = '\0'; + low = parse_and_eval_address (arg); + high = parse_and_eval_address (space_index + 1); + } - /* Pass address of internal copy as the arg to vprintf. */ - *((int *) &arg_bytes[argindex]) = (int) str; - argindex += sizeof (int); - } - else if (VALUE_TYPE (val_args[i])->code == TYPE_CODE_FLT) - { - *((double *) &arg_bytes[argindex]) = value_as_double (val_args[i]); - argindex += sizeof (double); - } - else -#ifdef LONG_LONG - if (TYPE_LENGTH (VALUE_TYPE (val_args[i])) == sizeof (long long)) - { - *(long long *) &arg_bytes[argindex] = value_as_long (val_args[i]); - argindex += sizeof (long long); - } - else -#endif - { - *((int *) &arg_bytes[argindex]) = value_as_long (val_args[i]); - argindex += sizeof (int); - } + printf_filtered ("Dump of assembler code "); + if (!space_index) + { + char *name; + find_pc_partial_function (pc, &name, 0); + printf_filtered ("for function %s:\n", name); } + else + printf_filtered ("from 0x%x to 0x%x:\n", low, high); - vprintf (string, arg_bytes); + /* Dump the specified range. */ + for (pc = low; pc < high; ) + { + QUIT; + print_address (pc, stdout); + printf_filtered (":\t"); + pc += print_insn (pc, stdout); + printf_filtered ("\n"); + } + printf_filtered ("End of assembler dump.\n"); + fflush (stdout); } + extern struct cmd_list_element *enablelist, *disablelist, *deletelist; extern struct cmd_list_element *cmdlist, *setlist; @@ -1481,6 +1641,12 @@ Defaults for format and size letters are those previously used.\n\ Default count is 1. Default address is following last thing printed\n\ with this command or \"print\"."); + add_com ("disassemble", class_vars, disassemble_command, + "Disassemble a specified section of memory.\n\ +Default is the function surrounding the pc of the selected frame.\n\ +With a single argument, the function surrounding that address is dumped.\n\ +Two arguments are taken as a range of memory to dump."); + add_com ("ptype", class_vars, ptype_command, "Print definition of type TYPE.\n\ Argument may be a type name defined by typedef, or \"struct STRUCTNAME\"\n\ @@ -1493,7 +1659,7 @@ The selected stack frame's lexical context is used to look up the name."); add_info ("display", display_info, "Expressions to display when program stops, with code numbers."); - add_abbrev_cmd ("undisplay", class_vars, undisplay_command, + add_cmd ("undisplay", class_vars, undisplay_command, "Cancel some expressions to be displayed when program stops.\n\ Arguments are the code numbers of the expressions to stop displaying.\n\ No argument means cancel all automatic-display expressions.\n\ @@ -1516,7 +1682,7 @@ Arguments are the code numbers of the expressions to resume displaying.\n\ No argument means enable all automatic-display expressions.\n\ Do \"info display\" to see current list of code numbers.", &enablelist); - add_cmd ("display", class_vars, disable_display, + add_cmd ("display", class_vars, disable_display_command, "Disable some expressions to be displayed when program stops.\n\ Arguments are the code numbers of the expressions to stop displaying.\n\ No argument means disable all automatic-display expressions.\n\ @@ -1576,4 +1742,3 @@ EXP may be preceded with /FMT, where FMT is a format letter\n\ but no count or size letter (see \"x\" command).")); add_com_alias ("p", "print", class_vars, 1); } - diff --git a/gdb/readline/ChangeLog b/gdb/readline/ChangeLog new file mode 100644 index 0000000000..6df2335531 --- /dev/null +++ b/gdb/readline/ChangeLog @@ -0,0 +1,70 @@ +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. + + diff --git a/gdb/readline/Makefile b/gdb/readline/Makefile new file mode 100644 index 0000000000..dc1153984e --- /dev/null +++ b/gdb/readline/Makefile @@ -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 diff --git a/gdb/readline/chardefs.h b/gdb/readline/chardefs.h new file mode 100644 index 0000000000..9749ae489f --- /dev/null +++ b/gdb/readline/chardefs.h @@ -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_ */ diff --git a/gdb/readline/emacs_keymap.c b/gdb/readline/emacs_keymap.c new file mode 100644 index 0000000000..7030e69f6b --- /dev/null +++ b/gdb/readline/emacs_keymap.c @@ -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 +#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 */ +}; diff --git a/gdb/readline/funmap.c b/gdb/readline/funmap.c new file mode 100644 index 0000000000..9783abf576 --- /dev/null +++ b/gdb/readline/funmap.c @@ -0,0 +1,212 @@ +/* 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 +#endif /* FILE */ + +#include "readline.h" + +FUNMAP **funmap = (FUNMAP **)NULL; +static int funmap_size = 0; +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 */ diff --git a/gdb/readline/history.c b/gdb/readline/history.c new file mode 100644 index 0000000000..7087718edc --- /dev/null +++ b/gdb/readline/history.c @@ -0,0 +1,1462 @@ +/* History.c -- standalone history library */ + +/* Copyright (C) 1989 Free Software Foundation, Inc. + + This file contains the GNU History Library (the Library), a set of + routines for managing the text of previously typed lines. + + The Library 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. + + The Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* The goal is to make the implementation transparent, so that you + don't have to know what data types are used, just what functions + you can call. I think I have done that. */ + +/* 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 + +#include + +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else +#if defined (sparc) && defined (sun) +#include +#else +extern char *alloca (); +#endif +#endif + +#include "history.h" + +#ifndef savestring +#define savestring(x) (char *)strcpy (xmalloc (1 + strlen (x)), (x)) +#endif + +#ifndef whitespace +#define whitespace(c) (((c) == ' ') || ((c) == '\t')) +#endif + +#ifndef digit +#define digit(c) ((c) >= '0' && (c) <= '9') +#endif + +#ifndef member +#define member(c, s) ((c) ? index ((s), (c)) : 0) +#endif + +/* **************************************************************** */ +/* */ +/* History functions */ +/* */ +/* **************************************************************** */ + +/* An array of HIST_ENTRY. This is where we store the history. */ +static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL; + +/* Non-zero means that we have enforced a limit on the amount of + history that we save. */ +static int history_stifled = 0; + +/* If HISTORY_STIFLED is non-zero, then this is the maximum number of + entries to remember. */ +static int max_input_history; + +/* The current location of the interactive history pointer. Just makes + life easier for outside callers. */ +static int history_offset = 0; + +/* The number of strings currently stored in the input_history list. */ +static int history_length = 0; + +/* The current number of slots allocated to the input_history. */ +static int history_size = 0; + +/* The number of slots to increase the_history by. */ +#define DEFAULT_HISTORY_GROW_SIZE 50 + +/* The character that represents the start of a history expansion + request. This is usually `!'. */ +char history_expansion_char = '!'; + +/* The character that invokes word substitution if found at the start of + a line. This is usually `^'. */ +char history_subst_char = '^'; + +/* During tokenization, if this character is seen as the first character + of a word, then it, and all subsequent characters upto a newline are + ignored. For a Bourne shell, this should be '#'. Bash special cases + the interactive comment character to not be a comment delimiter. */ +char history_comment_char = '\0'; + +/* The list of characters which inhibit the expansion of text if found + immediately following history_expansion_char. */ +char *history_no_expand_chars = " \t\n\r="; + +/* The logical `base' of the history array. It defaults to 1. */ +int history_base = 1; + +/* Begin a session in which the history functions might be used. This + initializes interactive variables. */ +void +using_history () +{ + history_offset = history_length; +} + +/* Place STRING at the end of the history list. The data field + is set to NULL. */ +void +add_history (string) + char *string; +{ + HIST_ENTRY *temp; + + if (history_stifled && (history_length == max_input_history)) { + register int i; + + /* If the history is stifled, and history_length is zero, + and it equals max_input_history, we don't save items. */ + if (!history_length) + return; + + /* If there is something in the slot, then remove it. */ + if (the_history[0]) { + free (the_history[0]->line); + free (the_history[0]); + } + + for (i = 0; i < history_length; i++) + the_history[i] = the_history[i + 1]; + + history_base++; + + } else { + + if (!history_size) { + the_history = + (HIST_ENTRY **)xmalloc ((history_size = DEFAULT_HISTORY_GROW_SIZE) + * sizeof (HIST_ENTRY *)); + history_length = 1; + + } else { + if (history_length == (history_size - 1)) { + the_history = + (HIST_ENTRY **)xrealloc (the_history, + ((history_size += DEFAULT_HISTORY_GROW_SIZE) + * sizeof (HIST_ENTRY *))); + } + history_length++; + } + } + + temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); + temp->line = savestring (string); + temp->data = (char *)NULL; + + the_history[history_length] = (HIST_ENTRY *)NULL; + the_history[history_length - 1] = temp; +} + +/* 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. */ +HIST_ENTRY * +replace_history_entry (which, line, data) + int which; + char *line; + char *data; +{ + HIST_ENTRY *temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); + HIST_ENTRY *old_value; + + if (which >= history_length) + return ((HIST_ENTRY *)NULL); + + old_value = the_history[which]; + + temp->line = savestring (line); + temp->data = data; + the_history[which] = temp; + + return (old_value); +} + +/* Returns the magic number which says what history element we are + looking at now. In this implementation, it returns history_offset. */ +int +where_history () +{ + return (history_offset); +} + +/* 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. */ +int +history_search (string, direction) + char *string; + int direction; +{ + register int i = history_offset; + register int reverse = (direction < 0); + register char *line; + register int index; + int string_len = strlen (string); + + /* Take care of trivial cases first. */ + + if (!history_length || (i == history_length) && !reverse) + return (-1); + + if (reverse && (i == history_length)) + i--; + + while (1) + { + /* Search each line in the history list for STRING. */ + + /* At limit for direction? */ + if ((reverse && i < 0) || + (!reverse && i == history_length)) + return (-1); + + line = the_history[i]->line; + index = strlen (line); + + /* If STRING is longer than line, no match. */ + if (string_len > index) + goto next_line; + + /* Do the actual search. */ + if (reverse) + { + index -= string_len; + + while (index >= 0) + { + if (strncmp (string, line + index, string_len) == 0) + { + history_offset = i; + return (index); + } + index--; + } + } + else + { + register int limit = (string_len - index) + 1; + index = 0; + + while (index < limit) + { + if (strncmp (string, line + index, string_len) == 0) + { + history_offset = i; + return (index); + } + index++; + } + } + next_line: + if (reverse) + i--; + else + i++; + } +} + +/* Remove history element WHICH from the history. The removed + element is returned to you so you can free the line, data, + and containing structure. */ +HIST_ENTRY * +remove_history (which) + int which; +{ + HIST_ENTRY *return_value; + + if (which >= history_length || !history_length) + return_value = (HIST_ENTRY *)NULL; + else + { + register int i; + return_value = the_history[which]; + + for (i = which; i < history_length; i++) + the_history[i] = the_history[i + 1]; + + history_length--; + } + return (return_value); +} + +/* Stifle the history list, remembering only MAX number of lines. */ +void +stifle_history (max) + int max; +{ + if (history_length > max) + { + register int i, j; + + /* This loses because we cannot free the data. */ + for (i = 0; i < (history_length - max); i++) + { + free (the_history[i]->line); + free (the_history[i]); + } + history_base = i; + for (j = 0, i = history_length - max; j < max; i++, j++) + the_history[j] = the_history[i]; + the_history[j] = (HIST_ENTRY *)NULL; + history_length = j; + } + history_stifled = 1; + max_input_history = max; +} + +/* 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. */ +int +unstifle_history () +{ + int result = max_input_history; + if (history_stifled) + { + result = - result; + history_stifled = 0; + } + return (result); +} + +/* Return the string that should be used in the place of this + filename. This only matters when you don't specify the + filename to read_history (), or write_history (). */ +static char * +history_filename (filename) + char *filename; +{ + char *return_val = filename ? savestring (filename) : (char *)NULL; + + if (!return_val) + { + char *home = (char *)getenv ("HOME"); + if (!home) home = "."; + return_val = (char *)xmalloc (2 + strlen (home) + strlen (".history")); + strcpy (return_val, home); + strcat (return_val, "/"); + strcat (return_val, ".history"); + } + return (return_val); +} + +/* What to use until the line gets too big. */ +#define TYPICAL_LINE_SIZE 2048 + +/* 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. */ +int +read_history (filename) + char *filename; +{ + char *input = history_filename (filename); + FILE *file = fopen (input, "r"); + char *line = (char *)xmalloc (TYPICAL_LINE_SIZE); + int line_size = TYPICAL_LINE_SIZE; + int done = 0; + + if (!file) + { + extern int errno; + free (line); + return (errno); + } + + while (!done) + { + int c; + int i; + + i = 0; + while (!(done = ((c = getc (file)) == EOF))) + { + if (c == '\n') + break; + + line [i++] = c; + if (i == line_size) + line = (char *)xrealloc (line, line_size += TYPICAL_LINE_SIZE); + } + line[i] = '\0'; + if (line[0]) + add_history (line); + } + free (line); + fclose (file); + return (0); +} + +/* Overwrite FILENAME with the current history. If FILENAME is NULL, + then write the history list to ~/.history. Values returned + are as in read_history ().*/ +int +write_history (filename) + char *filename; +{ + extern int errno; + char *output = history_filename (filename); + FILE *file = fopen (output, "w"); + register int i; + + if (!file) return (errno); + if (!history_length) return (0); + + for (i = 0; i < history_length; i++) + fprintf (file, "%s\n", the_history[i]->line); + + fclose (file); + return (0); +} + +/* 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 () +{ + if ((history_offset == history_length) || !the_history) + return ((HIST_ENTRY *)NULL); + else + return (the_history[history_offset]); +} + +/* Back up history_offset to the previous history entry, and return + a pointer to that entry. If there is no previous entry then return + a NULL pointer. */ +HIST_ENTRY * +previous_history () +{ + if (!history_offset) + return ((HIST_ENTRY *)NULL); + else + return (the_history[--history_offset]); +} + +/* Move history_offset forward to the next history entry, and return + a pointer to that entry. If there is no next entry then return a + NULL pointer. */ +HIST_ENTRY * +next_history () +{ + if (history_offset == history_length) + return ((HIST_ENTRY *)NULL); + else + return (the_history[++history_offset]); +} + +/* Return the current history array. The caller has to be carefull, since this + is the actual array of data, and could be bashed or made corrupt easily. + The array is terminated with a NULL pointer. */ +HIST_ENTRY ** +history_list () +{ + return (the_history); +} + +/* Return the history entry which is logically at OFFSET in the history array. + OFFSET is relative to history_base. */ +HIST_ENTRY * +history_get (offset) + int offset; +{ + int index = offset - history_base; + + if (index >= history_length || + index < 0 || + !the_history) + return ((HIST_ENTRY *)NULL); + return (the_history[index]); +} + +/* Search for STRING in the history list. DIR is < 0 for searching + backwards. POS is an absolute index into the history list at + which point to begin searching. */ +int +history_search_pos (string, dir, pos) + char *string; + int dir, pos; +{ + int ret, old = where_history (); + history_set_pos (pos); + if (history_search (string, dir) == -1) + { + history_set_pos (old); + return (-1); + } + ret = where_history (); + history_set_pos (old); + return ret; +} + +/* Make the current history item be the one at POS, an absolute index. + Returns zero if POS is out of range, else non-zero. */ +int +history_set_pos (pos) + int pos; +{ + if (pos > history_length || pos < 0 || !the_history) + return (0); + history_offset = pos; + return (1); +} + + +/* **************************************************************** */ +/* */ +/* History Expansion */ +/* */ +/* **************************************************************** */ + +/* Hairy history expansion on text, not tokens. This is of general + use, and thus belongs in this library. */ + +/* The last string searched for in a !?string? search. */ +static char *search_string = (char *)NULL; + +/* Return the event specified at TEXT + OFFSET modifying OFFSET to + point to after the event specifier. Just a pointer to the history + line is returned; NULL is returned in the event of a bad specifier. + You pass STRING with *INDEX equal to the history_expansion_char that + begins this specification. + DELIMITING_QUOTE is a character that is allowed to end the string + specification for what to search for in addition to the normal + characters `:', ` ', `\t', `\n', and sometimes `?'. + So you might call this function like: + line = get_history_event ("!echo:p", &index, 0); */ +char * +get_history_event (string, caller_index, delimiting_quote) + char *string; + int *caller_index; + int delimiting_quote; +{ + register int i = *caller_index; + int which, sign = 1; + HIST_ENTRY *entry; + + /* The event can be specified in a number of ways. + + !! the previous command + !n command line N + !-n current command-line minus N + !str the most recent command starting with STR + !?str[?] + the most recent command containing STR + + All values N are determined via HISTORY_BASE. */ + + if (string[i] != history_expansion_char) + return ((char *)NULL); + + /* Move on to the specification. */ + i++; + + /* Handle !! case. */ + if (string[i] == history_expansion_char) + { + i++; + which = history_base + (history_length - 1); + *caller_index = i; + goto get_which; + } + + /* Hack case of numeric line specification. */ + read_which: + if (string[i] == '-') + { + sign = -1; + i++; + } + + if (digit (string[i])) + { + int start = i; + + /* Get the extent of the digits. */ + for (; digit (string[i]); i++); + + /* Get the digit value. */ + sscanf (string + start, "%d", &which); + + *caller_index = i; + + if (sign < 0) + which = (history_length + history_base) - which; + + get_which: + if (entry = history_get (which)) + return (entry->line); + + return ((char *)NULL); + } + + /* This must be something to search for. If the spec begins with + a '?', then the string may be anywhere on the line. Otherwise, + the string must be found at the start of a line. */ + { + int index; + char *temp; + int substring_okay = 0; + + if (string[i] == '?') + { + substring_okay++; + i++; + } + + for (index = i; string[i]; i++) + if (whitespace (string[i]) || + string[i] == '\n' || + string[i] == ':' || + (substring_okay && string[i] == '?') || + string[i] == delimiting_quote) + break; + + temp = (char *)alloca (1 + (i - index)); + strncpy (temp, &string[index], (i - index)); + temp[i - index] = '\0'; + + if (string[i] == '?') + i++; + + *caller_index = i; + + search_again: + + index = history_search (temp, -1); + + if (index < 0) + search_lost: + { + history_offset = history_length; + return ((char *)NULL); + } + + if (index == 0 || substring_okay || + (strncmp (temp, the_history[history_offset]->line, + strlen (temp)) == 0)) + { + search_won: + entry = current_history (); + history_offset = history_length; + + /* If this was a substring search, then remember the string that + we matched for word substitution. */ + if (substring_okay) + { + if (search_string) + free (search_string); + search_string = savestring (temp); + } + + return (entry->line); + } + + if (history_offset) + history_offset--; + else + goto search_lost; + + goto search_again; + } +} + +/* 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. */ +int +history_expand (string, output) + char *string; + char **output; +{ + register int j, l = strlen (string); + int i, word_spec_error = 0; + int cc, modified = 0; + char *word_spec, *event; + int starting_index, only_printing = 0, substitute_globally = 0; + + char *get_history_word_specifier (), *rindex (); + + /* The output string, and its length. */ + int len = 0; + char *result = (char *)NULL; + + /* Used in add_string; */ + char *temp, tt[2], tbl[3]; + + /* Prepare the buffer for printing error messages. */ + result = (char *)xmalloc (len = 255); + + result[0] = tt[1] = tbl[2] = '\0'; + tbl[0] = '\\'; + tbl[1] = history_expansion_char; + + /* Grovel the string. Only backslash can quote the history escape + character. We also handle arg specifiers. */ + + /* Before we grovel forever, see if the history_expansion_char appears + anywhere within the text. */ + + /* The quick substitution character is a history expansion all right. That + is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact, + that is the substitution that we do. */ + if (string[0] == history_subst_char) + { + char *format_string = (char *)alloca (10 + strlen (string)); + + sprintf (format_string, "%c%c:s%s", + history_expansion_char, history_expansion_char, + string); + string = format_string; + l += 4; + goto grovel; + } + + /* If not quick substitution, still maybe have to do expansion. */ + + /* `!' followed by one of the characters in history_no_expand_chars + is NOT an expansion. */ + for (i = 0; string[i]; i++) + if (string[i] == history_expansion_char) + if (!string[i + 1] || member (string[i + 1], history_no_expand_chars)) + continue; + else + goto grovel; + + free (result); + *output = savestring (string); + return (0); + + grovel: + + for (i = j = 0; i < l; i++) + { + int tchar = string[i]; + if (tchar == history_expansion_char) + tchar = -3; + + switch (tchar) + { + case '\\': + if (string[i + 1] == history_expansion_char) + { + i++; + temp = tbl; + goto do_add; + } + else + goto add_char; + + /* case history_expansion_char: */ + case -3: + starting_index = i + 1; + cc = string[i + 1]; + + /* If the history_expansion_char is followed by one of the + characters in history_no_expand_chars, then it is not a + candidate for expansion of any kind. */ + if (member (cc, history_no_expand_chars)) + goto add_char; + + /* There is something that is listed as a `word specifier' in csh + documentation which means `the expanded text to this point'. + That is not a word specifier, it is an event specifier. */ + + if (cc == '#') + goto hack_pound_sign; + + /* If it is followed by something that starts a word specifier, + then !! is implied as the event specifier. */ + + if (member (cc, ":$*%^")) + { + char fake_s[2]; + int fake_i = 0; + i++; + fake_s[0] = fake_s[1] = history_expansion_char; + fake_s[2] = '\0'; + event = get_history_event (fake_s, &fake_i); + } + else + { + int quoted_search_delimiter = 0; + + /* If the character before this `!' is a double or single + quote, then this expansion takes place inside of the + quoted string. If we have to search for some text ("!foo"), + allow the delimiter to end the search string. */ + if (i && (string[i - 1] == '\'' || string[i - 1] == '"')) + quoted_search_delimiter = string[i - 1]; + + event = get_history_event (string, &i, quoted_search_delimiter); + } + + if (!event) + event_not_found: + { + int l = 1 + (i - starting_index); + + temp = (char *)alloca (1 + l); + strncpy (temp, string + starting_index, l); + temp[l - 1] = 0; + sprintf (result, "%s: %s.", temp, + word_spec_error ? "Bad word specifier" : "Event not found"); + error_exit: + *output = result; + return (-1); + } + + /* If a word specifier is found, then do what that requires. */ + starting_index = i; + + word_spec = get_history_word_specifier (string, event, &i); + + /* There is no such thing as a `malformed word specifier'. However, + it is possible for a specifier that has no match. In that case, + we complain. */ + if (word_spec == (char *)-1) + bad_word_spec: + { + word_spec_error++; + goto event_not_found; + } + + /* If no word specifier, than the thing of interest was the event. */ + if (!word_spec) + temp = event; + else + { + temp = (char *)alloca (1 + strlen (word_spec)); + strcpy (temp, word_spec); + free (word_spec); + } + + /* Perhaps there are other modifiers involved. Do what they say. */ + + hack_specials: + + if (string[i] == ':') + { + char *tstr; + + switch (string[i + 1]) + { + /* :p means make this the last executed line. So we + return an error state after adding this line to the + history. */ + case 'p': + only_printing++; + goto next_special; + + /* :t discards all but the last part of the pathname. */ + case 't': + tstr = rindex (temp, '/'); + if (tstr) + temp = ++tstr; + goto next_special; + + /* :h discards the last part of a pathname. */ + case 'h': + tstr = rindex (temp, '/'); + if (tstr) + *tstr = '\0'; + goto next_special; + + /* :r discards the suffix. */ + case 'r': + tstr = rindex (temp, '.'); + if (tstr) + *tstr = '\0'; + goto next_special; + + /* :e discards everything but the suffix. */ + case 'e': + tstr = rindex (temp, '.'); + if (tstr) + temp = tstr; + goto next_special; + + /* :s/this/that substitutes `this' for `that'. */ + /* :gs/this/that substitutes `this' for `that' globally. */ + case 'g': + if (string[i + 2] == 's') + { + i++; + substitute_globally = 1; + goto substitute; + } + else + + case 's': + substitute: + { + char *this, *that, *new_event; + int delimiter = 0; + int si, l_this, l_that, l_temp = strlen (temp); + + if (i + 2 < strlen (string)) + delimiter = string[i + 2]; + + if (!delimiter) + break; + + i += 3; + + /* Get THIS. */ + for (si = i; string[si] && string[si] != delimiter; si++); + l_this = (si - i); + this = (char *)alloca (1 + l_this); + strncpy (this, string + i, l_this); + this[l_this] = '\0'; + + i = si; + if (string[si]) + i++; + + /* Get THAT. */ + for (si = i; string[si] && string[si] != delimiter; si++); + l_that = (si - i); + that = (char *)alloca (1 + l_that); + strncpy (that, string + i, l_that); + that[l_that] = '\0'; + + i = si; + if (string[si]) i++; + + /* Ignore impossible cases. */ + if (l_this > l_temp) + goto cant_substitute; + + /* Find the first occurrence of THIS in TEMP. */ + si = 0; + for (; (si + l_this) <= l_temp; si++) + if (strncmp (temp + si, this, l_this) == 0) + { + new_event = + (char *)alloca (1 + (l_that - l_this) + l_temp); + strncpy (new_event, temp, si); + strncpy (new_event + si, that, l_that); + strncpy (new_event + si + l_that, + temp + si + l_this, + l_temp - (si + l_this)); + new_event[(l_that - l_this) + l_temp] = '\0'; + temp = new_event; + + if (substitute_globally) + { + si += l_that; + l_temp = strlen (temp); + substitute_globally++; + continue; + } + + goto hack_specials; + } + + cant_substitute: + + if (substitute_globally > 1) + { + substitute_globally = 0; + goto hack_specials; + } + + goto event_not_found; + } + + /* :# is the line so far. Note that we have to + alloca () it since RESULT could be realloc ()'ed + below in add_string. */ + case '#': + hack_pound_sign: + if (result) + { + temp = (char *)alloca (1 + strlen (result)); + strcpy (temp, result); + } + else + temp = ""; + + next_special: + i += 2; + goto hack_specials; + } + + } + /* Believe it or not, we have to back the pointer up by one. */ + --i; + goto add_string; + + /* A regular character. Just add it to the output string. */ + default: + add_char: + tt[0] = string[i]; + temp = tt; + goto do_add; + + add_string: + modified++; + + do_add: + j += strlen (temp); + while (j > len) + result = (char *)xrealloc (result, (len += 255)); + + strcpy (result + (j - strlen (temp)), temp); + } + } + + *output = result; + + if (only_printing) + { + add_history (result); + return (-1); + } + + return (modified != 0); +} + +/* Return a consed string which is the word specified in SPEC, and found + in FROM. NULL is returned if there is no spec. -1 is returned if + the word specified cannot be found. CALLER_INDEX is the offset in + SPEC to start looking; it is updated to point to just after the last + character parsed. */ +char * +get_history_word_specifier (spec, from, caller_index) + char *spec, *from; + int *caller_index; +{ + register int i = *caller_index; + int first, last; + int expecting_word_spec = 0; + char *history_arg_extract (); + + /* The range of words to return doesn't exist yet. */ + first = last = 0; + + /* If we found a colon, then this *must* be a word specification. If + it isn't, then it is an error. */ + if (spec[i] == ':') + i++, expecting_word_spec++; + + /* Handle special cases first. */ + + /* `%' is the word last searched for. */ + if (spec[i] == '%') + { + *caller_index = i + 1; + if (search_string) + return (savestring (search_string)); + else + return (savestring ("")); + } + + /* `*' matches all of the arguments, but not the command. */ + if (spec[i] == '*') + { + *caller_index = i + 1; + return (history_arg_extract (1, '$', from)); + } + + /* `$' is last arg. */ + if (spec[i] == '$') + { + *caller_index = i + 1; + return (history_arg_extract ('$', '$', from)); + } + + /* Try to get FIRST and LAST figured out. */ + if (spec[i] == '-' || spec[i] == '^') + { + first = 1; + goto get_last; + } + + get_first: + if (digit (spec[i]) && expecting_word_spec) + { + sscanf (spec + i, "%d", &first); + for (; digit (spec[i]); i++); + } + else + return ((char *)NULL); + + get_last: + if (spec[i] == '^') + { + i++; + last = 1; + goto get_args; + } + + if (spec[i] != '-') + { + last = first; + goto get_args; + } + + i++; + + if (digit (spec[i])) + { + sscanf (spec + i, "%d", &last); + for (; digit (spec[i]); i++); + } + else + if (spec[i] == '$') + { + i++; + last = '$'; + } + + get_args: + { + char *result = (char *)NULL; + + *caller_index = i; + + if (last >= first) + result = history_arg_extract (first, last, from); + + if (result) + return (result); + else + return ((char *)-1); + } +} + +/* Extract the args specified, starting at FIRST, and ending at LAST. + The args are taken from STRING. */ +char * +history_arg_extract (first, last, string) + int first, last; + char *string; +{ + register int i, len; + char *result = (char *)NULL; + int size = 0, offset = 0; + + char **history_tokenize (), **list; + + if (!(list = history_tokenize (string))) + return ((char *)NULL); + + for (len = 0; list[len]; len++); + + if (last == '$') + last = len - 1; + + if (first == '$') + first = len - 1; + + last++; + + if (first > len || last > len) + result = ((char *)NULL); + else { + for (i = first; i < last; i++) + { + int l = strlen (list[i]); + + if (!result) + result = (char *)xmalloc ((size = (2 + l))); + else + result = (char *)xrealloc (result, (size += (2 + l))); + strcpy (result + offset, list[i]); + offset += l; + if (i + 1 < last) + { + strcpy (result + offset, " "); + offset++; + } + } + } + + for (i = 0; i < len; i++) + free (list[i]); + + free (list); + + return (result); +} + +#define slashify_in_quotes "\\`\"$" + +/* Return an array of tokens, much as the shell might. The tokens are + parsed out of STRING. */ +char ** +history_tokenize (string) + char *string; +{ + char **result = (char **)NULL; + register int i, start, result_index, size; + int len; + + i = result_index = size = 0; + + /* Get a token, and stuff it into RESULT. The tokens are split + exactly where the shell would split them. */ + get_token: + + /* Skip leading whitespace. */ + for (; string[i] && whitespace(string[i]); i++); + + start = i; + + if (!string[i] || string[i] == history_comment_char) + return (result); + + if (member (string[i], "()\n")) { + i++; + goto got_token; + } + + if (member (string[i], "<>;&|")) { + int peek = string[i + 1]; + + if (peek == string[i]) { + if (peek == '<') { + if (string[1 + 2] == '-') + i++; + i += 2; + goto got_token; + } + + if (member (peek, ">:&|")) { + i += 2; + goto got_token; + } + } else { + if ((peek == '&' && + (string[i] == '>' || string[i] == '<')) || + ((peek == '>') && + (string[i] == '&'))) { + i += 2; + goto got_token; + } + } + i++; + goto got_token; + } + + /* Get word from string + i; */ + { + int delimiter = 0; + + if (member (string[i], "\"'`")) + delimiter = string[i++]; + + for (;string[i]; i++) { + + if (string[i] == '\\') { + + if (string[i + 1] == '\n') { + i++; + continue; + } else { + if (delimiter != '\'') + if ((delimiter != '"') || + (member (string[i], slashify_in_quotes))) { + i++; + continue; + } + } + } + + if (delimiter && string[i] == delimiter) { + delimiter = 0; + continue; + } + + if (!delimiter && (member (string[i], " \t\n;&()|<>"))) + goto got_token; + + if (!delimiter && member (string[i], "\"'`")) { + delimiter = string[i]; + continue; + } + } + got_token: + + len = i - start; + if (result_index + 2 >= size) { + if (!size) + result = (char **)xmalloc ((size = 10) * (sizeof (char *))); + else + result = + (char **)xrealloc (result, ((size += 10) * (sizeof (char *)))); + } + result[result_index] = (char *)xmalloc (1 + len); + strncpy (result[result_index], string + start, len); + result[result_index][len] = '\0'; + result_index++; + result[result_index] = (char *)NULL; + } + if (string[i]) + goto get_token; + + return (result); +} + +#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 */ + + +/* **************************************************************** */ +/* */ +/* Test Code */ +/* */ +/* **************************************************************** */ +#ifdef TEST +main () +{ + char line[1024], *t; + int done = 0; + + line[0] = 0; + + while (!done) + { + fprintf (stdout, "history%% "); + t = gets (line); + + if (!t) + strcpy (line, "quit"); + + if (line[0]) + { + char *expansion; + int result; + + using_history (); + + result = history_expand (line, &expansion); + strcpy (line, expansion); + free (expansion); + if (result) + fprintf (stderr, "%s\n", line); + + if (result < 0) + continue; + + add_history (line); + } + + if (strcmp (line, "quit") == 0) done = 1; + if (strcmp (line, "save") == 0) write_history (0); + if (strcmp (line, "read") == 0) read_history (0); + if (strcmp (line, "list") == 0) + { + register HIST_ENTRY **the_list = history_list (); + register int i; + + if (the_list) + for (i = 0; the_list[i]; i++) + fprintf (stdout, "%d: %s\n", i + history_base, the_list[i]->line); + } + if (strncmp (line, "delete", strlen ("delete")) == 0) + { + int which; + if ((sscanf (line + strlen ("delete"), "%d", &which)) == 1) + { + HIST_ENTRY *entry = remove_history (which); + if (!entry) + fprintf (stderr, "No such entry %d\n", which); + else + { + free (entry->line); + free (entry); + } + } + else + { + fprintf (stderr, "non-numeric arg given to `delete'\n"); + } + } + } +} + +#endif /* TEST */ + +/* +* Local variables: +* compile-command: "gcc -g -DTEST -o history history.c" +* end: +*/ diff --git a/gdb/readline/history.h b/gdb/readline/history.h new file mode 100644 index 0000000000..0bac209207 --- /dev/null +++ b/gdb/readline/history.h @@ -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 (); + + diff --git a/gdb/readline/inc-history.texinfo b/gdb/readline/inc-history.texinfo new file mode 100644 index 0000000000..4e121c313f --- /dev/null +++ b/gdb/readline/inc-history.texinfo @@ -0,0 +1,187 @@ +@ifinfo +This file documents the GNU History library. + +Copyright (C) 1988 Free Software Foundation, Inc. +Authored by Brian Fox. + +Permission is granted to make and distribute verbatim copies of this manual +provided the copyright notice and this permission notice are preserved on +all copies. +@end ifinfo + +@ignore +Permission is granted to process this file through Tex and print the +results, provided the printed document carries copying permission notice +identical to this one except for the removal of this paragraph (this +paragraph not being relevant to the printed manual). + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that the +GNU Copyright statement is available to the distributee, and provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions. +@end ignore + +@node History Top +@ifinfo +This file is meant to be an inclusion in the documentation of programs +that use the history library features. There is also a standalone +document, entitled @file{history.texinfo}. +@end ifinfo + +This chapter describes the GNU History library, a programming tool that +provides a consistent user interface for recalling lines of previously +typed input. + +@menu +* Introduction to History:: What is the GNU History library for? +* History Interaction:: What it feels like using History as a user. +@end menu + +@node Introduction to History, History Interaction, History Top, Top +@section Introduction to History + +Many programs read input from the user a line at a time. The GNU history +library is able to keep track of those lines, associate arbitrary data with +each line, and utilize information from previous lines in making up new +ones. + +The programmer using the History library has available to him functions +for remembering lines on a history stack, associating arbitrary data +with a line, removing lines from the stack, searching through the stack +for a line containing an arbitrary text string, and referencing any line +on the stack directly. In addition, a history @dfn{expansion} function +is available which provides for a consistent user interface across many +different programs. + +The end-user using programs written with the History library has the +benifit of a consistent user interface, with a set of well-known +commands for manipulating the text of previous lines and using that text +in new commands. The basic history manipulation commands are similar to +the history substitution used by Csh. + +If the programmer desires, he can use the Readline library, which +includes history manipulation by default, and has the added advantage of +Emacs style command line editing. + +@node History Interaction, , Introduction to History, Top +@section History Interaction +@cindex expansion + +The History library provides a history expansion feature that is similar +to the history expansion in Csh. The following text describes what +syntax features are available. + +History expansion takes place in two parts. The first is to determine +which line from the previous history should be used during substitution. +The second is to select portions of that line for inclusion into the +current one. The line selected from the previous history is called the +@dfn{event}, and the portions of that line that are acted upon are +called @dfn{words}. The line is broken into words in the same fashion +that the Bash shell does, so that several English (or Unix) words +surrounded by quotes are considered as one word. + +@menu +* Event Designators:: How to specify which history line to use. * +Word Designators:: Specifying which words are of interest. * +Modifiers:: Modifying the results of susbstitution. +@end menu + +@node Event Designators, Word Designators, , History Interaction +@subsection Event Designators +@cindex event designators + +An event designator is a reference to a command line entry in the +history list. + +@table @asis + +@item @code{!} +Start a history subsititution, except when followed by a space, tab, or +the end of the line... @key{=} or @key{(}. + +@item @code{!!} +Refer to the previous command. This is a synonym for @code{!-1}. + +@item @code{!n} +Refer to command line @var{n}. + +@item @code{!-n} +Refer to the command line @var{n} lines back. + +@item @code{!string} +Refer to the most recent command starting with @var{string}. + +@item @code{!?string}[@code{?}] +Refer to the most recent command containing @var{string}. + +@end table + +@node Word Designators, Modifiers, Event Designators, History Interaction +@subsection Word Designators + +A @key{:} separates the event specification from the word designator. It +can be omitted if the word designator begins with a @key{^}, @key{$}, +@key{*} or @key{%}. Words are numbered from the beginning of the line, +with the first word being denoted by a 0 (zero). + +@table @code + +@item 0 (zero) +The zero'th word. For many applications, this is the command word. + +@item n +The @var{n}'th word. + +@item ^ +The first argument. that is, word 1. + +@item $ +The last argument. + +@item % +The word matched by the most recent @code{?string?} search. + +@item x-y +A range of words; @code{-@var{y}} Abbreviates @code{0-@var{y}}. + +@item * +All of the words, excepting the zero'th. This is a synonym for @code{1-$}. +It is not an error to use @key{*} if there is just one word in the event. +The empty string is returned in that case. + +@end table + +@node Modifiers, , Word Designators, History Interaction +@subsection Modifiers + +After the optional word designator, you can add a sequence of one or more +of the following modifiers, each preceded by a @key{:}. + +@table @code + +@item # +The entire command line typed so far. This means the current command, +not the previous command, so it really isn't a word designator, and doesn't +belong in this section. + +@item h +Remove a trailing pathname component, leaving only the head. + +@item r +Remove a trailing suffix of the form @samp{.}@var{suffix}, leaving the basename. + +@item e +Remove all but the suffix. + +@item t +Remove all leading pathname components, leaving the tail. + +@item p +Print the new command but do not execute it. This takes effect +immediately, so it should be the last specifier on the line. + +@end table diff --git a/gdb/readline/inc-readline.texinfo b/gdb/readline/inc-readline.texinfo new file mode 100644 index 0000000000..8dc80ccab6 --- /dev/null +++ b/gdb/readline/inc-readline.texinfo @@ -0,0 +1,494 @@ +@ignore + +This file documents the end user interface to the GNU command line +editing feautres. It is to be an appendix to manuals for programs which +use these features. There is a document entitled "readline.texinfo" +which contains both end-user and programmer documentation for the GNU +Readline Library. + +Copyright (C) 1988 Free Software Foundation, Inc. + +Authored by Brian Fox. + +Permission is granted to process this file through Tex and print the +results, provided the printed document carries copying permission notice +identical to this one except for the removal of this paragraph (this +paragraph not being relevant to the printed manual). + +Permission is granted to make and distribute verbatim copies of this manual +provided the copyright notice and this permission notice are preserved on +all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that the +GNU Copyright statement is available to the distributee, and provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions. +@end ignore + +@appendix Command Line Editing +@node Command Line Editing, , , Top + +This appendix describes GNU's command line editing interface. + +@menu +* Introduction and Notation:: Notation used in this appendix. +* Basic Line Editing:: The minimum set of commands for editing a line. +* Movement Commands:: Commands for moving the cursor about the line. +* Cutting and Pasting:: Deletion and copying of text sections. +* Transposition:: Exchanging two characters or words. +* Completion:: Expansion of a partially typed word into + the full text. +@end menu + +@node Readline Introduction, Readline Interaction, Readline Top, Readline Top +@section Introduction to Line Editing + +Many programs read input from the user one line at a time. The GNU +Readline library provides Emacs style command line editing, and +interfaces directly with the GNU History library. @inforef{Top, History, +history.info}, for more information. + +Readline uses a single initialization file, (@file{~/.inputrc}) which +means that any program which uses Readline will present your customized +version of Readline. @xref{Readline Init File} for details. + +In this section of the manual, we use a special syntax to describe +keystrokes. + +The text @key{C-k} is read as `Control-K' and describes the character +produced when the Control key is depressed and the @key{k} key is struck. + +The text @key{M-k} is read as `Meta-K' and describes the character +produced when the meta key (if you have one) is depressed, and the @key{k} +key is struck. If you do not have a meta key, the identical keystroke +can be generated by typing @key{ESC} @i{first}, and then typing @key{k}. +Either process is known as @dfn{metafying} the @key{k} key. + +The text @key{M-C-k} is read as `Meta-Control-k' and describes the +character produced by @dfn{metafying} @key{C-k}. + +In addition, several keys have their own names. Specifically, +@key{RUBOUT}, @key{DEL}, @key{ESC}, @key{NEWLINE}, @key{SPACE}, +@key{RETURN}, @key{LFD}, and @key{TAB} all stand for themselves when +seen in this text, or in an init file (@pxref{Readline Init File}, for +more info). + +@node Readline Interaction, Readline Init File, Readline Introduction, Readline Top +@section Readline Interaction +@cindex interaction, readline + +Often during an interactive session you will type in a long line of +text, only to notice that the first word on the line is misspelled. The +Readline library gives you a set of commands for manipulating the text +as you type it in, allowing you to just fix your typo, and not forcing +you to retype the majority of the line. Using these editing commands, +you move the cursor to the place that needs correction, and delete or +insert the text of the corrections. Then, when you are satisfied with +the line, you simply press @key{RETURN}. You do not have to be at the +end of the line to press @key{RETURN}; the entire line will be accepted +in any case. + +@menu +* Readline Bare Essentials:: The least you need to know about Readline. +* Readline Movement Commands:: Moving about the input line. +* Readline Killing Commands:: How to delete text, and how to get it back! +* Readline Arguments:: Giving numeric arguments to commands. +@end menu + +@node Readline Bare Essentials, Readline Movement Commands, Readline Interaction, Readline Interaction +@subsection Readline Bare Essentials + +As you type text into the line, you will notice that characters to the +right of the cursor get `pushed over' to make room for the characters +that you are typing. Likewise, when you delete a character behind the +cursor, characters to the right of the cursor get `pulled back' to fill +in the blank space created by the removal of the character. There is no +`overwrite mode' provided by Readline; all characters are inserted. + +Here are the basic bare essentials for editing the text of an input line. + +@table @key +@item C-b +Move back one character. +@item C-f +Move forward one character. +@item C-d +Delete the character underneath the cursor. +@item DEL +Delete the character to the left of the cursor. +@item printing character +Insert itself into the line at the cursor. +@item C-_ +Undo the last thing that you did. You can undo all the way back to an +empty line. +@end table + +@node Readline Movement Commands, Readline Killing Commands, Readline Bare Essentials, Readline Interaction +@subsection Readline Movement Commands + +The above table described the most basic possible keystrokes that you +would need in order to do editing of the input line. For your +convenience, many other commands have been added in addition to +@key{C-b}, @key{C-f}, @key{C-d}, and @key{DEL}. Here are some +commands for moving more rapidly about the line. + +@table @key +@item C-a +Move to the start of the line. +@item C-e +Move to the end of the line. +@item M-f +Move forward a word. +@item M-b +Move backward a word. +@item C-l +Clear the screen, reprinting the current line at the top. +@end table + +Notice how @key{C-f} moves forward a character, while @key{M-f} moves +forward a word? It is a loose convention that control keystrokes +operate on characters while meta keystrokes operate on words. + +@node Readline Killing Commands, Readline Arguments, Readline Movement Commands, Readline Interaction +@subsection Readline Killing Commands + +Now that we know how to move about the line, we might be interested in +performing more sophisticated operations, such as moving a word from the +front of the line to the end, or removing a mistyped argument to a +command. + +@dfn{Killing} text means to delete the text from the line, but to save +it away for later use, usually by @dfn{yanking} it back into the line. +If the description for a command says that it `kills' text, then you can +be sure that you can get the text back in a different (or the same) +place later. + +Here is the list of commands for killing text. + +@table @key +@item C-k +Kill the text from the current cursor position to the end of the line. + +@item M-d +Kill from the cursor to the end of the current word, or if between +words, to the end of the next word. + +@item M-DEL +Kill from the cursor to the start of the current word, or if between +words, to the start of the previous word. + +@item C-w +Kill from the cursor to the previous whitespace. This is different than +@key{M-DEL} because the word boundaries differ. + +@end table + +And, here is how to @dfn{yank} the text back into the line. + +@table @key +@item C-y +Yank the most recently killed text back into the buffer at the cursor. + +@item M-y +Rotate the kill-ring, and yank the new top. You can only do this if +the prior command is @key{C-y} or @key{M-y}. +@end table + +When you use a kill command, the text is saved in a @dfn{kill-ring}. +Any number of consecutive kills save all of the killed text together, so +that when you yank it back, you get it in one clean sweep. The kill +ring is not line specific; the text that you killed on a previously +typed line is available to be yanked back later, when you are typing +another line. + +@node Readline Arguments, , Readline Killing Commands, Readline Interaction +@subsection Readline Arguments + +You can pass numeric arguments to Readline commands. Sometimes the +argument acts as a repeat count, other times it is the @i{sign} of the +argument that is significant. If you pass a negative argument to a +command which normally acts in a forward direction, that command will +act in a backward direction. For example, to kill text back to the +start of the line, you might type @key{M--} @key{C-k}. + +The general way to pass numeric arguments to a command is to type meta +digits before the command. If the first `digit' you type is a minus +sign (@key{-}), then the sign of the argument will be negative. Once +you have typed one meta digit to get the argument started, you can type +the remainder of the digits, and then the command. For example, to give +the @key{C-d} command an argument of 10, you could type @key{M-1 0 C-d}. + + +@node Readline Init File, , Readline Interaction, Readline Top +@section Readline Init File + +Although the Readline library comes with a set of Emacs-like +keybindings, it is possible that you would like to use a different set +of keybindings. You can customize programs that use Readline by putting +commands in an @dfn{init} file in your home directory. The name of this +file is @file{~/.inputrc}. + +When a program which uses the Readline library starts up, the +@file{~/.inputrc} file is read, and the keybindings are set. + +@menu +* Readline Init Syntax:: Syntax for the commands in @file{~/.inputrc}. +* Readline Vi Mode:: Switching to @code{vi} mode in Readline. +@end menu + +@node Readline Init Syntax, Readline Vi Mode, Readline Init File, Readline Init File +@subsection Readline Init Syntax + +You can start up with a vi-like editing mode by placing + +@example +@code{set editing-mode vi} +@end example + +in your @file{~/.inputrc} file. + +You can have Readline use a single line for display, scrolling the input +between the two edges of the screen by placing + +@example +@code{set horizontal-scroll-mode On} +@end example + +in your @file{~/.inputrc} file. + +The syntax for controlling keybindings in the @file{~/.inputrc} file is +simple. First you have to know the @i{name} of the command that you +want to change. The following pages contain tables of the command name, the +default keybinding, and a short description of what the command does. + +Once you know the name of the command, simply place the name of the key +you wish to bind the command to, a colon, and then the name of the +command on a line in the @file{~/.inputrc} file. Here is an example: + +@example +# This is a comment line. +Meta-Rubout: backward-kill-word +Control-u: universal-argument +@end example + +@menu +* Commands For Moving:: Moving about the line. +* Commands For History:: Getting at previous lines. +* Commands For Text:: Commands for changing text. +* Commands For Killing:: Commands for killing and yanking. +* Numeric Arguments:: Specifying numeric arguments, repeat counts. +* Commands For Completion:: Getting Readline to do the typing for you. +* Miscellaneous Commands:: Other miscillaneous commands. +@end menu + +@node Commands For Moving, Commands For History, Readline Init Syntax, Readline Init Syntax +@subsubsection Commands For Moving +@table @code +@item beginning-of-line (C-a) +Move to the start of the current line. + +@item end-of-line (C-e) +Move to the end of the line. + +@item forward-char (C-f) +Move forward a character. + +@item backward-char (C-b) +Move back a character. + +@item forward-word (M-f) +Move forward to the end of the next word. + +@item backward-word (M-b) +Move back to the start of this, or the previous, word. + +@item clear-screen (C-l) +Clear the screen leaving the current line at the top of the screen. + +@end table + +@node Commands For History, Commands For Text, Commands For Moving, Readline Init Syntax +@subsubsection Commands For Manipulating The History + +@table @code +@item accept-line (Newline, Return) +Accept the line regardless of where the cursor is. If this line is +non-empty, add it too the history list. If this line was a history +line, then restore the history line to its original state. + +@item previous-history (C-p) +Move `up' through the history list. + +@item next-history (C-n) +Move `down' through the history list. + +@item beginning-of-history (M-<) +Move to the first line in the history. + +@item end-of-history (M->) +Move to the end of the input history, i.e., the line you are entering! + +@item reverse-search-history (C-r) +Search backward starting at the current line and moving `up' through +the history as necessary. This is an incremental search. + +@item forward-search-history (C-s) +Search forward starting at the current line and moving `down' through +the the history as neccessary. + +@end table + +@node Commands For Text, Commands For Killing, Commands For History, Readline Init Syntax +@subsubsection Commands For Changing Text + +@table @code +@item delete-char (C-d) +Delete the character under the cursor. If the cursor is at the +beginning of the line, and there are no characters in the line, and +the last character typed was not C-d, then return EOF. + +@item backward-delete-char (Rubout) +Delete the character behind the cursor. A numeric arg says to kill +the characters instead of deleting them. + +@item quoted-insert (C-q, C-v) +Add the next character that you type to the line verbatim. This is +how to insert things like C-q for example. + +@item tab-insert (M-TAB) +Insert a tab character. + +@item self-insert (a, b, A, 1, !, ...) +Insert yourself. + +@item transpose-chars (C-t) +Drag the character before point forward over the character at point. +Point moves forward as well. If point is at the end of the line, then +transpose the two characters before point. Negative args don't work. + +@item transpose-words (M-t) +Drag the word behind the cursor past the word in front of the cursor +moving the cursor over that word as well. + +@item upcase-word (M-u) +Uppercase the current (or following) word. With a negative argument, +do the previous word, but do not move point. + +@item downcase-word (M-l) +Lowercase the current (or following) word. With a negative argument, +do the previous word, but do not move point. + +@item capitalize-word (M-c) +Uppercase the current (or following) word. With a negative argument, +do the previous word, but do not move point. + +@end table + +@node Commands For Killing, Numeric Arguments, Commands For Text, Readline Init Syntax +@subsubsection Killing And Yanking + +@table @code + +@item kill-line (C-k) +Kill the text from the current cursor position to the end of the line. + +@item backward-kill-line () +Kill backward to the beginning of the line. This is normally unbound. + +@item kill-word (M-d) +Kill from the cursor to the end of the current word, or if between +words, to the end of the next word. + +@item backward-kill-word (M-DEL) +Kill the word behind the cursor. + +@item unix-line-discard (C-u) +Do what C-u used to do in Unix line input. We save the killed text on +the kill-ring, though. + +@item unix-word-rubout (C-w) +Do what C-w used to do in Unix line input. The killed text is saved +on the kill-ring. This is different than backward-kill-word because +the word boundaries differ. + +@item yank (C-y) +Yank the top of the kill ring into the buffer at point. + +@item yank-pop (M-y) +Rotate the kill-ring, and yank the new top. You can only do this if +the prior command is yank or yank-pop. +@end table + +@node Numeric Arguments, Commands For Completion, Commands For Killing, Readline Init Syntax +@subsubsection Specifying Numeric Arguments +@table @code + +@item digit-argument (M-0, M-1, ... M--) +Add this digit to the argument already accumulating, or start a new +argument. M-- starts a negative argument. + +@item universal-argument () +Do what C-u does in emacs. By default, this is not bound. +@end table + + +@node Commands For Completion, Miscellaneous Commands, Numeric Arguments, Readline Init Syntax +@subsubsection Letting Readline Type For You + +@table @code +@item complete (TAB) +Attempt to do completion on the text before point. This is +implementation defined. Generally, if you are typing a filename +argument, you can do filename completion; if you are typing a command, +you can do command completion, if you are typing in a symbol to GDB, you +can do symbol name completion, if you are typing in a variable to Bash, +you can do variable name completion... + +@item possible-completions (M-?) +List the possible completions of the text before point. +@end table + +@node Miscellaneous Commands, , Commands For Completion, Readline Init Syntax +@subsubsection Some Miscellaneous Commands +@table @code + +@item abort (C-g) +Ding! Stops things. + +@item do-uppercase-version (M-a, M-b, ...) +Run the command that is bound to your uppercase brother. + +@item prefix-meta (ESC) +Make the next character that you type be metafied. This is for +people without a meta key. @key{ESC-f} is equivalent to @key{M-f}. + +@item undo (C-_) +Incremental undo, separately remembered for each line. + +@item revert-line (M-r) +Undo all changes made to this line. This is like typing the `undo' +command enough times to get back to the beginning. +@end table + +@node Readline Vi Mode, , Readline Init Syntax, Readline Init File +@subsection Readline Vi Mode + +While the Readline library does not have a full set of Vi editing +functions, it does contain enough to allow simple editing of the line. + +In order to switch interactively between Emacs and Vi editing modes, use +the command M-C-j (toggle-editing-mode). + +When you enter a line in Vi mode, you are already placed in `insertion' +mode, as if you had typed an `i'. Pressing @key{ESC} switches you into +`edit' mode, where you can edit the text of the line with the standard +Vi movement keys, move to previous history lines with `k', and following +lines with `j', and so forth. + + + + diff --git a/gdb/readline/keymaps.c b/gdb/readline/keymaps.c new file mode 100644 index 0000000000..e0c5e394a4 --- /dev/null +++ b/gdb/readline/keymaps.c @@ -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 */ diff --git a/gdb/readline/keymaps.h b/gdb/readline/keymaps.h new file mode 100644 index 0000000000..3c577b398f --- /dev/null +++ b/gdb/readline/keymaps.h @@ -0,0 +1,53 @@ +/* keymaps.h -- Manipulation of readline keymaps. */ + +#ifndef _KEYMAPS_H_ +#define _KEYMAPS_H_ + +#include + +#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_ */ + + diff --git a/gdb/readline/readline.c b/gdb/readline/readline.c new file mode 100644 index 0000000000..a9ed39e116 --- /dev/null +++ b/gdb/readline/readline.c @@ -0,0 +1,5559 @@ +/* readline.c -- a general facility for reading lines of input + with emacs style editing and completion. */ + +/* Copyright (C) 1987,1989 Free Software Foundation, Inc. + + This file contains the Readline Library (the Library), a set of + routines for providing Emacs style line input to programs that ask + for it. + + The Library 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. + + The Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* 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 + +#include +#include +#include +#include +#include + +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else +#if defined (sparc) && defined (sun) +#include +#endif +#endif + +#define NEW_TTY_DRIVER +#if defined (SYSV) || defined (hpux) +#undef NEW_TTY_DRIVER +#include +#else +#include +#endif + +#include +extern int errno; + +#include + +/* These next are for filename completion. Perhaps this belongs + in a different place. */ +#include + +#include +#ifdef SYSV +struct passwd *getpwuid (), *getpwent (); +#endif + +#define HACK_TERMCAP_MOTION + +#ifndef SYSV +#include +#else /* SYSV */ +#ifdef hpux +#include +#else +#include +#define direct dirent +#define d_namlen d_reclen +#endif /* hpux */ +#endif /* SYSV */ + +/* Some standard library routines. */ +#include "readline.h" +#include "history.h" + +#ifndef digit +#define digit(c) ((c) >= '0' && (c) <= '9') +#endif + +#ifndef isletter +#define isletter(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z')) +#endif + +#ifndef digit_value +#define digit_value(c) ((c) - '0') +#endif + +#ifndef member +char *index (); +#define member(c, s) ((c) ? index ((s), (c)) : 0) +#endif + +#ifndef isident +#define isident(c) ((isletter(c) || digit(c) || c == '_')) +#endif + +#ifndef exchange +#define exchange(x, y) {int temp = x; x = y; y = temp;} +#endif + +static update_line (); +static void output_character_function (); +static delete_chars (); +static start_insert (); +static end_insert (); + +#ifdef VOID_SIGHANDLER +#define sighandler void +#else +#define sighandler int +#endif + +/* This typedef is equivalant to the one for Function; it allows us + to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */ +typedef sighandler SigHandler (); + +#ifdef SIGWINCH +static sighandler rl_handle_sigwinch (); +static SigHandler *old_sigwinch = (SigHandler *)NULL; +#endif + +/* If on, then readline handles signals in a way that doesn't screw. */ +#define HANDLE_SIGNALS + +#if defined (SYSV) +#ifdef HANDLE_SIGNALS +#undef HANDLE_SIGNALS +#endif +#endif + + +/* **************************************************************** */ +/* */ +/* Line editing input utility */ +/* */ +/* **************************************************************** */ + +/* A pointer to the keymap that is currently in use. + By default, it is the standard emacs keymap. */ +Keymap keymap = emacs_standard_keymap; + +#define vi_mode 0 +#define emacs_mode 1 + +/* The current style of editing. */ +int rl_editing_mode = emacs_mode; + +/* Non-zero if the previous command was a kill command. */ +static int last_command_was_kill = 0; + +/* The current value of the numeric argument specified by the user. */ +int rl_numeric_arg = 1; + +/* Non-zero if an argument was typed. */ +int rl_explicit_arg = 0; + +/* Temporary value used while generating the argument. */ +static int arg_sign = 1; + +/* Non-zero means we have been called at least once before. */ +static int rl_initialized = 0; + +/* If non-zero, this program is running in an EMACS buffer. */ +static char *running_in_emacs = (char *)NULL; + +/* The current offset in the current input line. */ +int rl_point; + +/* Mark in the current input line. */ +int rl_mark; + +/* Length of the current input line. */ +int rl_end; + +/* Make this non-zero to return the current input_line. */ +int rl_done; + +/* The last function executed by readline. */ +Function *rl_last_func = (Function *)NULL; + +/* Top level environment for readline_internal (). */ +static jmp_buf readline_top_level; + +/* The streams we interact with. */ +static FILE *in_stream, *out_stream; + +/* The names of the streams that we do input and output to. */ +FILE *rl_instream = stdin, *rl_outstream = stdout; + +/* Non-zero means echo characters as they are read. */ +int readline_echoing_p = 1; + +/* Current prompt. */ +char *rl_prompt; + +/* The number of characters read in order to type this complete command. */ +int rl_key_sequence_length = 0; + +/* If non-zero, then this is the address of a function to call just + before readline_internal () prints the first prompt. */ +Function *rl_startup_hook = (Function *)NULL; + +/* What we use internally. You should always refer to RL_LINE_BUFFER. */ +static char *the_line; + +/* The character that can generate an EOF. Really read from + the terminal driver... just defaulted here. */ +static int eof_char = CTRL ('D'); + +/* Non-zero makes this the next keystroke to read. */ +int rl_pending_input = 0; + +/* Pointer to a useful terminal name. */ +char *rl_terminal_name = (char *)NULL; + +/* Line buffer and maintenence. */ +char *rl_line_buffer = (char *)NULL; +static int rl_line_buffer_len = 0; +#define DEFAULT_BUFFER_SIZE 256 + + +/* **************************************************************** */ +/* */ +/* Top Level Functions */ +/* */ +/* **************************************************************** */ + +/* Read a line of input. Prompt with PROMPT. A NULL PROMPT means + none. A return value of NULL means that EOF was encountered. */ +char * +readline (prompt) + char *prompt; +{ + static rl_prep_terminal (), rl_deprep_terminal (); + char *readline_internal (); + char *value; + + rl_prompt = prompt; + + /* If we are at EOF return a NULL string. */ + if (rl_pending_input == EOF) + { + rl_pending_input = 0; + return ((char *)NULL); + } + + rl_initialize (); + rl_prep_terminal (); + +#ifdef SIGWINCH + old_sigwinch = (SigHandler *)signal (SIGWINCH, rl_handle_sigwinch); +#endif + +#ifdef HANDLE_SIGNALS + rl_set_signals (); +#endif + + value = readline_internal (); + rl_deprep_terminal (); + +#ifdef SIGWINCH + signal (SIGWINCH, old_sigwinch); +#endif + +#ifdef HANDLE_SIGNALS + rl_clear_signals (); +#endif + + return (value); +} + +/* Read a line of input from the global rl_instream, doing output on + the global rl_outstream. + If rl_prompt is non-null, then that is our prompt. */ +char * +readline_internal () +{ + int lastc, c, eof_found; + + in_stream = rl_instream; out_stream = rl_outstream; + lastc = eof_found = 0; + + if (rl_startup_hook) + (*rl_startup_hook) (); + + if (!readline_echoing_p) + { + if (rl_prompt) + fprintf (out_stream, "%s", rl_prompt); + } + else + { + rl_on_new_line (); + rl_redisplay (); +#ifdef VI_MODE + if (rl_editing_mode == vi_mode) + rl_vi_insertion_mode (); +#endif /* VI_MODE */ + } + + while (!rl_done) + { + int lk = last_command_was_kill; + int code = setjmp (readline_top_level); + + if (code) + rl_redisplay (); + + if (!rl_pending_input) + { + /* Then initialize the argument and number of keys read. */ + rl_init_argument (); + rl_key_sequence_length = 0; + } + + c = rl_read_key (); + + /* EOF typed to a non-blank line is a . */ + if (c == EOF && rl_end) + c = NEWLINE; + + /* The character eof_char typed to blank line, and not as the + previous character is interpreted as EOF. */ + if (((c == eof_char && lastc != c) || c == EOF) && !rl_end) + { + eof_found = 1; + break; + } + + lastc = c; + rl_dispatch (c, keymap); + + /* If there was no change in last_command_was_kill, then no kill + has taken place. Note that if input is pending we are reading + a prefix command, so nothing has changed yet. */ + if (!rl_pending_input) + { + if (lk == last_command_was_kill) + last_command_was_kill = 0; + } + +#ifdef VI_MODE + /* In vi mode, when you exit insert mode, the cursor moves back + over the previous character. We explicitly check for that here. */ + if (rl_editing_mode == vi_mode && keymap == vi_movement_keymap) + rl_vi_check (); +#endif + + if (!rl_done) + rl_redisplay (); + } + + /* Restore the original of this history line, iff the line that we + are editing was originally in the history, AND the line has changed. */ + { + HIST_ENTRY *entry = current_history (); + + if (entry && rl_undo_list) + { + char *temp = savestring (the_line); + rl_revert_line (); + entry = replace_history_entry (where_history (), the_line, + (HIST_ENTRY *)NULL); + free_history_entry (entry); + + strcpy (the_line, temp); + free (temp); + } + } + + /* At any rate, it is highly likely that this line has an undo list. Get + rid of it now. */ + if (rl_undo_list) + free_undo_list (); + + if (eof_found) + return (char *)NULL; + else + return (savestring (the_line)); +} + + +/* **************************************************************** */ +/* */ +/* Signal Handling */ +/* */ +/* **************************************************************** */ + +#ifdef SIGWINCH +static sighandler +rl_handle_sigwinch (sig, code, scp) + int sig, code; + struct sigcontext *scp; +{ + char *term = rl_terminal_name, *getenv (); + + if (readline_echoing_p) + { + if (!term) + term = getenv ("TERM"); + if (!term) + term = "dumb"; + rl_reset_terminal (term); +#ifdef NEVER + crlf (); + rl_forced_update_display (); +#endif + } + + if (old_sigwinch && + old_sigwinch != (SigHandler *)SIG_IGN && + old_sigwinch != (SigHandler *)SIG_DFL) + (*old_sigwinch)(sig, code, scp); +} +#endif /* SIGWINCH */ + +#ifdef HANDLE_SIGNALS +/* Interrupt handling. */ +static SigHandler *old_int = (SigHandler *)NULL, + *old_tstp = (SigHandler *)NULL, + *old_ttou = (SigHandler *)NULL, + *old_ttin = (SigHandler *)NULL, + *old_cont = (SigHandler *)NULL; + +/* Handle an interrupt character. */ +static sighandler +rl_signal_handler (sig, code, scp) + int sig, code; + struct sigcontext *scp; +{ + static rl_prep_terminal (), rl_deprep_terminal (); + + switch (sig) + { + case SIGINT: + free_undo_list (); + rl_clear_message (); + rl_init_argument (); +#ifdef SIGWINCH + signal (SIGWINCH, old_sigwinch); +#endif + +#ifdef SIGTSTP + case SIGTSTP: + case SIGTTOU: + case SIGTTIN: +#endif + + rl_clean_up_for_exit (); + rl_deprep_terminal (); + rl_clear_signals (); + rl_pending_input = 0; + + kill (getpid (), sig); + sigsetmask (0); + + rl_prep_terminal (); + rl_set_signals (); + } +} + +rl_set_signals () +{ + static int rl_signal_handler (); + + old_int = (SigHandler *)signal (SIGINT, rl_signal_handler); + if (old_int == (SigHandler *)SIG_IGN) + signal (SIGINT, SIG_IGN); + +#ifdef SIGTSTP + old_tstp = (SigHandler *)signal (SIGTSTP, rl_signal_handler); + if (old_tstp == (SigHandler *)SIG_IGN) + signal (SIGTSTP, SIG_IGN); +#endif +#ifdef SIGTTOU + old_ttou = (SigHandler *)signal (SIGTTOU, rl_signal_handler); + old_ttin = (SigHandler *)signal (SIGTTIN, rl_signal_handler); +#endif +} + +rl_clear_signals () +{ + signal (SIGINT, old_int); + +#ifdef SIGTSTP + signal (SIGTSTP, old_tstp); +#endif +#ifdef SIGTTOU + signal (SIGTTOU, old_ttou); + signal (SIGTTIN, old_ttin); +#endif +} +#endif /* HANDLE_SIGNALS */ + + + +/* **************************************************************** */ +/* */ +/* Character Input Buffering */ +/* */ +/* **************************************************************** */ + +/* If the terminal was in xoff state when we got to it, then xon_char + contains the character that is supposed to start it again. */ +static int xon_char, xoff_state; +static int pop_index = 0, push_index = 0, ibuffer_len = 511; +static unsigned char ibuffer[512]; + +/* Non-null means it is a pointer to a function to run while waiting for + character input. */ +Function *rl_event_hook = (Function *)NULL; + +#define any_typein (push_index != pop_index) + +/* Add KEY to the buffer of characters to be read. */ +rl_stuff_char (key) + int key; +{ + if (key == EOF) + { + key = NEWLINE; + rl_pending_input = EOF; + } + ibuffer[push_index++] = key; + if (push_index >= ibuffer_len) + push_index = 0; +} + +/* Return the amount of space available in the + buffer for stuffing characters. */ +int +ibuffer_space () +{ + if (pop_index > push_index) + return (pop_index - push_index); + else + return (ibuffer_len - (push_index - pop_index)); +} + +/* Get a key from the buffer of characters to be read. + Return the key in KEY. + Result is KEY if there was a key, or 0 if there wasn't. */ +int +rl_get_char (key) + int *key; +{ + if (push_index == pop_index) + return (0); + + *key = ibuffer[pop_index++]; + + if (pop_index >= ibuffer_len) + pop_index = 0; + + return (1); +} + +/* Stuff KEY into the *front* of the input buffer. + Returns non-zero if successful, zero if there is + no space left in the buffer. */ +int +rl_unget_char (key) + int key; +{ + if (ibuffer_space ()) + { + pop_index--; + if (pop_index < 0) + pop_index = ibuffer_len - 1; + ibuffer[pop_index] = key; + return (1); + } + return (0); +} + +/* If a character is available to be read, then read it + and stuff it into IBUFFER. Otherwise, just return. */ +rl_gather_tyi () +{ + int tty = fileno (in_stream); + register int tem, result = -1; + long chars_avail; + char input; + +#ifdef FIONREAD + result = ioctl (tty, FIONREAD, &chars_avail); +#endif + + if (result == -1) + { + fcntl (tty, F_SETFL, O_NDELAY); + chars_avail = read (tty, &input, 1); + fcntl (tty, F_SETFL, 0); + if (chars_avail == -1 && errno == EAGAIN) + return; + } + + tem = ibuffer_space (); + + if (chars_avail > tem) + chars_avail = tem; + + /* One cannot read all of the available input. I can only read a single + character at a time, or else programs which require input can be + thwarted. If the buffer is larger than one character, I lose. + Damn! */ + if (tem < ibuffer_len) + chars_avail = 0; + + if (result != -1) + { + while (chars_avail--) + rl_stuff_char (rl_getc (in_stream)); + } + else + { + if (chars_avail) + rl_stuff_char (input); + } +} + +/* Read a key, including pending input. */ +int +rl_read_key () +{ + int c; + + rl_key_sequence_length++; + + if (rl_pending_input) + { + c = rl_pending_input; + rl_pending_input = 0; + } + else + { + static int next_macro_key (); + + /* If input is coming from a macro, then use that. */ + if (c = next_macro_key ()) + return (c); + + /* If the user has an event function, then call it periodically. */ + if (rl_event_hook) + { + while (rl_event_hook && !rl_get_char (&c)) + { + (*rl_event_hook) (); + rl_gather_tyi (); + } + } + else + { + if (!rl_get_char (&c)) + c = rl_getc (in_stream); + } + } +#ifdef TIOCSTART + /* Ugh. But I can't think of a better way. */ + if (xoff_state && c == xon_char) + { + ioctl (fileno (in_stream), TIOCSTART, 0); + xoff_state = 0; + return rl_read_key (); + } +#endif /* TIOCSTART */ + return (c); +} + +/* Do the command associated with KEY in MAP. + If the associated command is really a keymap, then read + another key, and dispatch into that map. */ +rl_dispatch (key, map) + register int key; + Keymap map; +{ + static int defining_kbd_macro; + + if (defining_kbd_macro) + add_macro_char (key); + + if (key > 127 && key < 256) + { + if (map[ESC].type == ISKMAP) + { + map = (Keymap)map[ESC].function; + key -= 128; + rl_dispatch (key, map); + } + else + ding (); + return; + } + + switch (map[key].type) + { + case ISFUNC: + { + Function *func = map[key].function; + + if (func != (Function *)NULL) + { + /* Special case rl_do_lowercase_version (). */ + if (func == rl_do_lowercase_version) + { + rl_dispatch (to_lower (key), map); + return; + } + + (*map[key].function)(rl_numeric_arg * arg_sign, key); + } + else + { + ding (); + return; + } + } + break; + + case ISKMAP: + if (map[key].function != (Function *)NULL) + { + int newkey; + + rl_key_sequence_length++; + newkey = rl_read_key (); + rl_dispatch (newkey, (Keymap)map[key].function); + } + else + { + ding (); + return; + } + break; + + case ISMACR: + if (map[key].function != (Function *)NULL) + { + static with_macro_input (); + char *macro = savestring ((char *)map[key].function); + + with_macro_input (macro); + return; + } + break; + } + + /* If we have input pending, then the last command was a prefix + command. Don't change the state of rl_last_func. */ + if (!rl_pending_input) + rl_last_func = map[key].function; +} + + +/* **************************************************************** */ +/* */ +/* Hacking Keyboard Macros */ +/* */ +/* **************************************************************** */ + +/* The currently executing macro string. If this is non-zero, + then it is a malloc ()'ed string where input is coming from. */ +static char *executing_macro = (char *)NULL; + +/* The offset in the above string to the next character to be read. */ +static int executing_macro_index = 0; + +/* Non-zero means to save keys that we dispatch on in a kbd macro. */ +static int defining_kbd_macro = 0; + +/* The current macro string being built. Characters get stuffed + in here by add_macro_char (). */ +static char *current_macro = (char *)NULL; + +/* The size of the buffer allocated to current_macro. */ +static int current_macro_size = 0; + +/* The index at which characters are being added to current_macro. */ +static int current_macro_index = 0; + +/* A structure used to save nested macro strings. + It is a linked list of string/index for each saved macro. */ +struct saved_macro { + struct saved_macro *next; + char *string; + int index; +}; + +/* The list of saved macros. */ +struct saved_macro *macro_list = (struct saved_macro *)NULL; + +/* Set up to read subsequent input from STRING. + STRING is free ()'ed when we are done with it. */ +static +with_macro_input (string) + char *string; +{ + push_executing_macro (); + executing_macro = string; + executing_macro_index = 0; +} + +/* Return the next character available from a macro, or 0 if + there are no macro characters. */ +static int +next_macro_key () +{ + if (!executing_macro) + return (0); + + if (!executing_macro[executing_macro_index]) + { + pop_executing_macro (); + return (next_macro_key ()); + } + + return (executing_macro[executing_macro_index++]); +} + +/* Save the currently executing macro on a stack of saved macros. */ +static +push_executing_macro () +{ + struct saved_macro *saver; + + saver = (struct saved_macro *)xmalloc (sizeof (struct saved_macro)); + saver->next = macro_list; + saver->index = executing_macro_index; + saver->string = executing_macro; + + macro_list = saver; +} + +/* Discard the current macro, replacing it with the one + on the top of the stack of saved macros. */ +static +pop_executing_macro () +{ + if (executing_macro) + free (executing_macro); + + executing_macro = (char *)NULL; + executing_macro_index = 0; + + if (macro_list) + { + struct saved_macro *disposer = macro_list; + executing_macro = macro_list->string; + executing_macro_index = macro_list->index; + macro_list = macro_list->next; + free (disposer); + } +} + +/* Add a character to the macro being built. */ +static +add_macro_char (c) + int c; +{ + if (current_macro_index + 1 >= current_macro_size) + { + if (!current_macro) + current_macro = (char *)xmalloc (current_macro_size = 25); + else + current_macro = + (char *)xrealloc (current_macro, current_macro_size += 25); + } + + current_macro[current_macro_index++] = c; + current_macro[current_macro_index] = '\0'; +} + +/* Begin defining a keyboard macro. + Keystrokes are recorded as they are executed. + End the definition with rl_end_kbd_macro (). + If a numeric argument was explicitly typed, then append this + definition to the end of the existing macro, and start by + re-executing the existing macro. */ +rl_start_kbd_macro (ignore1, ignore2) + int ignore1, ignore2; +{ + if (defining_kbd_macro) + rl_abort (); + + if (rl_explicit_arg) + { + if (current_macro) + with_macro_input (savestring (current_macro)); + } + else + current_macro_index = 0; + + defining_kbd_macro = 1; +} + +/* Stop defining a keyboard macro. + A numeric argument says to execute the macro right now, + that many times, counting the definition as the first time. */ +rl_end_kbd_macro (count, ignore) + int count, ignore; +{ + if (!defining_kbd_macro) + rl_abort (); + + current_macro_index -= (rl_key_sequence_length - 1); + current_macro[current_macro_index] = '\0'; + + defining_kbd_macro = 0; + + rl_call_last_kbd_macro (--count, 0); +} + +/* Execute the most recently defined keyboard macro. + COUNT says how many times to execute it. */ +rl_call_last_kbd_macro (count, ignore) + int count, ignore; +{ + if (!current_macro) + rl_abort (); + + while (count--) + with_macro_input (savestring (current_macro)); +} + + +/* **************************************************************** */ +/* */ +/* Initializations */ +/* */ +/* **************************************************************** */ + +/* Initliaze readline (and terminal if not already). */ +rl_initialize () +{ + extern char *rl_display_prompt; + + /* If we have never been called before, initialize the + terminal and data structures. */ + if (!rl_initialized) + { + readline_initialize_everything (); + rl_initialized++; + } + + /* Initalize the current line information. */ + rl_point = rl_end = 0; + the_line = rl_line_buffer; + the_line[0] = 0; + + /* We aren't done yet. We haven't even gotten started yet! */ + rl_done = 0; + + /* Tell the history routines what is going on. */ + start_using_history (); + + /* Make the display buffer match the state of the line. */ + { + extern char *rl_display_prompt; + extern int forced_display; + + rl_on_new_line (); + + rl_display_prompt = rl_prompt ? rl_prompt : ""; + forced_display = 1; + } + + /* No such function typed yet. */ + rl_last_func = (Function *)NULL; + + /* Parsing of key-bindings begins in an enabled state. */ + { + static unsigned char parsing_conditionalized_out; + parsing_conditionalized_out = 0; + } +} + +/* Initialize the entire state of the world. */ +readline_initialize_everything () +{ + /* Find out if we are running in Emacs. */ + running_in_emacs = (char *)getenv ("EMACS"); + + /* Allocate data structures. */ + if (!rl_line_buffer) + rl_line_buffer = + (char *)xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE); + + /* Initialize the terminal interface. */ + init_terminal_io ((char *)NULL); + + /* Bind tty characters to readline functions. */ + readline_default_bindings (); + + /* Initialize the function names. */ + rl_initialize_funmap (); + + /* Read in the init file. */ + rl_read_init_file ((char *)NULL); + + /* If the completion parser's default word break characters haven't + been set yet, then do so now. */ + { + extern char *rl_completer_word_break_characters; + extern char *rl_basic_word_break_characters; + + if (rl_completer_word_break_characters == (char *)NULL) + rl_completer_word_break_characters = rl_basic_word_break_characters; + } +} + +/* If this system allows us to look at the values of the regular + input editing characters, then bind them to their readline + equivalents. */ +readline_default_bindings () +{ +#ifdef TIOCGETP + struct sgttyb ttybuff; + int tty = fileno (rl_instream); + + if (ioctl (tty, TIOCGETP, &ttybuff) != -1) + { + int erase = ttybuff.sg_erase, kill = ttybuff.sg_kill; + + if (erase != -1 && keymap[erase].type == ISFUNC) + keymap[erase].function = rl_rubout; + + if (kill != -1 && keymap[kill].type == ISFUNC) + keymap[kill].function = rl_unix_line_discard; + } + +#ifdef TIOCGLTC + { + struct ltchars lt; + + if (ioctl (tty, TIOCGLTC, <) != -1) + { + int erase = lt.t_werasc, nextc = lt.t_lnextc; + + if (erase != -1 && keymap[erase].type == ISFUNC) + keymap[erase].function = rl_unix_word_rubout; + + if (nextc != -1 && keymap[nextc].type == ISFUNC) + keymap[nextc].function = rl_quoted_insert; + } + } +#endif /* TIOCGLTC */ +#endif /* TIOCGETP */ +} + + +/* **************************************************************** */ +/* */ +/* Numeric Arguments */ +/* */ +/* **************************************************************** */ + +/* Handle C-u style numeric args, as well as M--, and M-digits. */ + +/* Add the current digit to the argument in progress. */ +rl_digit_argument (ignore, key) + int ignore, key; +{ + rl_pending_input = key; + rl_digit_loop (); +} + +/* What to do when you abort reading an argument. */ +rl_discard_argument () +{ + ding (); + rl_clear_message (); + rl_init_argument (); +} + +/* Create a default argument. */ +rl_init_argument () +{ + rl_numeric_arg = arg_sign = 1; + rl_explicit_arg = 0; +} + +/* C-u, universal argument. Multiply the current argument by 4. + Read a key. If the key has nothing to do with arguments, then + dispatch on it. If the key is the abort character then abort. */ +rl_universal_argument () +{ + rl_numeric_arg *= 4; + rl_digit_loop (); +} + +rl_digit_loop () +{ + 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 + { + if (c == '-' && !rl_explicit_arg) + { + rl_numeric_arg = 1; + arg_sign = -1; + } + else + { + rl_clear_message (); + rl_dispatch (key, keymap); + return; + } + } + } +} + + +/* **************************************************************** */ +/* */ +/* Display stuff */ +/* */ +/* **************************************************************** */ + +/* This is the stuff that is hard for me. I never seem to write good + display routines in C. Let's see how I do this time. */ + +/* (PWP) Well... Good for a simple line updater, but totally ignores + the problems of input lines longer than the screen width. + + update_line and the code that calls it makes a multiple line, + automatically wrapping line update. Carefull attention needs + to be paid to the vertical position variables. + + handling of terminals with autowrap on (incl. DEC braindamage) + could be improved a bit. Right now I just cheat and decrement + screenwidth by one. */ + +/* Keep two buffers; one which reflects the current contents of the + screen, and the other to draw what we think the new contents should + be. Then compare the buffers, and make whatever changes to the + screen itself that we should. Finally, make the buffer that we + just drew into be the one which reflects the current contents of the + screen, and place the cursor where it belongs. + + Commands that want to can fix the display themselves, and then let + this function know that the display has been fixed by setting the + RL_DISPLAY_FIXED variable. This is good for efficiency. */ + +/* Termcap variables: */ +extern char *term_up, *term_dc, *term_cr; +extern int screenheight, screenwidth, terminal_can_insert; + +/* What YOU turn on when you have handled all redisplay yourself. */ +int rl_display_fixed = 0; + +/* The visible cursor position. If you print some text, adjust this. */ +int last_c_pos = 0; +int last_v_pos = 0; + +/* The last left edge of text that was displayed. This is used when + doing horizontal scrolling. It shifts in thirds of a screenwidth. */ +static int last_lmargin = 0; + +/* The line display buffers. One is the line currently displayed on + the screen. The other is the line about to be displayed. */ +static char *visible_line = (char *)NULL; +static char *invisible_line = (char *)NULL; + +/* Number of lines currently on screen minus 1. */ +int vis_botlin = 0; + +/* A buffer for `modeline' messages. */ +char msg_buf[128]; + +/* Non-zero forces the redisplay even if we thought it was unnecessary. */ +int forced_display = 0; + +/* The stuff that gets printed out before the actual text of the line. + This is usually pointing to rl_prompt. */ +char *rl_display_prompt = (char *)NULL; + +/* Default and initial buffer size. Can grow. */ +static int line_size = 1024; + +/* Non-zero means to always use horizontal scrolling in line display. */ +int horizontal_scroll_mode = 0; + +/* I really disagree with this, but my boss (among others) insists that we + support compilers that don't work. I don't think we are gaining by doing + so; what is the advantage in producing better code if we can't use it? */ +/* The following two declarations belong inside the + function block, not here. */ +static void move_cursor_relative (); +static void output_some_chars (); + +/* Basic redisplay algorithm. */ +rl_redisplay () +{ + register int in, out, c, linenum; + register char *line = invisible_line; + int c_pos = 0; + int inv_botlin = 0; /* Number of lines in newly drawn buffer. */ + + extern int readline_echoing_p; + + if (!readline_echoing_p) + return; + + if (!rl_display_prompt) + rl_display_prompt = ""; + + if (!invisible_line) + { + visible_line = (char *)xmalloc (line_size); + invisible_line = (char *)xmalloc (line_size); + line = invisible_line; + for (in = 0; in < line_size; in++) + { + visible_line[in] = 0; + invisible_line[in] = 1; + } + rl_on_new_line (); + } + + /* Draw the line into the buffer. */ + c_pos = -1; + + /* Mark the line as modified or not. We only do this for history + lines. */ + out = 0; + if (current_history () && rl_undo_list) + { + line[out++] = '*'; + line[out] = '\0'; + } + + /* If someone thought that the redisplay was handled, but the currently + visible line has a different modification state than the one about + to become visible, then correct the callers misconception. */ + if (visible_line[0] != invisible_line[0]) + rl_display_fixed = 0; + + strncpy (line + out, rl_display_prompt, strlen (rl_display_prompt)); + out += strlen (rl_display_prompt); + line[out] = '\0'; + + for (in = 0; in < rl_end; in++) + { + c = the_line[in]; + + if (out + 1 >= line_size) + { + line_size *= 2; + visible_line = (char *)xrealloc (visible_line, line_size); + invisible_line = (char *)xrealloc (invisible_line, line_size); + line = invisible_line; + } + + if (in == rl_point) + c_pos = out; + + if (c > 127) + { + line[out++] = 'M'; + line[out++] = '-'; + line[out++] = c - 128; + } +#define DISPLAY_TABS +#ifdef DISPLAY_TABS + else if (c == '\t') + { + register int newout = (out | (int)7) + 1; + while (out < newout) + line[out++] = ' '; + } +#endif + else if (c < 32) + { + line[out++] = 'C'; + line[out++] = '-'; + line[out++] = c + 64; + } + else + line[out++] = c; + } + line[out] = '\0'; + if (c_pos < 0) + c_pos = out; + + /* PWP: now is when things get a bit hairy. The visible and invisible + line buffers are really multiple lines, which would wrap every + (screenwidth - 1) characters. Go through each in turn, finding + the changed region and updating it. The line order is top to bottom. */ + + /* If we can move the cursor up and down, then use multiple lines, + otherwise, let long lines display in a single terminal line, and + horizontally scroll it. */ + + if (!horizontal_scroll_mode && term_up && *term_up) + { + int total_screen_chars = (screenwidth * screenheight); + + if (!rl_display_fixed || forced_display) + { + forced_display = 0; + + /* If we have more than a screenful of material to display, then + only display a screenful. We should display the last screen, + not the first. I'll fix this in a minute. */ + if (out >= total_screen_chars) + out = total_screen_chars - 1; + + /* Number of screen lines to display. */ + inv_botlin = out / screenwidth; + + /* For each line in the buffer, do the updating display. */ + for (linenum = 0; linenum <= inv_botlin; linenum++) + update_line (linenum > vis_botlin ? "" + : &visible_line[linenum * screenwidth], + &invisible_line[linenum * screenwidth], + linenum); + + /* We may have deleted some lines. If so, clear the left over + blank ones at the bottom out. */ + if (vis_botlin > inv_botlin) + { + char *tt; + for (; linenum <= vis_botlin; linenum++) + { + tt = &visible_line[linenum * screenwidth]; + move_vert (linenum); + move_cursor_relative (0, tt); + clear_to_eol ((linenum == vis_botlin)? + strlen (tt) : screenwidth); + } + } + vis_botlin = inv_botlin; + + /* Move the cursor where it should be. */ + move_vert (c_pos / screenwidth); + move_cursor_relative (c_pos % screenwidth, + &invisible_line[(c_pos / screenwidth) * screenwidth]); + } + } + else /* Do horizontal scrolling. */ + { + int lmargin; + + /* Always at top line. */ + last_v_pos = 0; + + /* If the display position of the cursor would be off the edge + of the screen, start the display of this line at an offset that + leaves the cursor on the screen. */ + if (c_pos - last_lmargin > screenwidth - 2) + lmargin = (c_pos / (screenwidth / 3) - 2) * (screenwidth / 3); + else if (c_pos - last_lmargin < 1) + lmargin = ((c_pos - 1) / (screenwidth / 3)) * (screenwidth / 3); + else + lmargin = last_lmargin; + + /* If the first character on the screen isn't the first character + in the display line, indicate this with a special character. */ + if (lmargin > 0) + line[lmargin] = '<'; + + if (lmargin + screenwidth < out) + line[lmargin + screenwidth - 1] = '>'; + + if (!rl_display_fixed || forced_display || lmargin != last_lmargin) + { + forced_display = 0; + update_line (&visible_line[last_lmargin], + &invisible_line[lmargin], 0); + + move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]); + last_lmargin = lmargin; + } + } + fflush (out_stream); + + /* Swap visible and non-visible lines. */ + { + char *temp = visible_line; + visible_line = invisible_line; + invisible_line = temp; + rl_display_fixed = 0; + } +} + +/* PWP: update_line() is based on finding the middle difference of each + line on the screen; vis: + + /old first difference + /beginning of line | /old last same /old EOL + v v v v +old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as +new: eddie> Oh, my little buggy says to me, as lurgid as + ^ ^ ^ ^ + \beginning of line | \new last same \new end of line + \new first difference + + All are character pointers for the sake of speed. Special cases for + no differences, as well as for end of line additions must be handeled. + + Could be made even smarter, but this works well enough */ +static +update_line (old, new, current_line) + register char *old, *new; + int current_line; +{ + register char *ofd, *ols, *oe, *nfd, *nls, *ne; + int lendiff, wsatend; + + /* Find first difference. */ + for (ofd = old, nfd = new; + (ofd - old < screenwidth) && *ofd && (*ofd == *nfd); + ofd++, nfd++) + ; + + /* Move to the end of the screen line. */ + for (oe = ofd; ((oe - old) < screenwidth) && *oe; oe++); + for (ne = nfd; ((ne - new) < screenwidth) && *ne; ne++); + + /* If no difference, continue to next line. */ + if (ofd == oe && nfd == ne) + return; + + wsatend = 1; /* flag for trailing whitespace */ + ols = oe - 1; /* find last same */ + nls = ne - 1; + while ((*ols == *nls) && (ols > ofd) && (nls > nfd)) + { + if (*ols != ' ') + wsatend = 0; + ols--; + nls--; + } + + if (wsatend) + { + ols = oe; + nls = ne; + } + else if (*ols != *nls) + { + if (*ols) /* don't step past the NUL */ + ols++; + if (*nls) + nls++; + } + + move_vert (current_line); + move_cursor_relative (ofd - old, old); + + /* if (len (new) > len (old)) */ + lendiff = (nls - nfd) - (ols - ofd); + + /* Insert (diff(len(old),len(new)) ch */ + if (lendiff > 0) + { + if (terminal_can_insert) + { + extern char *term_IC; + + /* Sometimes it is cheaper to print the characters rather than + use the terminal's capabilities. */ + if ((2 * (ne - nfd)) < lendiff && (!term_IC || !*term_IC)) + { + output_some_chars (nfd, (ne - nfd)); + last_c_pos += (ne - nfd); + } + else + { + if (*ols) + { + start_insert (lendiff); + output_some_chars (nfd, lendiff); + last_c_pos += lendiff; + end_insert (); + } + else + { + /* At the end of a line the characters do not have to + be "inserted". They can just be placed on the screen. */ + output_some_chars (nfd, lendiff); + last_c_pos += lendiff; + } + /* Copy (new) chars to screen from first diff to last match. */ + if (((nls - nfd) - lendiff) > 0) + { + output_some_chars (&nfd[lendiff], ((nls - nfd) - lendiff)); + last_c_pos += ((nls - nfd) - lendiff); + } + } + } + else + { /* cannot insert chars, write to EOL */ + output_some_chars (nfd, (ne - nfd)); + last_c_pos += (ne - nfd); + } + } + else /* Delete characters from line. */ + { + /* If possible and inexpensive to use terminal deletion, then do so. */ + if (term_dc && (2 * (ne - nfd)) >= (-lendiff)) + { + if (lendiff) + delete_chars (-lendiff); /* delete (diff) characters */ + + /* Copy (new) chars to screen from first diff to last match */ + if ((nls - nfd) > 0) + { + output_some_chars (nfd, (nls - nfd)); + last_c_pos += (nls - nfd); + } + } + /* Otherwise, print over the existing material. */ + else + { + output_some_chars (nfd, (ne - nfd)); + last_c_pos += (ne - nfd); + clear_to_eol ((oe - old) - (ne - new)); + } + } +} + +/* (PWP) tell the update routines that we have moved onto a + new (empty) line. */ +rl_on_new_line () +{ + if (visible_line) + visible_line[0] = '\0'; + + last_c_pos = last_v_pos = 0; + vis_botlin = last_lmargin = 0; +} + +/* Actually update the display, period. */ +rl_forced_update_display () +{ + if (visible_line) + { + register char *temp = visible_line; + + while (*temp) *temp++ = '\0'; + } + rl_on_new_line (); + forced_display++; + rl_redisplay (); +} + +/* Move the cursor from last_c_pos to NEW, which are buffer indices. + DATA is the contents of the screen line of interest; i.e., where + the movement is being done. */ +static void +move_cursor_relative (new, data) + int new; + char *data; +{ + register int i; + static void output_character_function (); + + /* It may be faster to output a CR, and then move forwards instead + of moving backwards. */ + if (new + 1 < last_c_pos - new) + { + tputs (term_cr, 1, output_character_function); + last_c_pos = 0; + } + + if (last_c_pos == new) return; + + if (last_c_pos < new) + { + /* Move the cursor forward. We do it by printing the command + to move the cursor forward if there is one, else print that + portion of the output buffer again. Which is cheaper? */ + + /* The above comment is left here for posterity. It is faster + to print one character (non-control) than to print a control + sequence telling the terminal to move forward one character. + That kind of control is for people who don't know what the + data is underneath the cursor. */ +#ifdef HACK_TERMCAP_MOTION + extern char *term_forward_char; + + if (term_forward_char) + for (i = last_c_pos; i < new; i++) + tputs (term_forward_char, 1, output_character_function); + else + for (i = last_c_pos; i < new; i++) + putc (data[i], out_stream); +#else + for (i = last_c_pos; i < new; i++) + putc (data[i], out_stream); +#endif /* HACK_TERMCAP_MOTION */ + } + else + backspace (last_c_pos - new); + last_c_pos = new; +} + +/* PWP: move the cursor up or down. */ +move_vert (to) + int to; +{ + void output_character_function (); + register int delta, i; + + if (last_v_pos == to) return; + + if (to > screenheight) + return; + + if ((delta = to - last_v_pos) > 0) + { + for (i = 0; i < delta; i++) + putc ('\n', out_stream); + tputs (term_cr, 1, output_character_function); + last_c_pos = 0; /* because crlf() will do \r\n */ + } + else + { /* delta < 0 */ + if (term_up && *term_up) + for (i = 0; i < -delta; i++) + tputs (term_up, 1, output_character_function); + } + last_v_pos = to; /* now to is here */ +} + +/* Physically print C on out_stream. This is for functions which know + how to optimize the display. */ +rl_show_char (c) + int c; +{ + if (c > 127) + { + fprintf (out_stream, "M-"); + c -= 128; + } + +#ifdef DISPLAY_TABS + if (c < 32 && c != '\t') +#else + if (c < 32) +#endif + { + + c += 64; + } + + putc (c, out_stream); + fflush (out_stream); +} + +#ifdef DISPLAY_TABS +int +rl_character_len (c, pos) + register int c, pos; +{ + if (c < ' ' || c > 126) + { + if (c == '\t') + return (((pos | (int)7) + 1) - pos); + else + return (3); + } + else + return (1); +} +#else +int +rl_character_len (c) + int c; +{ + if (c < ' ' || c > 126) + return (3); + else + return (1); +} +#endif /* DISPLAY_TAB */ + +/* How to print things in the "echo-area". The prompt is treated as a + mini-modeline. */ +rl_message (string, arg1, arg2) + char *string; +{ + sprintf (msg_buf, string, arg1, arg2); + rl_display_prompt = msg_buf; + rl_redisplay (); +} + +/* How to clear things from the "echo-area". */ +rl_clear_message () +{ + rl_display_prompt = rl_prompt; + rl_redisplay (); +} + +/* **************************************************************** */ +/* */ +/* Terminal and Termcap */ +/* */ +/* **************************************************************** */ + +static char *term_buffer = (char *)NULL; +static char *term_string_buffer = (char *)NULL; + +/* Non-zero means this terminal can't really do anything. */ +int dumb_term = 0; + +char PC; +char *BC, *UP; + +/* Some strings to control terminal actions. These are output by tputs (). */ +char *term_goto, *term_clreol, *term_cr, *term_clrpag, *term_backspace; + +int screenwidth, screenheight; + +/* Non-zero if we determine that the terminal can do character insertion. */ +int terminal_can_insert = 0; + +/* How to insert characters. */ +char *term_im, *term_ei, *term_ic, *term_ip, *term_IC; + +/* How to delete characters. */ +char *term_dc, *term_DC; + +#ifdef HACK_TERMCAP_MOTION +char *term_forward_char; +#endif /* HACK_TERMCAP_MOTION */ + +/* How to go up a line. */ +char *term_up; + +/* Re-initialize the terminal considering that the TERM/TERMCAP variable + has changed. */ +rl_reset_terminal (terminal_name) + char *terminal_name; +{ + init_terminal_io (terminal_name); +} + +init_terminal_io (terminal_name) + char *terminal_name; +{ + char *term = (terminal_name? terminal_name : (char *)getenv ("TERM")); + char *tgetstr (), *buffer; + + + if (!term_string_buffer) + term_string_buffer = (char *)xmalloc (2048); + + if (!term_buffer) + term_buffer = (char *)xmalloc (2048); + + buffer = term_string_buffer; + + term_clrpag = term_cr = term_clreol = (char *)NULL; + + if (!term) + term = "dumb"; + + if (tgetent (term_buffer, term) < 0) + { + dumb_term = 1; + return; + } + + BC = tgetstr ("pc", &buffer); + PC = buffer ? *buffer : 0; + + term_backspace = tgetstr ("le", &buffer); + + term_cr = tgetstr ("cr", &buffer); + term_clreol = tgetstr ("ce", &buffer); + term_clrpag = tgetstr ("cl", &buffer); + + if (!term_cr) + term_cr = "\r"; + +#ifdef HACK_TERMCAP_MOTION + term_forward_char = tgetstr ("nd", &buffer); +#endif /* HACK_TERMCAP_MOTION */ + + screenwidth = tgetnum ("co"); + if (screenwidth <= 0) + screenwidth = 80; + screenwidth--; /* PWP: avoid autowrap bugs */ + + screenheight = tgetnum ("li"); + if (screenheight <= 0) + screenheight = 24; + + term_im = tgetstr ("im", &buffer); + term_ei = tgetstr ("ei", &buffer); + term_IC = tgetstr ("IC", &buffer); + term_ic = tgetstr ("ic", &buffer); + term_ip = tgetstr ("ip", &buffer); + term_IC = tgetstr ("IC", &buffer); + + /* "An application program can assume that the terminal can do + character insertion if *any one of* the capabilities `IC', + `im', `ic' or `ip' is provided." */ + terminal_can_insert = (term_IC || term_im || term_ic || term_ip); + + term_up = tgetstr ("up", &buffer); + term_dc = tgetstr ("dc", &buffer); + term_DC = tgetstr ("DC", &buffer); +} + +/* A function for the use of tputs () */ +static void +output_character_function (c) + int c; +{ + putc (c, out_stream); +} + +/* Write COUNT characters from STRING to the output stream. */ +static void +output_some_chars (string, count) + char *string; + int count; +{ + fwrite (string, 1, count, out_stream); +} + + +/* Delete COUNT characters from the display line. */ +static +delete_chars (count) + int count; +{ + if (count > screenwidth) + return; + + if (term_DC && *term_DC) + { + char *tgoto (), *buffer; + buffer = tgoto (term_DC, 0, count); + tputs (buffer, 1, output_character_function); + } + else + { + if (term_dc && *term_dc) + while (count--) + tputs (term_dc, 1, output_character_function); + } +} + +/* Prepare to insert by inserting COUNT blank spaces. */ +static +start_insert (count) + int count; +{ + if (term_im && *term_im) + tputs (term_im, 1, output_character_function); + + if (term_IC && *term_IC && + (count > 1 || !term_ic || !*term_ic)) + { + char *tgoto (), *buffer; + buffer = tgoto (term_IC, 0, count); + tputs (buffer, 1, output_character_function); + } + else + { + if (term_ic && *term_ic) + while (count--) + tputs (term_ic, 1, output_character_function); + } +} + +/* We are finished doing our insertion. Send ending string. */ +static +end_insert () +{ + if (term_ei && *term_ei) + tputs (term_ei, 1, output_character_function); +} + +/* Move the cursor back. */ +backspace (count) + int count; +{ + register int i; + + if (term_backspace) + for (i = 0; i < count; i++) + tputs (term_backspace, 1, output_character_function); + else + for (i = 0; i < count; i++) + putc ('\b', out_stream); +} + +/* Move to the start of the next line. */ +crlf () +{ + tputs (term_cr, 1, output_character_function); + putc ('\n', out_stream); +} + +/* Clear to the end of the line. COUNT is the minimum + number of character spaces to clear, */ +clear_to_eol (count) + int count; +{ + if (term_clreol) { + tputs (term_clreol, 1, output_character_function); + } else { + register int i; + /* Do one more character space. */ + count++; + for (i = 0; i < count; i++) + putc (' ', out_stream); + backspace (count); + } +} + + +/* **************************************************************** */ +/* */ +/* Saving and Restoring the TTY */ +/* */ +/* **************************************************************** */ + +#ifdef NEW_TTY_DRIVER + +/* Standard flags, including ECHO. */ +static int original_tty_flags = 0; + +/* Local mode flags, like LPASS8. */ +static int local_mode_flags = 0; + +/* Terminal characters. This has C-s and C-q in it. */ +static struct tchars original_tchars; + +/* Local special characters. This has the interrupt characters in it. */ +static struct ltchars original_ltchars; + +/* We use this to get and set the tty_flags. */ +static struct sgttyb the_ttybuff; + +/* Put the terminal in CBREAK mode so that we can detect key presses. */ +static +rl_prep_terminal () +{ + int tty = fileno (rl_instream); + + /* We always get the latest tty values. Maybe stty changed them. */ + + ioctl (tty, TIOCGETP, &the_ttybuff); + original_tty_flags = the_ttybuff.sg_flags; + + readline_echoing_p = (original_tty_flags & ECHO); + + /* If this terminal doesn't care how the 8th bit is used, + then we can use it for the meta-key. + We check by seeing if BOTH odd and even parity are allowed. */ + if ((the_ttybuff.sg_flags & (ODDP | EVENP)) == (ODDP | EVENP)) + { +#ifdef PASS8 + the_ttybuff.sg_flags |= PASS8; +#endif + +#if defined (TIOCLGET) && defined (LPASS8) + { + int flags; + ioctl (tty, TIOCLGET, &flags); + local_mode_flags = flags; + flags |= LPASS8; + ioctl (tty, TIOCLSET, &flags); + } +#endif + } + +#ifdef TIOCGETC + { + struct tchars temp; + + ioctl (tty, TIOCGETC, &original_tchars); + bcopy (&original_tchars, &temp, sizeof (struct tchars)); + + /* Get rid of C-s and C-q. + We remember the value of startc (C-q) so that if the terminal is in + xoff state, the user can xon it by pressing that character. */ + xon_char = temp.t_startc; + temp.t_stopc = -1; + temp.t_startc = -1; + + /* If there is an XON character, bind it to restart the output. */ + if (xon_char != -1) + rl_bind_key (xon_char, rl_restart_output); + + /* If there is an EOF char, bind eof_char to it. */ + if (temp.t_eofc != -1) + eof_char = temp.t_eofc; + +#ifdef NEVER + /* Get rid of C-\ and C-c. */ + temp.t_intrc = temp.t_quitc = -1; +#endif + + ioctl (tty, TIOCSETC, &temp); + } +#endif /* TIOCGETC */ + +#ifdef TIOCGLTC + { + struct ltchars temp; + + ioctl (tty, TIOCGLTC, &original_ltchars); + bcopy (&original_ltchars, &temp, sizeof (struct ltchars)); + + /* Make the interrupt keys go away. Just enough to make people happy. */ + temp.t_dsuspc = -1; /* C-y */ + temp.t_lnextc = -1; /* C-v */ + + ioctl (tty, TIOCSLTC, &temp); + } +#endif /* TIOCGLTC */ + + the_ttybuff.sg_flags &= ~ECHO; + the_ttybuff.sg_flags |= CBREAK; + ioctl (tty, TIOCSETN, &the_ttybuff); +} + +/* Restore the terminal to its original state. */ +static +rl_deprep_terminal () +{ + int tty = fileno (rl_instream); + +#if defined (TIOCLGET) && defined (LPASS8) + ioctl (tty, TIOCLSET, &local_mode_flags); +#endif + +#ifdef TIOCSLTC + ioctl (tty, TIOCSLTC, &original_ltchars); +#endif + +#ifdef TIOCSETC + ioctl (tty, TIOCSETC, &original_tchars); +#endif + + the_ttybuff.sg_flags = original_tty_flags; + ioctl (tty, TIOCSETN, &the_ttybuff); + readline_echoing_p = 1; +} + +#else /* !defined (NEW_TTY_DRIVER) */ +static struct termio otio; + +static +rl_prep_terminal () +{ + int tty = fileno (rl_instream); + struct termio tio; + + ioctl (tty, TCGETA, &tio); + ioctl (tty, TCGETA, &otio); + + readline_echoing_p = (tio.c_lflag & ECHO); + + tio.c_lflag &= ~(ICANON|ECHO); + tio.c_iflag &= ~(IXON|ISTRIP|INPCK); + +#ifndef HANDLE_SIGNALS + tio.c_lflag &= ~ISIG; +#endif + + tio.c_cc[VEOF] = 1; /* really: MIN */ + tio.c_cc[VEOL] = 0; /* really: TIME */ + ioctl (tty, TCSETAW,&tio); +} + +static +rl_deprep_terminal () +{ + int tty = fileno (rl_instream); + ioctl (tty, TCSETAW, &otio); +} +#endif /* NEW_TTY_DRIVER */ + + +/* **************************************************************** */ +/* */ +/* Utility Functions */ +/* */ +/* **************************************************************** */ + +/* Return 0 if C is not a member of the class of characters that belong + in words, or 1 if it is. */ + +int allow_pathname_alphabetic_chars = 0; +char *pathname_alphabetic_chars = "/-_=~.#$"; + +int +alphabetic (c) + int c; +{ + char *rindex (); + if (pure_alphabetic (c) || (numeric (c))) + return (1); + + if (allow_pathname_alphabetic_chars) + return ((int)rindex (pathname_alphabetic_chars, c)); + else + return (0); +} + +/* Return non-zero if C is a numeric character. */ +int +numeric (c) + int c; +{ + return (c >= '0' && c <= '9'); +} + +/* Ring the terminal bell. */ +int +ding () +{ + if (readline_echoing_p) + { + fprintf (stderr, "\007"); + fflush (stderr); + } + return (-1); +} + +/* How to abort things. */ +rl_abort () +{ + ding (); + rl_clear_message (); + rl_init_argument (); + rl_pending_input = 0; + + defining_kbd_macro = 0; + while (executing_macro) + pop_executing_macro (); + + longjmp (readline_top_level, 1); +} + +/* Return a copy of the string between FROM and TO. + FROM is inclusive, TO is not. */ +char * +rl_copy (from, to) + int from, to; +{ + register int length; + char *copy; + + /* Fix it if the caller is confused. */ + if (from > to) { + int t = from; + from = to; + to = t; + } + + length = to - from; + copy = (char *)xmalloc (1 + length); + strncpy (copy, the_line + from, length); + copy[length] = '\0'; + return (copy); +} + + +/* **************************************************************** */ +/* */ +/* Insert and Delete */ +/* */ +/* **************************************************************** */ + + +/* Insert a string of text into the line at point. This is the only + way that you should do insertion. rl_insert () calls this + function. */ +rl_insert_text (string) + char *string; +{ + extern int doing_an_undo; + register int i, l = strlen (string); + while (rl_end + l >= rl_line_buffer_len) + { + rl_line_buffer = + (char *)xrealloc (rl_line_buffer, + rl_line_buffer_len += DEFAULT_BUFFER_SIZE); + the_line = rl_line_buffer; + } + + for (i = rl_end; i >= rl_point; i--) + the_line[i + l] = the_line[i]; + strncpy (the_line + rl_point, string, l); + + /* Remember how to undo this if we aren't undoing something. */ + if (!doing_an_undo) + { + /* If possible and desirable, concatenate the undos. */ + if ((strlen (string) == 1) && + rl_undo_list && + (rl_undo_list->what == UNDO_INSERT) && + (rl_undo_list->end == rl_point) && + (rl_undo_list->end - rl_undo_list->start < 20)) + rl_undo_list->end++; + else + rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL); + } + rl_point += l; + rl_end += l; + the_line[rl_end] = '\0'; +} + +/* Delete the string between FROM and TO. FROM is + inclusive, TO is not. */ +rl_delete_text (from, to) + int from, to; +{ + extern int doing_an_undo; + register char *text; + + /* Fix it if the caller is confused. */ + if (from > to) { + int t = from; + from = to; + to = t; + } + text = rl_copy (from, to); + strncpy (the_line + from, the_line + to, rl_end - to); + + /* Remember how to undo this delete. */ + if (!doing_an_undo) + rl_add_undo (UNDO_DELETE, from, to, text); + else + free (text); + + rl_end -= (to - from); + the_line[rl_end] = '\0'; +} + + +/* **************************************************************** */ +/* */ +/* Readline character functions */ +/* */ +/* **************************************************************** */ + +/* This is not a gap editor, just a stupid line input routine. No hair + is involved in writing any of the functions, and none should be. */ + +/* Note that: + + rl_end is the place in the string that we would place '\0'; + i.e., it is always safe to place '\0' there. + + rl_point is the place in the string where the cursor is. Sometimes + this is the same as rl_end. + + Any command that is called interactively receives two arguments. + The first is a count: the numeric arg pased to this command. + The second is the key which invoked this command. +*/ + + +/* **************************************************************** */ +/* */ +/* Movement Commands */ +/* */ +/* **************************************************************** */ + +/* Note that if you `optimize' the display for these functions, you cannot + use said functions in other functions which do not do optimizing display. + I.e., you will have to update the data base for rl_redisplay, and you + might as well let rl_redisplay do that job. */ + +/* Move forward COUNT characters. */ +rl_forward (count) + int count; +{ + if (count < 0) + rl_backward (-count); + else + while (count) + { +#ifdef VI_MODE + if (rl_point == (rl_end - (rl_editing_mode == vi_mode))) +#else + if (rl_point == rl_end) +#endif + { + ding (); + return; + } + else + rl_point++; + --count; + } +} + +/* Move backward COUNT characters. */ +rl_backward (count) + int count; +{ + if (count < 0) + rl_forward (-count); + else + while (count) + { + if (!rl_point) + { + ding (); + return; + } + else + --rl_point; + --count; + } +} + +/* Move to the beginning of the line. */ +rl_beg_of_line () +{ + rl_point = 0; +} + +/* Move to the end of the line. */ +rl_end_of_line () +{ + rl_point = rl_end; +} + +/* Move forward a word. We do what Emacs does. */ +rl_forward_word (count) + int count; +{ + int c; + + if (count < 0) + { + rl_backward_word (-count); + return; + } + + while (count) + { + if (rl_point == rl_end) + return; + + /* If we are not in a word, move forward until we are in one. + Then, move forward until we hit a non-alphabetic character. */ + c = the_line[rl_point]; + if (!alphabetic (c)) + { + while (++rl_point < rl_end) + { + c = the_line[rl_point]; + if (alphabetic (c)) break; + } + } + if (rl_point == rl_end) return; + while (++rl_point < rl_end) + { + c = the_line[rl_point]; + if (!alphabetic (c)) break; + } + --count; + } +} + +/* Move backward a word. We do what Emacs does. */ +rl_backward_word (count) + int count; +{ + int c; + + if (count < 0) + { + rl_forward_word (-count); + return; + } + + while (count) + { + if (!rl_point) + return; + + /* Like rl_forward_word (), except that we look at the characters + just before point. */ + + c = the_line[rl_point - 1]; + if (!alphabetic (c)) + { + while (--rl_point) + { + c = the_line[rl_point - 1]; + if (alphabetic (c)) break; + } + } + + while (rl_point) + { + c = the_line[rl_point - 1]; + if (!alphabetic (c)) + break; + else --rl_point; + } + --count; + } +} + +/* Clear the current line. Numeric argument to C-l does this. */ +rl_refresh_line () +{ + int curr_line = last_c_pos / screenwidth; + + move_vert(curr_line); + move_cursor_relative (0, the_line); /* XXX is this right */ + rl_forced_update_display (); + rl_display_fixed = 1; +} + +/* C-l typed to a line without quoting clears the screen, and then reprints + the prompt and the current input line. Given a numeric arg, redraw only + the current line. */ +rl_clear_screen () +{ + extern char *term_clrpag; + static void output_character_function (); + + if (rl_explicit_arg) + { + rl_refresh_line (); + return; + } + + if (term_clrpag) + tputs (term_clrpag, 1, output_character_function); + else + crlf (); + + rl_forced_update_display (); + rl_display_fixed = 1; +} + + +/* **************************************************************** */ +/* */ +/* Text commands */ +/* */ +/* **************************************************************** */ + +/* Insert the character C at the current location, moving point forward. */ +rl_insert (count, c) + int count, c; +{ + register int i; + char *string; + + if (count <= 0) + return; + + /* If we can optimize, then do it. But don't let people crash + readline because of extra large arguments. */ + if (count > 1 && count < 1024) + { + string = (char *)alloca (1 + count); + + for (i = 0; i < count; i++) + string[i] = c; + + string[i] = '\0'; + rl_insert_text (string); + return; + } + + if (count > 1024) + { + int descreaser; + + string = (char *)alloca (1024 + 1); + + for (i = 0; i < 1024; i++) + string[i] = c; + + while (count) + { + descreaser = (count > 1024 ? 1024 : count); + string[descreaser] = '\0'; + rl_insert_text (string); + count -= descreaser; + } + return; + } + + /* We are inserting a single character. + If there is pending input, then make a string of all of the + pending characters that are bound to rl_insert, and insert + them all. */ + if (any_typein) + { + int slen, key = 0, t; + + i = 0; + string = (char *)alloca (ibuffer_len + 1); + string[i++] = c; + + while ((t = rl_get_char (&key)) && + (keymap[key].type == ISFUNC && + keymap[key].function == rl_insert)) + string[i++] = key; + + if (t) + rl_unget_char (key); + + string[i] = '\0'; + rl_insert_text (string); + return; + } + else + { + /* Inserting a single character. */ + string = (char *)alloca (2); + + string[1] = '\0'; + string[0] = c; + rl_insert_text (string); + } +} + +/* Insert the next typed character verbatim. */ +rl_quoted_insert (count) + int count; +{ + int c = rl_read_key (in_stream); + rl_insert (count, c); +} + +/* Insert a tab character. */ +rl_tab_insert (count) + int count; +{ + rl_insert (count, '\t'); +} + +/* What to do when a NEWLINE is pressed. We accept the whole line. + KEY is the key that invoked this command. I guess it could have + meaning in the future. */ +rl_newline (count, key) + int count, key; +{ + + rl_done = 1; + +#ifdef VI_MODE + { + static int vi_doing_insert; + if (vi_doing_insert) + { + rl_end_undo_group (); + vi_doing_insert = 0; + } + } +#endif /* VI_MODE */ + + if (readline_echoing_p) + { + move_vert (vis_botlin); + vis_botlin = 0; + crlf (); + fflush (out_stream); + rl_display_fixed++; + } +} + +rl_clean_up_for_exit () +{ + if (readline_echoing_p) + { + move_vert (vis_botlin); + vis_botlin = 0; + fflush (out_stream); + rl_restart_output (); + } +} + +/* What to do for some uppercase characters, like meta characters, + and some characters appearing in emacs_ctlx_keymap. This function + is just a stub, you bind keys to it and the code in rl_dispatch () + is special cased. */ +rl_do_lowercase_version (ignore1, ignore2) + int ignore1, ignore2; +{ +} + +/* Rubout the character behind point. */ +rl_rubout (count) + int count; +{ + if (count < 0) + { + rl_delete (-count); + return; + } + + if (!rl_point) + { + ding (); + return; + } + + if (count > 1) + { + int orig_point = rl_point; + rl_backward (count); + rl_kill_text (orig_point, rl_point); + } + else + { + int c = the_line[--rl_point]; + rl_delete_text (rl_point, rl_point + 1); + + if (rl_point == rl_end && alphabetic (c) && last_c_pos) + { + backspace (1); + putc (' ', out_stream); + backspace (1); + last_c_pos--; + rl_display_fixed++; + } + } +} + +/* Delete the character under the cursor. Given a numeric argument, + kill that many characters instead. */ +rl_delete (count, invoking_key) + int count; +{ + if (count < 0) + { + rl_rubout (-count); + return; + } + + if (rl_point == rl_end) + { + ding (); + return; + } + + if (count > 1) + { + int orig_point = rl_point; + rl_forward (count); + rl_kill_text (orig_point, rl_point); + rl_point = orig_point; + } + else + rl_delete_text (rl_point, rl_point + 1); +} + + +/* **************************************************************** */ +/* */ +/* Kill commands */ +/* */ +/* **************************************************************** */ + +/* The next two functions mimic unix line editing behaviour, except they + save the deleted text on the kill ring. This is safer than not saving + it, and since we have a ring, nobody should get screwed. */ + +/* This does what C-w does in Unix. We can't prevent people from + using behaviour that they expect. */ +rl_unix_word_rubout () +{ + if (!rl_point) ding (); + else { + int orig_point = rl_point; + while (rl_point && whitespace (the_line[rl_point - 1])) + rl_point--; + while (rl_point && !whitespace (the_line[rl_point - 1])) + rl_point--; + rl_kill_text (rl_point, orig_point); + } +} + +/* Here is C-u doing what Unix does. You don't *have* to use these + key-bindings. We have a choice of killing the entire line, or + killing from where we are to the start of the line. We choose the + latter, because if you are a Unix weenie, then you haven't backspaced + into the line at all, and if you aren't, then you know what you are + doing. */ +rl_unix_line_discard () +{ + if (!rl_point) ding (); + else { + rl_kill_text (rl_point, 0); + rl_point = 0; + } +} + + + +/* **************************************************************** */ +/* */ +/* Commands For Typos */ +/* */ +/* **************************************************************** */ + +/* Random and interesting things in here. */ + + +/* **************************************************************** */ +/* */ +/* Changing Case */ +/* */ +/* **************************************************************** */ + +/* The three kinds of things that we know how to do. */ +#define UpCase 1 +#define DownCase 2 +#define CapCase 3 + +/* Uppercase the word at point. */ +rl_upcase_word (count) + int count; +{ + rl_change_case (count, UpCase); +} + +/* Lowercase the word at point. */ +rl_downcase_word (count) + int count; +{ + rl_change_case (count, DownCase); +} + +/* Upcase the first letter, downcase the rest. */ +rl_capitalize_word (count) + int count; +{ + rl_change_case (count, CapCase); +} + +/* The meaty function. + Change the case of COUNT words, performing OP on them. + OP is one of UpCase, DownCase, or CapCase. + If a negative argument is given, leave point where it started, + otherwise, leave it where it moves to. */ +rl_change_case (count, op) + int count, op; +{ + register int start = rl_point, end; + int state = 0; + + rl_forward_word (count); + end = rl_point; + + if (count < 0) + { + int temp = start; + start = end; + end = temp; + } + + /* We are going to modify some text, so let's prepare to undo it. */ + rl_modifying (start, end); + + for (; start < end; start++) + { + switch (op) + { + case UpCase: + the_line[start] = to_upper (the_line[start]); + break; + + case DownCase: + the_line[start] = to_lower (the_line[start]); + break; + + case CapCase: + if (state == 0) + { + the_line[start] = to_upper (the_line[start]); + state = 1; + } + else + { + the_line[start] = to_lower (the_line[start]); + } + if (!pure_alphabetic (the_line[start])) + state = 0; + break; + + default: + abort (); + } + } + rl_point = end; +} + +/* **************************************************************** */ +/* */ +/* Transposition */ +/* */ +/* **************************************************************** */ + +/* Transpose the words at point. */ +rl_transpose_words (count) + int count; +{ + char *word1, *word2; + int w1_beg, w1_end, w2_beg, w2_end; + int orig_point = rl_point; + + if (!count) return; + + /* Find the two words. */ + rl_forward_word (count); + w2_end = rl_point; + rl_backward_word (1); + w2_beg = rl_point; + rl_backward_word (count); + w1_beg = rl_point; + rl_forward_word (1); + w1_end = rl_point; + + /* Do some check to make sure that there really are two words. */ + if ((w1_beg == w2_beg) || (w2_beg < w1_end)) + { + ding (); + rl_point = orig_point; + return; + } + + /* Get the text of the words. */ + word1 = rl_copy (w1_beg, w1_end); + word2 = rl_copy (w2_beg, w2_end); + + /* We are about to do many insertions and deletions. Remember them + as one operation. */ + rl_begin_undo_group (); + + /* Do the stuff at word2 first, so that we don't have to worry + about word1 moving. */ + rl_point = w2_beg; + rl_delete_text (w2_beg, w2_end); + rl_insert_text (word1); + + rl_point = w1_beg; + rl_delete_text (w1_beg, w1_end); + rl_insert_text (word2); + + /* This is exactly correct since the text before this point has not + changed in length. */ + rl_point = w2_end; + + /* I think that does it. */ + rl_end_undo_group (); + free (word1); free (word2); +} + +/* Transpose the characters at point. If point is at the end of the line, + then transpose the characters before point. */ +rl_transpose_chars (count) + int count; +{ + if (!count) + return; + + if (!rl_point || rl_end < 2) { + ding (); + return; + } + + while (count) { + if (rl_point == rl_end) { + int t = the_line[rl_point - 1]; + the_line[rl_point - 1] = the_line[rl_point - 2]; + the_line[rl_point - 2] = t; + } else { + int t = the_line[rl_point]; + the_line[rl_point] = the_line[rl_point - 1]; + the_line[rl_point - 1] = t; + if (count < 0 && rl_point) + rl_point--; + else + rl_point++; + } + if (count < 0) + count++; + else + count--; + } +} + + +/* **************************************************************** */ +/* */ +/* Bogus Flow Control */ +/* */ +/* **************************************************************** */ + +rl_restart_output (count, key) + int count, key; +{ + int fildes = fileno (stdin); +#ifdef TIOCSTART + ioctl (fildes, TIOCSTART, 0); +#endif /* TIOCSTART */ +} + +/* **************************************************************** */ +/* */ +/* Completion matching, from readline's point of view. */ +/* */ +/* **************************************************************** */ + +/* Pointer to the generator function for completion_matches (). + NULL means to use filename_entry_function (), the default filename + completer. */ +Function *rl_completion_entry_function = (Function *)NULL; + +/* 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. */ +Function *rl_attempted_completion_function = (Function *)NULL; + +/* Complete the word at or before point. You have supplied the function + that does the initial simple matching selection algorithm (see + completion_matches ()). The default is to do filename completion. */ +rl_complete (ignore, invoking_key) + int ignore, invoking_key; +{ + rl_complete_internal (TAB); + if (running_in_emacs) + printf ("%s", the_line); +} + +/* List the possible completions. See description of rl_complete (). */ +rl_possible_completions () +{ + rl_complete_internal ('?'); +} + +/* The user must press "y" or "n". Non-zero return means "y" pressed. */ +get_y_or_n () +{ + int c; + loop: + c = rl_read_key (in_stream); + if (c == 'y' || c == 'Y') return (1); + if (c == 'n' || c == 'N') return (0); + if (c == ABORT_CHAR) rl_abort (); + ding (); goto loop; +} + +/* Up to this many items will be displayed in response to a + possible-completions call. After that, we ask the user if + she is sure she wants to see them all. */ +int rl_completion_query_items = 100; + +/* 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. " \t\n\"\\'`@$><=" */ +char *rl_basic_word_break_characters = " \t\n\"\\'`@$><="; + +/* 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. */ +char *rl_completer_word_break_characters = (char *)NULL; + +/* 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. */ +char *rl_special_prefixes = (char *)NULL; + +/* If non-zero, then disallow duplicates in the matches. */ +int rl_ignore_completion_duplicates = 1; + +/* Non-zero means that the results of the matches are to be treated + as filenames. This is ALWAYS zero on entry, and can only be changed + within a completion entry finder function. */ +int rl_filename_completion_desired = 0; + +/* Complete the word at or before point. + WHAT_TO_DO says what to do with the completion. + `?' means list the possible completions. + TAB means do standard completion. + `*' means insert all of the possible completions. */ +rl_complete_internal (what_to_do) + int what_to_do; +{ + char *filename_completion_function (); + char **completion_matches (), **matches; + Function *our_func; + int start, end, delimiter = 0; + char *text; + + if (rl_completion_entry_function) + our_func = rl_completion_entry_function; + else + our_func = (int (*)())filename_completion_function; + + /* Only the completion entry function can change this. */ + rl_filename_completion_desired = 0; + + /* We now look backwards for the start of a filename/variable word. */ + end = rl_point; + if (rl_point) + { + while (--rl_point && + !rindex (rl_completer_word_break_characters, the_line[rl_point])); + + /* If we are at a word break, then advance past it. */ + if (rindex (rl_completer_word_break_characters, (the_line[rl_point]))) + { + /* If the character that caused the word break was a quoting + character, then remember it as the delimiter. */ + if (rindex ("\"'", the_line[rl_point]) && (end - rl_point) > 1) + delimiter = the_line[rl_point]; + + /* If the character isn't needed to determine something special + about what kind of completion to perform, then advance past it. */ + + if (!rl_special_prefixes || + !rindex (rl_special_prefixes, the_line[rl_point])) + rl_point++; + } + } + + start = rl_point; + rl_point = end; + text = rl_copy (start, end); + + /* If the user wants to TRY to complete, but then wants to give + up and use the default completion function, they set the + variable rl_attempted_completion_function. */ + if (rl_attempted_completion_function) + { + matches = + (char **)(*rl_attempted_completion_function) (text, start, end); + + if (matches) + goto after_usual_completion; + } + + matches = completion_matches (text, our_func, start, end); + + after_usual_completion: + free (text); + + if (!matches) + ding (); + else + { + register int i; + + some_matches: + + /* It seems to me that in all the cases we handle we would like + to ignore duplicate possiblilities. Scan for the text to + insert being identical to the other completions. */ + if (rl_ignore_completion_duplicates) + { + char *lowest_common; + int compare_strings (), j, newlen = 0; + + /* Sort the items. */ + /* It is safe to sort this array, because the lowest common + denominator found in matches[0] will remain in place. */ + for (i = 0; matches[i]; i++); + qsort (matches, i, sizeof (char *), compare_strings); + + /* Remember the lowest common denimator for it may be unique. */ + lowest_common = savestring (matches[0]); + + for (i = 0; matches[i + 1]; i++) + { + if (strcmp (matches[i], matches[i + 1]) == 0) + { + free (matches[i]); + matches[i] = (char *)-1; + } + else + newlen++; + } + + /* We have marked all the dead slots with (char *)-1. + Copy all the non-dead entries into a new array. */ + { + char **temp_array = + (char **)malloc ((3 + newlen) * sizeof (char *)); + + for (i = 1, j = 1; matches[i]; i++) + if (matches[i] != (char *)-1) + temp_array[j++] = matches[i]; + temp_array[j] = (char *)NULL; + + if (matches[0] != (char *)-1) + free (matches[0]); + free (matches); + + matches = temp_array; + } + + /* Place the lowest common denominator back in [0]. */ + matches[0] = lowest_common; + + /* If there is one string left, and it is identical to the + lowest common denominator, then the LCD is the string to + insert. */ + if (j == 2 && strcmp (matches[0], matches[1]) == 0) + { + free (matches[1]); + matches[1] = (char *)NULL; + } + } + + switch (what_to_do) + { + case TAB: + rl_delete_text (start, rl_point); + rl_point = start; + rl_insert_text (matches[0]); + + /* If there are more matches, ring the bell to indicate. + If this was the only match, and we are hacking files, + check the file to see if it was a directory. If so, + add a '/' to the name. If not, and we are at the end + of the line, then add a space. */ + if (matches[1]) + { + ding (); /* There are other matches remaining. */ + } + else + { + char temp_string[2]; + + temp_string[0] = delimiter ? delimiter : ' '; + temp_string[1] = '\0'; + + if (rl_filename_completion_desired) + { + struct stat finfo; + char *tilde_expand (); + char *filename = tilde_expand (matches[0]); + + if ((stat (filename, &finfo) == 0) && + ((finfo.st_mode & S_IFMT) == S_IFDIR)) + { + if (the_line[rl_point] != '/') + rl_insert_text ("/"); + } + else + { + if (rl_point == rl_end) + rl_insert_text (temp_string); + } + free (filename); + } + else + { + if (rl_point == rl_end) + rl_insert_text (temp_string); + } + } + break; + + case '*': + { + int i = 1; + + rl_delete_text (start, rl_point); + rl_point = start; + rl_begin_undo_group (); + if (matches[1]) + { + while (matches[i]) + { + rl_insert_text (matches[i++]); + rl_insert_text (" "); + } + } + else + { + rl_insert_text (matches[0]); + rl_insert_text (" "); + } + rl_end_undo_group (); + } + break; + + + case '?': + { + int len, count, limit, max = 0; + int j, k, l; + + /* Handle simple case first. What if there is only one answer? */ + if (!matches[1]) + { + char *rindex (), *temp; + + if (rl_filename_completion_desired) + temp = rindex (matches[0], '/'); + else + temp = (char *)NULL; + + if (!temp) + temp = matches[0]; + else + temp++; + + crlf (); + fprintf (out_stream, "%s", temp); + crlf (); + goto restart; + } + + /* There is more than one answer. Find out how many there are, + and find out what the maximum printed length of a single entry + is. */ + for (i = 1; matches[i]; i++) + { + char *rindex (), *temp = (char *)NULL; + + /* If we are hacking filenames, then only count the characters + after the last slash in the pathname. */ + if (rl_filename_completion_desired) + temp = rindex (matches[i], '/'); + else + temp = (char *)NULL; + + if (!temp) + temp = matches[i]; + else + temp++; + + if (strlen (temp) > max) + max = strlen (temp); + } + + len = i; + + /* If there are many items, then ask the user if she + really wants to see them all. */ + if (len >= rl_completion_query_items) + { + crlf (); + fprintf (out_stream, + "There are %d possibilities. Do you really", len); + crlf (); + fprintf (out_stream, "wish to see them all? (y or n)"); + fflush (out_stream); + if (!get_y_or_n ()) + { + crlf (); + goto restart; + } + } + /* How many items of MAX length can we fit in the screen window? */ + max += 2; + limit = screenwidth / max; + if (limit != 1 && (limit * max == screenwidth)) + limit--; + + /* How many iterations of the printing loop? */ + count = (len + (limit - 1)) / limit; + + /* Watch out for special case. If LEN is less than LIMIT, then + just do the inner printing loop. */ + if (len < limit) count = 1; + + /* Sort the items if they are not already sorted. */ + if (!rl_ignore_completion_duplicates) + { + int compare_strings (); + qsort (matches, len, sizeof (char *), compare_strings); + } + + /* Print the sorted items, up-and-down alphabetically, like + ls might. */ + crlf (); + + for (i = 1; i < count + 1; i++) + { + for (j = 0, l = i; j < limit; j++) + { + if (l > len || !matches[l]) + { + break; + } + else + { + char *rindex (), *temp = (char *)NULL; + + if (rl_filename_completion_desired) + temp = rindex (matches[l], '/'); + else + temp = (char *)NULL; + + if (!temp) + temp = matches[l]; + else + temp++; + + fprintf (out_stream, "%s", temp); + for (k = 0; k < max - strlen (temp); k++) + putc (' ', out_stream); + } + l += count; + } + crlf (); + } + restart: + + rl_on_new_line (); + } + break; + + default: + abort (); + } + + for (i = 0; matches[i]; i++) + free (matches[i]); + free (matches); + } +} + +/* Stupid comparison routine for qsort () ing strings. */ +static int +compare_strings (s1, s2) + char **s1, **s2; +{ + return (strcmp (*s1, *s2)); +} + +/* A completion function for usernames. + TEXT contains a partial username preceded by a random + character (usually `~'). */ +char * +username_completion_function (text, state) + int state; + char *text; +{ + static char *username = (char *)NULL; + static struct passwd *entry; + static int namelen; + + if (!state) + { + if (username) + free (username); + username = savestring (&text[1]); + namelen = strlen (username); + setpwent (); + } + + while (entry = getpwent ()) + { + if (strncmp (username, entry->pw_name, namelen) == 0) + break; + } + + if (!entry) + { + endpwent (); + return ((char *)NULL); + } + else + { + char *value = (char *)xmalloc (2 + strlen (entry->pw_name)); + *value = *text; + strcpy (value + 1, entry->pw_name); + rl_filename_completion_desired = 1; + return (value); + } +} + +/* 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. */ +Function *rl_tilde_expander = (Function *)NULL; + +/* Expand FILENAME if it begins with a tilde. This always returns + a new string. */ +char * +tilde_expand (filename) + char *filename; +{ + char *dirname = filename ? savestring (filename) : (char *)NULL; + + if (dirname && *dirname == '~') + { + char *temp_name; + if (!dirname[1] || dirname[1] == '/') + { + /* Prepend $HOME to the rest of the string. */ + char *temp_home = (char *)getenv ("HOME"); + + temp_name = (char *)alloca (1 + strlen (&dirname[1]) + + (temp_home? strlen (temp_home) : 0)); + temp_name[0] = '\0'; + if (temp_home) + strcpy (temp_name, temp_home); + strcat (temp_name, &dirname[1]); + free (dirname); + dirname = savestring (temp_name); + } + else + { + struct passwd *getpwnam (), *user_entry; + char *username = (char *)alloca (257); + int i, c; + + for (i = 1; c = dirname[i]; i++) + { + if (c == '/') break; + else username[i - 1] = c; + } + username[i - 1] = '\0'; + + if (!(user_entry = getpwnam (username))) + { + /* If the calling program has a special syntax for + expanding tildes, and we couldn't find a standard + expansion, then let them try. */ + if (rl_tilde_expander) + { + char *expansion; + + expansion = (char *)(*rl_tilde_expander) (username); + + if (expansion) + { + temp_name = (char *)alloca (1 + strlen (expansion) + + strlen (&dirname[i])); + strcpy (temp_name, expansion); + strcat (temp_name, &dirname[i]); + free (expansion); + goto return_name; + } + } + /* + * We shouldn't report errors. + */ + } + else + { + temp_name = (char *)alloca (1 + strlen (user_entry->pw_dir) + + strlen (&dirname[i])); + strcpy (temp_name, user_entry->pw_dir); + strcat (temp_name, &dirname[i]); + return_name: + free (dirname); + dirname = savestring (temp_name); + } + } + } + return (dirname); +} + + +/* **************************************************************** */ +/* */ +/* Undo, and Undoing */ +/* */ +/* **************************************************************** */ + +/* Non-zero tells rl_delete_text and rl_insert_text to not add to + the undo list. */ +int doing_an_undo = 0; + +/* The current undo list for THE_LINE. */ +UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL; + +/* Remember how to undo something. Concatenate some undos if that + seems right. */ +rl_add_undo (what, start, end, text) + enum undo_code what; + int start, end; + char *text; +{ + UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST)); + temp->what = what; + temp->start = start; + temp->end = end; + temp->text = text; + temp->next = rl_undo_list; + rl_undo_list = temp; +} + +/* Free the existing undo list. */ +free_undo_list () +{ + while (rl_undo_list) { + UNDO_LIST *release = rl_undo_list; + rl_undo_list = rl_undo_list->next; + + if (release->what == UNDO_DELETE) + free (release->text); + + free (release); + } +} + +/* Undo the next thing in the list. Return 0 if there + is nothing to undo, or non-zero if there was. */ +int +rl_do_undo () +{ + UNDO_LIST *release; + int waiting_for_begin = 0; + +undo_thing: + if (!rl_undo_list) + return (0); + + doing_an_undo = 1; + + switch (rl_undo_list->what) { + + /* Undoing deletes means inserting some text. */ + case UNDO_DELETE: + rl_point = rl_undo_list->start; + rl_insert_text (rl_undo_list->text); + free (rl_undo_list->text); + break; + + /* Undoing inserts means deleting some text. */ + case UNDO_INSERT: + rl_delete_text (rl_undo_list->start, rl_undo_list->end); + rl_point = rl_undo_list->start; + break; + + /* Undoing an END means undoing everything 'til we get to + a BEGIN. */ + case UNDO_END: + waiting_for_begin++; + break; + + /* Undoing a BEGIN means that we are done with this group. */ + case UNDO_BEGIN: + if (waiting_for_begin) + waiting_for_begin--; + else + abort (); + break; + } + + doing_an_undo = 0; + + release = rl_undo_list; + rl_undo_list = rl_undo_list->next; + free (release); + + if (waiting_for_begin) + goto undo_thing; + + return (1); +} + +/* Begin a group. Subsequent undos are undone as an atomic operation. */ +rl_begin_undo_group () +{ + rl_add_undo (UNDO_BEGIN, 0, 0, 0); +} + +/* End an undo group started with rl_begin_undo_group (). */ +rl_end_undo_group () +{ + rl_add_undo (UNDO_END, 0, 0, 0); +} + +/* Save an undo entry for the text from START to END. */ +rl_modifying (start, end) + int start, end; +{ + if (start > end) + { + int t = start; + start = end; + end = t; + } + + if (start != end) + { + char *temp = rl_copy (start, end); + rl_begin_undo_group (); + rl_add_undo (UNDO_DELETE, start, end, temp); + rl_add_undo (UNDO_INSERT, start, end, (char *)NULL); + rl_end_undo_group (); + } +} + +/* Revert the current line to its previous state. */ +rl_revert_line () +{ + if (!rl_undo_list) ding (); + else { + while (rl_undo_list) + rl_do_undo (); + } +} + +/* Do some undoing of things that were done. */ +rl_undo_command (count) +{ + if (count < 0) return; /* Nothing to do. */ + + while (count) + { + if (rl_do_undo ()) + { + count--; + } + else + { + ding (); + break; + } + } +} + +/* **************************************************************** */ +/* */ +/* History Utilities */ +/* */ +/* **************************************************************** */ + +/* We already have a history library, and that is what we use to control + the history features of readline. However, this is our local interface + to the history mechanism. */ + +/* While we are editing the history, this is the saved + version of the original line. */ +HIST_ENTRY *saved_line_for_history = (HIST_ENTRY *)NULL; + +/* Set the history pointer back to the last entry in the history. */ +start_using_history () +{ + using_history (); + if (saved_line_for_history) + free_history_entry (saved_line_for_history); + + saved_line_for_history = (HIST_ENTRY *)NULL; +} + +/* Free the contents (and containing structure) of a HIST_ENTRY. */ +free_history_entry (entry) + HIST_ENTRY *entry; +{ + if (!entry) return; + if (entry->line) + free (entry->line); + free (entry); +} + +/* Perhaps put back the current line if it has changed. */ +maybe_replace_line () +{ + HIST_ENTRY *temp = current_history (); + + /* If the current line has changed, save the changes. */ + if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list)) { + temp = replace_history_entry (where_history (), the_line, rl_undo_list); + free (temp->line); + free (temp); + } +} + +/* Put back the saved_line_for_history if there is one. */ +maybe_unsave_line () +{ + if (saved_line_for_history) { + strcpy (the_line, saved_line_for_history->line); + rl_undo_list = (UNDO_LIST *)saved_line_for_history->data; + free_history_entry (saved_line_for_history); + saved_line_for_history = (HIST_ENTRY *)NULL; + rl_end = rl_point = strlen (the_line); + } else { + ding (); + } +} + +/* Save the current line in saved_line_for_history. */ +maybe_save_line () +{ + if (!saved_line_for_history) { + saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); + saved_line_for_history->line = savestring (the_line); + saved_line_for_history->data = (char *)rl_undo_list; + } +} + + + +/* **************************************************************** */ +/* */ +/* History Commands */ +/* */ +/* **************************************************************** */ + +/* Meta-< goes to the start of the history. */ +rl_beginning_of_history () +{ + rl_get_previous_history (1 + where_history ()); +} + +/* Meta-> goes to the end of the history. (The current line). */ +rl_end_of_history () +{ + maybe_replace_line (); + using_history (); + maybe_unsave_line (); +} + +/* Move down to the next history line. */ +rl_get_next_history (count) + int count; +{ + HIST_ENTRY *temp = (HIST_ENTRY *)NULL; + + if (count < 0) + { + rl_get_previous_history (-count); + return; + } + + if (!count) + return; + + maybe_replace_line (); + + while (count) + { + temp = next_history (); + if (!temp) + break; + --count; + } + + if (!temp) + maybe_unsave_line (); + else + { + strcpy (the_line, temp->line); + rl_undo_list = (UNDO_LIST *)temp->data; + rl_end = rl_point = strlen (the_line); + } +} + +/* Get the previous item out of our interactive history, making it the current + line. If there is no previous history, just ding. */ +rl_get_previous_history (count) + int count; +{ + HIST_ENTRY *old_temp = (HIST_ENTRY *)NULL; + HIST_ENTRY *temp = (HIST_ENTRY *)NULL; + + if (count < 0) + { + rl_get_next_history (-count); + return; + } + + if (!count) + return; + + /* If we don't have a line saved, then save this one. */ + maybe_save_line (); + + /* If the current line has changed, save the changes. */ + maybe_replace_line (); + + while (count) + { + temp = previous_history (); + if (!temp) + break; + else + old_temp = temp; + --count; + } + + /* If there was a large argument, and we moved back to the start of the + history, that is not an error. So use the last value found. */ + if (!temp && old_temp) + temp = old_temp; + + if (!temp) + ding (); + else + { + strcpy (the_line, temp->line); + rl_undo_list = (UNDO_LIST *)temp->data; + rl_end = rl_point = strlen (the_line); +#ifdef VI_MODE + if (rl_editing_mode == vi_mode) + rl_point = 0; +#endif /* VI_MODE */ + } +} + +/* There is a command in ksh which yanks into this line, the last word + of the previous line. Here it is. We left it on M-. */ +rl_yank_previous_last_arg (ignore) + int ignore; +{ +} + + + +/* **************************************************************** */ +/* */ +/* I-Search and Searching */ +/* */ +/* **************************************************************** */ + +/* Search backwards through the history looking for a string which is typed + interactively. Start with the current line. */ +rl_reverse_search_history (sign, key) + int sign; + int key; +{ + rl_search_history (-sign, key); +} + +/* Search forwards through the history looking for a string which is typed + interactively. Start with the current line. */ +rl_forward_search_history (sign, key) + int sign; + int key; +{ + rl_search_history (sign, key); +} + +/* Display the current state of the search in the echo-area. + SEARCH_STRING contains the string that is being searched for, + DIRECTION is zero for forward, or 1 for reverse, + WHERE is the history list number of the current line. If it is + -1, then this line is the starting one. */ +rl_display_search (search_string, reverse_p, where) + char *search_string; + int reverse_p, where; +{ + char *message = (char *)NULL; + + message = + (char *)alloca (1 + (search_string ? strlen (search_string) : 0) + 30); + + *message = '\0'; + +#ifdef NEVER + if (where != -1) + sprintf (message, "[%d]", where + history_base); +#endif + + strcat (message, "("); + + if (reverse_p) + strcat (message, "reverse-"); + + strcat (message, "i-search)`"); + + if (search_string) + strcat (message, search_string); + + strcat (message, "': "); + rl_message (message, 0, 0); + rl_redisplay (); +} + +/* Search through the history looking for an interactively typed string. + This is analogous to i-search. We start the search in the current line. + DIRECTION is which direction to search; > 0 means forward, < 0 means + backwards. */ +rl_search_history (direction, invoking_key) + int direction; + int invoking_key; +{ + /* The string that the user types in to search for. */ + char *search_string = (char *)alloca (128); + + /* The current length of SEARCH_STRING. */ + int search_string_index; + + /* The list of lines to search through. */ + char **lines; + + /* The length of LINES. */ + int hlen; + + /* Where we get LINES from. */ + HIST_ENTRY **hlist = history_list (); + + int orig_point = rl_point; + int orig_line = where_history (); + int last_found_line = orig_line; + int c, done = 0; + register int i = 0; + + + /* The line currently being searched. */ + char *sline; + + /* Offset in that line. */ + int index; + + /* Non-zero if we are doing a reverse search. */ + int reverse = (direction < 0); + + /* Create an arrary of pointers to the lines that we want to search. */ + + maybe_replace_line (); + if (hlist) + for (i = 0; hlist[i]; i++); + + /* Allocate space for this many lines, +1 for the current input line, + and remember those lines. */ + lines = (char **)alloca ((1 + (hlen = i)) * sizeof (char *)); + for (i = 0; i < hlen; i++) + lines[i] = hlist[i]->line; + + if (saved_line_for_history) + lines[i] = saved_line_for_history->line; + else + { + /* So I have to type it in this way instead. */ + lines[i] = (char *)alloca (1 + strlen (the_line)); + strcpy (lines[i], &the_line[0]); + } + + hlen++; + + /* The line where we start the search. */ + i = orig_line; + + /* Initialize search parameters. */ + *search_string = '\0'; + search_string_index = 0; + + rl_display_search (search_string, reverse, -1); + + sline = the_line; + index = rl_point; + + while (!done) + { + c = rl_read_key (in_stream); + + /* Hack C to Do What I Mean. */ + { + Function *f = (Function *)NULL; + + if (keymap[c].type == ISFUNC) + f = keymap[c].function; + + if (f == rl_reverse_search_history) + c = reverse ? -1 : -2; + else if (f == rl_forward_search_history) + c = !reverse ? -1 : -2; + } + + switch (c) + { + case ESC: + done = 1; + continue; + + /* case invoking_key: */ + case -1: + goto search_again; + + /* switch directions */ + case -2: + direction = -direction; + reverse = (direction < 0); + + goto do_search; + + case CTRL ('G'): + strcpy (the_line, lines[orig_line]); + rl_point = orig_point; + rl_end = strlen (the_line); + rl_clear_message (); + return; + + default: + if (c < 32 || c > 126) + { + rl_execute_next (c); + done = 1; + continue; + } + else + { + search_string[search_string_index++] = c; + search_string[search_string_index] = '\0'; + goto do_search; + + search_again: + + if (!search_string_index) + continue; + else + { + if (reverse) + --index; + else + if (index != strlen (sline)) + ++index; + else + ding (); + } + do_search: + + while (1) + { + if (reverse) + { + while (index >= 0) + if (strncmp + (search_string, + sline + index, + search_string_index) == 0) + goto string_found; + else + index--; + } + else + { + register int limit = + (strlen (sline) - search_string_index) + 1; + + while (index < limit) + { + if (strncmp (search_string, + sline + index, + search_string_index) == 0) + goto string_found; + index++; + } + } + + next_line: + i += direction; + + /* At limit for direction? */ + if ((reverse && i < 0) || + (!reverse && i == hlen)) + goto search_failed; + + sline = lines[i]; + if (reverse) + index = strlen (sline); + else + index = 0; + + /* If the search string is longer than the current + line, no match. */ + if (search_string_index > strlen (sline)) + goto next_line; + + /* Start actually searching. */ + if (reverse) + index -= search_string_index; + } + + search_failed: + /* We cannot find the search string. Ding the bell. */ + ding (); + i = last_found_line; + break; + + string_found: + /* We have found the search string. Just display it. But don't + actually move there in the history list until the user accepts + the location. */ + strcpy (the_line, lines[i]); + rl_point = index; + rl_end = strlen (the_line); + last_found_line = i; + rl_display_search (search_string, reverse, + (i == orig_line) ? -1 : i); + } + } + continue; + } + /* The user has won. They found the string that they wanted. Now all + we have to do is place them there. */ + { + int now = last_found_line; + + /* First put back the original state. */ + strcpy (the_line, lines[orig_line]); + + if (now < orig_line) + rl_get_previous_history (orig_line - now); + else + rl_get_next_history (now - orig_line); + + rl_point = index; + rl_clear_message (); + } +} + +/* Make C be the next command to be executed. */ +rl_execute_next (c) + int c; +{ + rl_pending_input = c; +} + +/* **************************************************************** */ +/* */ +/* Killing Mechanism */ +/* */ +/* **************************************************************** */ + +/* What we assume for a max number of kills. */ +#define DEFAULT_MAX_KILLS 10 + +/* The real variable to look at to find out when to flush kills. */ +int rl_max_kills = DEFAULT_MAX_KILLS; + +/* Where to store killed text. */ +char **rl_kill_ring = (char **)NULL; + +/* Where we are in the kill ring. */ +int rl_kill_index = 0; + +/* How many slots we have in the kill ring. */ +int rl_kill_ring_length = 0; + +/* How to say that you only want to save a certain amount + of kill material. */ +rl_set_retained_kills (num) + int num; +{} + +/* The way to kill something. This appends or prepends to the last + kill, if the last command was a kill command. if FROM is less + than TO, then the text is appended, otherwise prepended. If the + last command was not a kill command, then a new slot is made for + this kill. */ +rl_kill_text (from, to) + int from, to; +{ + int slot; + char *text = rl_copy (from, to); + + /* Is there anything to kill? */ + if (from == to) { + free (text); + last_command_was_kill++; + return; + } + + /* Delete the copied text from the line. */ + rl_delete_text (from, to); + + /* First, find the slot to work with. */ + if (!last_command_was_kill) { + + /* Get a new slot. */ + if (!rl_kill_ring) { + + /* If we don't have any defined, then make one. */ + rl_kill_ring = + (char **)xmalloc (((rl_kill_ring_length = 1) + 1) * sizeof (char *)); + slot = 1; + + } else { + + /* We have to add a new slot on the end, unless we have exceeded + the max limit for remembering kills. */ + slot = rl_kill_ring_length; + if (slot == rl_max_kills) { + register int i; + free (rl_kill_ring[0]); + for (i = 0; i < slot; i++) + rl_kill_ring[i] = rl_kill_ring[i + 1]; + } else { + rl_kill_ring = + (char **)xrealloc (rl_kill_ring, + ((slot = (rl_kill_ring_length += 1)) + 1) + * sizeof (char *)); + } + } + slot--; + } else { + slot = rl_kill_ring_length - 1; + } + + /* If the last command was a kill, prepend or append. */ + if (last_command_was_kill) { + char *old = rl_kill_ring[slot]; + char *new = (char *)xmalloc (1 + strlen (old) + strlen (text)); + + if (from < to) { + strcpy (new, old); + strcat (new, text); + } else { + strcpy (new, text); + strcat (new, old); + } + free (old); + free (text); + rl_kill_ring[slot] = new; + } else { + rl_kill_ring[slot] = text; + } + rl_kill_index = slot; + last_command_was_kill++; +} + +/* Now REMEMBER! In order to do prepending or appending correctly, kill + commands always make rl_point's original position be the FROM argument, + and rl_point's extent be the TO argument. */ + + +/* **************************************************************** */ +/* */ +/* Killing Commands */ +/* */ +/* **************************************************************** */ + +/* Delete the word at point, saving the text in the kill ring. */ +rl_kill_word (count) + int count; +{ + int orig_point = rl_point; + + if (count < 0) + rl_backward_kill_word (-count); + else + { + rl_forward_word (count); + + if (rl_point != orig_point) + rl_kill_text (orig_point, rl_point); + + rl_point = orig_point; + } +} + +/* Rubout the word before point, placing it on the kill ring. */ +rl_backward_kill_word (count) + int count; +{ + int orig_point = rl_point; + + if (count < 0) + rl_kill_word (-count); + else + { + rl_backward_word (count); + + if (rl_point != orig_point) + rl_kill_text (orig_point, rl_point); + } +} + +/* Kill from here to the end of the line. If DIRECTION is negative, kill + back to the line start instead. */ +rl_kill_line (direction) + int direction; +{ + int orig_point = rl_point; + + if (direction < 0) + rl_backward_kill_line (1); + else + { + rl_end_of_line (); + if (orig_point != rl_point) + rl_kill_text (orig_point, rl_point); + rl_point = orig_point; + } +} + +/* Kill backwards to the start of the line. If DIRECTION is negative, kill + forwards to the line end instead. */ +rl_backward_kill_line (direction) + int direction; +{ + int orig_point = rl_point; + + if (direction < 0) + rl_kill_line (1); + else + { + if (!rl_point) + ding (); + else + { + rl_beg_of_line (); + rl_kill_text (orig_point, rl_point); + } + } +} + +/* Yank back the last killed text. This ignores arguments. */ +rl_yank () +{ + if (!rl_kill_ring) rl_abort (); + rl_insert_text (rl_kill_ring[rl_kill_index]); +} + +/* If the last command was yank, or yank_pop, and the text just + before point is identical to the current kill item, then + delete that text from the line, rotate the index down, and + yank back some other text. */ +rl_yank_pop () +{ + int l; + + if (((rl_last_func != rl_yank_pop) && (rl_last_func != rl_yank)) || + !rl_kill_ring) + { + rl_abort (); + } + + l = strlen (rl_kill_ring[rl_kill_index]); + if (((rl_point - l) >= 0) && + (strncmp (the_line + (rl_point - l), + rl_kill_ring[rl_kill_index], l) == 0)) + { + rl_delete_text ((rl_point - l), rl_point); + rl_point -= l; + rl_kill_index--; + if (rl_kill_index < 0) + rl_kill_index = rl_kill_ring_length - 1; + rl_yank (); + } + else + rl_abort (); + +} + +/* Yank the COUNTth argument from the previous history line. */ +rl_yank_nth_arg (count, ignore) + int count; +{ + register HIST_ENTRY *entry = previous_history (); + char *arg; + + if (entry) + next_history (); + else + { + ding (); + return; + } + + arg = history_arg_extract (count, count, entry->line); + if (!arg || !*arg) + { + ding (); + return; + } + + rl_begin_undo_group (); + if (rl_point && the_line[rl_point - 1] != ' ') + rl_insert_text (" "); + rl_insert_text (arg); + free (arg); + rl_end_undo_group (); +} + +/* Vi Mode. */ +#ifdef VI_MODE +#include "vi_mode.c" +#endif /* VI_MODE */ + +/* How to toggle back and forth between editing modes. */ +rl_vi_editing_mode () +{ +#ifdef VI_MODE + rl_editing_mode = vi_mode; + rl_vi_insertion_mode (); +#endif /* VI_MODE */ +} + +rl_emacs_editing_mode () +{ + rl_editing_mode = emacs_mode; + keymap = emacs_standard_keymap; +} + + +/* **************************************************************** */ +/* */ +/* Completion */ +/* */ +/* **************************************************************** */ + +/* Non-zero means that case is not significant in completion. */ +int completion_case_fold = 0; + +/* Return an array of (char *) which is a list of completions for TEXT. + If there are no completions, return a NULL pointer. + The first entry in the returned array is the substitution for TEXT. + The remaining entries are the possible completions. + The array is terminated with a NULL pointer. + + ENTRY_FUNCTION is a function of two args, and returns a (char *). + The first argument is TEXT. + The second is a state argument; it should be zero on the first call, and + non-zero on subsequent calls. It returns a NULL pointer to the caller + when there are no more matches. + */ +char ** +completion_matches (text, entry_function) + char *text; + char *(*entry_function) (); +{ + /* Number of slots in match_list. */ + int match_list_size; + + /* The list of matches. */ + char **match_list = + (char **)xmalloc (((match_list_size = 10) + 1) * sizeof (char *)); + + /* Number of matches actually found. */ + int matches = 0; + + /* Temporary string binder. */ + char *string; + + match_list[1] = (char *)NULL; + + while (string = (*entry_function) (text, matches)) + { + if (matches + 1 == match_list_size) + match_list = + (char **)xrealloc (match_list, + ((match_list_size += 10) + 1) * sizeof (char *)); + + match_list[++matches] = string; + match_list[matches + 1] = (char *)NULL; + } + + /* If there were any matches, then look through them finding out the + lowest common denominator. That then becomes match_list[0]. */ + if (matches) + { + register int i = 1; + int low = 100000; /* Count of max-matched characters. */ + + /* If only one match, just use that. */ + if (matches == 1) + { + match_list[0] = match_list[1]; + match_list[1] = (char *)NULL; + } + else + { + /* Otherwise, compare each member of the list with + the next, finding out where they stop matching. */ + + while (i < matches) + { + register int c1, c2, si; + + if (completion_case_fold) + { + for (si = 0; + (c1 = to_lower(match_list[i][si])) && + (c2 = to_lower(match_list[i + 1][si])); + si++) + if (c1 != c2) break; + } + else + { + for (si = 0; + (c1 = match_list[i][si]) && + (c2 = match_list[i + 1][si]); + si++) + if (c1 != c2) break; + } + + if (low > si) low = si; + i++; + } + match_list[0] = (char *)xmalloc (low + 1); + strncpy (match_list[0], match_list[1], low); + match_list[0][low] = '\0'; + } + } + else /* There were no matches. */ + { + free (match_list); + match_list = (char **)NULL; + } + return (match_list); +} + +/* Okay, now we write the entry_function for filename completion. In the + general case. Note that completion in the shell is a little different + because of all the pathnames that must be followed when looking up the + completion for a command. */ +char * +filename_completion_function (text, state) + int state; + char *text; +{ + static DIR *directory; + static char *filename = (char *)NULL; + static char *dirname = (char *)NULL; + static char *users_dirname = (char *)NULL; + static int filename_len; + + struct direct *entry = (struct direct *)NULL; + + /* If we don't have any state, then do some initialization. */ + if (!state) + { + char *rindex (), *temp; + + if (dirname) free (dirname); + if (filename) free (filename); + if (users_dirname) free (users_dirname); + + filename = savestring (text); + if (!*text) text = "."; + dirname = savestring (text); + + temp = rindex (dirname, '/'); + + if (temp) + { + strcpy (filename, ++temp); + *temp = '\0'; + } + else + strcpy (dirname, "."); + + /* We aren't done yet. We also support the "~user" syntax. */ + + /* Save the version of the directory that the user typed. */ + users_dirname = savestring (dirname); + { + char *tilde_expand (), *temp_dirname = tilde_expand (dirname); + free (dirname); + dirname = temp_dirname; +#ifdef SHELL + { + extern int follow_symbolic_links; + char *make_absolute (); + + if (follow_symbolic_links && (strcmp (dirname, ".") != 0)) + { + temp_dirname = make_absolute (dirname, get_working_directory ("")); + + if (temp_dirname) + { + free (dirname); + dirname = temp_dirname; + } + } + } +#endif /* SHELL */ + } + directory = opendir (dirname); + filename_len = strlen (filename); + + rl_filename_completion_desired = 1; + } + + /* At this point we should entertain the possibility of hacking wildcarded + filenames, like /usr/man*\/te. If the directory name contains + globbing characters, then build an array of directories to glob on, and + glob on the first one. */ + + /* Now that we have some state, we can read the directory. */ + + while (directory && (entry = readdir (directory))) + { + /* Special case for no filename. + All entries except "." and ".." match. */ + if (!filename_len) + { + if ((strcmp (entry->d_name, ".") != 0) && + (strcmp (entry->d_name, "..") != 0)) + break; + } + else + { + /* Otherwise, if these match upto the length of filename, then + it is a match. */ +#ifdef TMB_SYSV + if ((strlen (entry->d_name) >= filename_len) && + (strncmp (filename, entry->d_name, filename_len) == 0)) +#else + if ((entry->d_namlen >= filename_len) && + (strncmp (filename, entry->d_name, filename_len) == 0)) +#endif /* TMB_SYSV */ + { + break; + } + } + } + + if (!entry) + { + if (directory) + { + closedir (directory); + directory = (DIR *)NULL; + } + return (char *)NULL; + } + else + { + char *temp; + + if (dirname && (strcmp (dirname, ".") != 0)) + { +#ifdef TMB_SYSV + temp = (char *)xmalloc (1 + strlen (users_dirname) + + strlen (entry->d_name)); +#else + temp = (char *)xmalloc (1 + strlen (users_dirname) + + entry->d_namlen); +#endif /* TMB_SYSV */ + strcpy (temp, users_dirname); + strcat (temp, entry->d_name); + } + else + { + temp = (savestring (entry->d_name)); + } + return (temp); + } +} + + +/* **************************************************************** */ +/* */ +/* Binding keys */ +/* */ +/* **************************************************************** */ + +/* 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. */ +rl_add_defun (name, function, key) + char *name; + Function *function; + int key; +{ + if (key != -1) + rl_bind_key (key, function); + rl_add_funmap_entry (name, function); +} + +/* Bind KEY to FUNCTION. Returns non-zero if KEY is out of range. */ +int +rl_bind_key (key, function) + int key; + Function *function; +{ + if (key < 0) + return (key); + + if (key > 127 && key < 256) + { + if (keymap[ESC].type == ISKMAP) + { + Keymap escmap = (Keymap)keymap[ESC].function; + + key -= 128; + escmap[key].type = ISFUNC; + escmap[key].function = function; + return (0); + } + return (key); + } + + keymap[key].type = ISFUNC; + keymap[key].function = function; + return (0); +} + +/* Bind KEY to FUNCTION in MAP. Returns non-zero in case of invalid + KEY. */ +int +rl_bind_key_in_map (key, function, map) + int key; + Function *function; + Keymap map; +{ + int result; + Keymap oldmap = keymap; + + keymap = map; + result = rl_bind_key (key, function); + keymap = oldmap; + return (result); +} + +/* Make KEY do nothing in the currently selected keymap. + Returns non-zero in case of error. */ +int +rl_unbind_key (key) + int key; +{ + return (rl_bind_key (key, (Function *)NULL)); +} + +/* Make KEY do nothing in MAP. + Returns non-zero in case of error. */ +int +rl_unbind_key_in_map (key, map) + int key; + Keymap map; +{ + return (rl_bind_key_in_map (key, (Function *)NULL, map)); +} + +/* Bind the key sequence represented by the string KEYSEQ to + FUNCTION. This makes new keymaps as necessary. The initial + place to do bindings is in MAP. */ +rl_set_key (keyseq, function, map) + char *keyseq; + Function *function; + Keymap map; +{ + rl_generic_bind (ISFUNC, keyseq, function, map); +} + +/* Bind the key sequence represented by the string KEYSEQ to + the string of characters MACRO. This makes new keymaps as + necessary. The initial place to do bindings is in MAP. */ +rl_macro_bind (keyseq, macro, map) + char *keyseq, *macro; + Keymap map; +{ + char *macro_keys = (char *)xmalloc (2 * (strlen (macro))); + int macro_keys_len; + + if (rl_translate_keyseq (macro, macro_keys, ¯o_keys_len)) + { + free (macro_keys); + return; + } + rl_generic_bind (ISMACR, keyseq, macro_keys, map); +} + +/* Bind the key sequence represented by the string KEYSEQ to + the arbitrary pointer DATA. TYPE says what kind of data is + pointed to by DATA, right now this can be a function (ISFUNC), + a macro (ISMACR), or a keymap (ISKMAP). This makes new keymaps + as necessary. The initial place to do bindings is in MAP. */ +rl_generic_bind (type, keyseq, data, map) + int type; + char *keyseq, *data; + Keymap map; +{ + char *keys; + int keys_len; + register int i; + + /* If no keys to bind to, exit right away. */ + if (!keyseq || !*keyseq) + { + if (type == ISMACR) + free (data); + return; + } + + keys = (char *)alloca (1 + (2 * strlen (keyseq))); + + /* Translate the ASCII representation of KEYSEQ into an array + of characters. Stuff the characters into ARRAY, and the + length of ARRAY into LENGTH. */ + if (rl_translate_keyseq (keyseq, keys, &keys_len)) + return; + + /* Bind keys, making new keymaps as necessary. */ + for (i = 0; i < keys_len; i++) + { + if (i + 1 < keys_len) + { + if (map[keys[i]].type != ISKMAP) + { + if (map[i].type == ISMACR) + free ((char *)map[i].function); + + map[keys[i]].type = ISKMAP; + map[keys[i]].function = (Function *)rl_make_bare_keymap (); + } + map = (Keymap)map[keys[i]].function; + } + else + { + if (map[keys[i]].type == ISMACR) + free ((char *)map[keys[i]].function); + + map[keys[i]].function = (Function *)data; + map[keys[i]].type = type; + } + } +} + +/* Translate the ASCII representation of SEQ, stuffing the + values into ARRAY, an array of characters. LEN gets the + final length of ARRAY. Return non-zero if there was an + error parsing SEQ. */ +rl_translate_keyseq (seq, array, len) + char *seq, *array; + int *len; +{ + register int i, c, l = 0; + + for (i = 0; c = seq[i]; i++) + { + if (c == '\\') + { + c = seq[++i]; + + if (!c) + break; + + if (((c == 'C' || c == 'M') && seq[i + 1] == '-') || + (c == 'e')) + { + /* Handle special case of backwards define. */ + if (strncmp (&seq[i], "C-\\M-", 5) == 0) + { + array[l++] = ESC; + i += 5; + array[l++] = CTRL (to_upper (seq[i])); + if (!seq[i]) + i--; + continue; + } + + switch (c) + { + case 'M': + i++; + array[l++] = ESC; + break; + + case 'C': + i += 2; + array[l++] = CTRL (to_upper (seq[i])); + break; + + case 'e': + array[l++] = ESC; + } + + continue; + } + } + array[l++] = c; + } + + array[l] = '\0'; + *len = l; + return (0); +} + +/* Return a pointer to the function that STRING represents. + If STRING doesn't have a matching function, then a NULL pointer + is returned. */ +Function * +rl_named_function (string) + char *string; +{ + register int i; + + for (i = 0; funmap[i]; i++) + if (stricmp (funmap[i]->name, string) == 0) + return (funmap[i]->function); + return ((Function *)NULL); +} + +/* The last key bindings file read. */ +static char *last_readline_init_file = "~/.inputrc"; + +/* Re-read the current keybindings file. */ +rl_re_read_init_file (count, ignore) + int count, ignore; +{ + rl_read_init_file (last_readline_init_file); +} + +/* Do key bindings from a file. If FILENAME is NULL it defaults + to `~/.inputrc'. If the file existed and could be opened and + read, 0 is returned, otherwise errno is returned. */ +int +rl_read_init_file (filename) + char *filename; +{ + extern int errno; + int line_size, line_index; + char *line = (char *)xmalloc (line_size = 100); + char *openname; + FILE *file; + + int c; + + /* Default the filename. */ + if (!filename) + filename = "~/.inputrc"; + + openname = tilde_expand (filename); + + /* Open the file. */ + file = fopen (openname, "r"); + free (openname); + + if (!file) + return (errno); + + last_readline_init_file = filename; + + /* Loop reading lines from the file. Lines that start with `#' are + comments, all other lines are commands for readline initialization. */ + while ((c = rl_getc (file)) != EOF) + { + /* If comment, flush to EOL. */ + if (c == '#') + { + while ((c = rl_getc (file)) != EOF && c != '\n'); + if (c == EOF) + goto function_exit; + continue; + } + + /* Otherwise, this is the start of a line. Read the + line from the file. */ + line_index = 0; + while (c != EOF && c != '\n') + { + line[line_index++] = c; + if (line_index == line_size) + line = (char *)xrealloc (line, line_size += 100); + c = rl_getc (file); + } + line[line_index] = '\0'; + + /* Parse the line. */ + rl_parse_and_bind (line); + } + +function_exit: + + free (line); + /* Close up the file and exit. */ + fclose (file); + return (0); +} + + +/* **************************************************************** */ +/* */ +/* Parser Directives */ +/* */ +/* **************************************************************** */ + +/* Conditionals. */ + +/* Calling programs set this to have their argv[0]. */ +char *rl_readline_name = "other"; + +/* Non-zero means do not parse any lines other than comments and + parser directives. */ +static unsigned char parsing_conditionalized_out = 0; + +/* Stack of previous values of parsing_conditionalized_out. */ +static unsigned char *if_stack = (unsigned char *)NULL; +static int if_stack_depth = 0; +static int if_stack_size = 0; + +/* Push parsing_conditionalized_out, and set parser state based on ARGS. */ +parser_if (args) + char *args; +{ + register int i; + + /* Push parser state. */ + if (if_stack_depth + 1 >= if_stack_size) + { + if (!if_stack) + if_stack = (unsigned char *)xmalloc (if_stack_size = 20); + else + if_stack = (unsigned char *)xrealloc (if_stack, if_stack_size += 20); + } + if_stack[if_stack_depth++] = parsing_conditionalized_out; + + /* We only check to see if the first word in ARGS is the same as the + value stored in rl_readline_name. */ + + /* Isolate first argument. */ + for (i = 0; args[i] && !whitespace (args[i]); i++); + + if (args[i]) + args[i++] = '\0'; + + if (stricmp (args, rl_readline_name) == 0) + parsing_conditionalized_out = 0; + else + parsing_conditionalized_out = 1; +} + +/* Invert the current parser state if there is anything on the stack. */ +parser_else (args) + char *args; +{ + if (if_stack_depth) + parsing_conditionalized_out = !parsing_conditionalized_out; + else + { + /* *** What, no error message? *** */ + } +} + +/* Terminate a conditional, popping the value of + parsing_conditionalized_out from the stack. */ +parser_endif (args) + char *args; +{ + if (if_stack_depth) + parsing_conditionalized_out = if_stack[--if_stack_depth]; + else + { + /* *** What, no error message? *** */ + } +} + +/* Associate textual names with actual functions. */ +static struct { + char *name; + Function *function; +} parser_directives [] = { + { "if", parser_if }, + { "endif", parser_endif }, + { "else", parser_else }, + { (char *)0x0, (Function *)0x0 } +}; + +/* Handle a parser directive. STATEMENT is the line of the directive + without any leading `$'. */ +static int +handle_parser_directive (statement) + char *statement; +{ + register int i; + char *directive, *args; + + /* Isolate the actual directive. */ + + /* Skip whitespace. */ + for (i = 0; whitespace (statement[i]); i++); + + directive = &statement[i]; + + for (; statement[i] && !whitespace (statement[i]); i++); + + if (statement[i]) + statement[i++] = '\0'; + + for (; statement[i] && whitespace (statement[i]); i++); + + args = &statement[i]; + + /* Lookup the command, and act on it. */ + for (i = 0; parser_directives[i].name; i++) + if (stricmp (directive, parser_directives[i].name) == 0) + { + (*parser_directives[i].function) (args); + return (0); + } + + /* *** Should an error message be output? */ + return (1); +} + +/* Read the binding command from STRING and perform it. + A key binding command looks like: Keyname: function-name\0, + a variable binding command looks like: set variable value. + A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark. */ +rl_parse_and_bind (string) + char *string; +{ + extern char *possible_control_prefixes[], *possible_meta_prefixes[]; + char *rindex (), *funname, *kname; + static int substring_member_of_array (); + register int c; + int key, i; + + if (!string || !*string || *string == '#') + return; + + /* If this is a parser directive, act on it. */ + if (*string == '$') + { + handle_parser_directive (&string[1]); + return; + } + + /* If we are supposed to be skipping parsing right now, then do it. */ + if (parsing_conditionalized_out) + return; + + i = 0; + /* If this keyname is a complex key expression surrounded by quotes, + advance to after the matching close quote. */ + if (*string == '"') + { + for (i = 1; c = string[i]; i++) + { + if (c == '"' && string[i - 1] != '\\') + break; + } + } + + /* Advance to the colon (:) or whitespace which separates the two objects. */ + for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ ); + + /* Mark the end of the command (or keyname). */ + if (string[i]) + string[i++] = '\0'; + + /* If this is a command to set a variable, then do that. */ + if (stricmp (string, "set") == 0) + { + char *var = string + i; + char *value; + + /* Make VAR point to start of variable name. */ + while (*var && whitespace (*var)) var++; + + /* Make value point to start of value string. */ + value = var; + while (*value && !whitespace (*value)) value++; + if (*value) + *value++ = '\0'; + while (*value && whitespace (*value)) value++; + + rl_variable_bind (var, value); + return; + } + + /* Skip any whitespace between keyname and funname. */ + for (; string[i] && whitespace (string[i]); i++); + funname = &string[i]; + + /* Now isolate funname. + For straight function names just look for whitespace, since + that will signify the end of the string. But this could be a + macro definition. In that case, the string is quoted, so skip + to the matching delimiter. */ + if (*funname == '\'' || *funname == '"') + { + int delimiter = string[i++]; + + for (; c = string[i]; i++) + { + if (c == delimiter && string[i - 1] != '\\') + break; + } + if (c) + i++; + } + + /* Advance to the end of the string. */ + for (; string[i] && !whitespace (string[i]); i++); + + /* No extra whitespace at the end of the string. */ + string[i] = '\0'; + + /* If this is a new-style key-binding, then do the binding with + rl_set_key (). Otherwise, let the older code deal with it. */ + if (*string == '"') + { + char *seq = (char *)alloca (1 + strlen (string)); + register int j, k = 0; + + for (j = 1; string[j]; j++) + { + if (string[j] == '"' && string[j - 1] != '\\') + break; + + seq[k++] = string[j]; + } + seq[k] = '\0'; + + /* Binding macro? */ + if (*funname == '\'' || *funname == '"') + { + j = strlen (funname); + + if (j && funname[j - 1] == *funname) + funname[j - 1] = '\0'; + + rl_macro_bind (seq, &funname[1], keymap); + } + else + rl_set_key (seq, rl_named_function (funname), keymap); + + return; + } + + /* Get the actual character we want to deal with. */ + kname = rindex (string, '-'); + if (!kname) + kname = string; + else + kname++; + + key = glean_key_from_name (kname); + + /* Add in control and meta bits. */ + if (substring_member_of_array (string, possible_control_prefixes)) + key = CTRL (to_upper (key)); + + if (substring_member_of_array (string, possible_meta_prefixes)) + key = META (key); + + /* Temporary. Handle old-style keyname with macro-binding. */ + if (*funname == '\'' || *funname == '"') + { + char seq[2]; + int fl = strlen (funname); + + seq[0] = key; seq[1] = '\0'; + if (fl && funname[fl - 1] == *funname) + funname[fl - 1] = '\0'; + + rl_macro_bind (seq, &funname[1], keymap); + } + else + rl_bind_key (key, rl_named_function (funname)); +} + +rl_variable_bind (name, value) + char *name, *value; +{ + static int strnicmp (); + + if (stricmp (name, "editing-mode") == 0) + { + if (strnicmp (value, "vi", 2) == 0) + { +#ifdef VI_MODE + keymap = vi_insertion_keymap; + rl_editing_mode = vi_mode; +#endif /* VI_MODE */ + } + else if (strnicmp (value, "emacs", 5) == 0) + { + keymap = emacs_standard_keymap; + rl_editing_mode = emacs_mode; + } + } + else if (stricmp (name, "horizontal-scroll-mode") == 0) + { + if (!*value || stricmp (value, "On") == 0) + horizontal_scroll_mode = 1; + else + horizontal_scroll_mode = 0; + } +} + +/* Return the character which matches NAME. + For example, `Space' returns ' '. */ + +typedef struct { + char *name; + int value; +} assoc_list; + +assoc_list name_key_alist[] = { + { "Space", ' ' }, + { "SPC", ' ' }, + { "Rubout", 0x7f }, + { "DEL", 0x7f }, + { "Tab", 0x09 }, + { "Newline", '\n' }, + { "Return", '\r' }, + { "RET", '\r' }, + { "LFD", '\n' }, + { "Escape", '\033' }, + { "ESC", '\033' }, + + { (char *)0x0, 0 } +}; + +int +glean_key_from_name (name) + char *name; +{ + register int i; + + for (i = 0; name_key_alist[i].name; i++) + if (stricmp (name, name_key_alist[i].name) == 0) + return (name_key_alist[i].value); + + return (*name); +} + + +/* **************************************************************** */ +/* */ +/* String Utility Functions */ +/* */ +/* **************************************************************** */ + +/* Return non-zero if any members of ARRAY are a substring in STRING. */ +static int +substring_member_of_array (string, array) + char *string, **array; +{ + static char *strindex (); + + while (*array) + { + if (strindex (string, *array)) + return (1); + array++; + } + return (0); +} + +/* Whoops, Unix doesn't have strnicmp. */ + +/* Compare at most COUNT characters from string1 to string2. Case + doesn't matter. */ +static int +strnicmp (string1, string2, count) + char *string1, *string2; +{ + register char ch1, ch2; + + while (count) { + ch1 = *string1++; + ch2 = *string2++; + if (to_upper(ch1) == to_upper(ch2)) + count--; + else break; + } + return (count); +} + +/* strcmp (), but caseless. */ +static int +stricmp (string1, string2) + char *string1, *string2; +{ + register char ch1, ch2; + + while (*string1 && *string2) { + ch1 = *string1++; + ch2 = *string2++; + if (to_upper(ch1) != to_upper(ch2)) + return (1); + } + return (*string1 | *string2); +} + +/* Determine if s2 occurs in s1. If so, return a pointer to the + match in s1. The compare is case insensitive. */ +static char * +strindex (s1, s2) + register char *s1, *s2; +{ + register int i, l = strlen (s2); + register int len = strlen (s1); + + for (i = 0; (len - i) >= l; i++) + if (strnicmp (&s1[i], s2, l) == 0) + return (s1 + i); + return ((char *)NULL); +} + + +/* **************************************************************** */ +/* */ +/* SYSV Support */ +/* */ +/* **************************************************************** */ + +/* Since system V reads input differently than we do, I have to + make a special version of getc for that. */ + +#ifdef SYSV + +extern int errno; +#include + +int +rl_getc (stream) + FILE *stream; +{ + int result; + unsigned char c; + + while (1) + { + result = read (fileno (stream), &c, sizeof (char)); + if (result == sizeof (char)) + return (c); + + if (errno != EINTR) + return (EOF); + } +} +#else +int +rl_getc (stream) + FILE *stream; +{ + return (getc (stream)); +} +#endif + +#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 */ + + +/* **************************************************************** */ +/* */ +/* Testing Readline */ +/* */ +/* **************************************************************** */ + +#ifdef TEST + +main () +{ + HIST_ENTRY **history_list (); + char *temp = (char *)NULL; + char *prompt = "readline% "; + int done = 0; + + while (!done) + { + temp = readline (prompt); + + /* Test for EOF. */ + if (!temp) + exit (1); + + /* If there is anything on the line, print it and remember it. */ + if (*temp) + { + fprintf (stderr, "%s\r\n", temp); + add_history (temp); + } + + /* Check for `command' that we handle. */ + if (strcmp (temp, "quit") == 0) + done = 1; + + if (strcmp (temp, "list") == 0) { + HIST_ENTRY **list = history_list (); + register int i; + if (list) { + for (i = 0; list[i]; i++) { + fprintf (stderr, "%d: %s\r\n", i, list[i]->line); + free (list[i]->line); + } + free (list); + } + } + free (temp); + } +} + +#endif /* TEST */ + + +/* + * Local variables: + * compile-command: "gcc -g -traditional -I. -I.. -DTEST -o readline readline.c keymaps.o funmap.o history.o -ltermcap" + * end: + */ diff --git a/gdb/readline/readline.h b/gdb/readline/readline.h new file mode 100644 index 0000000000..7d7fbe7c3c --- /dev/null +++ b/gdb/readline/readline.h @@ -0,0 +1,161 @@ +/* Readline.h -- the names of functions callable from within readline. */ + +#ifndef _READLINE_H_ +#define _READLINE_H_ + +#include + +#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_ */ + diff --git a/gdb/readline/vi_keymap.c b/gdb/readline/vi_keymap.c new file mode 100644 index 0000000000..896ef484da --- /dev/null +++ b/gdb/readline/vi_keymap.c @@ -0,0 +1,474 @@ +/* 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 +#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_insert }, /* 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 */ +}; diff --git a/gdb/readline/vi_mode.c b/gdb/readline/vi_mode.c new file mode 100644 index 0000000000..0900e89ac5 --- /dev/null +++ b/gdb/readline/vi_mode.c @@ -0,0 +1,859 @@ +/* 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; + +/* Non-zero means enter insertion mode. */ +static vi_doing_insert = 0; + +/* *** 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)) + rl_forward (1); + + 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--; + + 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_getc (in_stream); + + 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_getc (in_stream); + + 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[ESC].function = rl_vi_movement_mode; + vi_replace_map[RETURN].function = rl_newline; + vi_replace_map[NEWLINE].function = rl_newline; + keymap = vi_replace_map; +} diff --git a/gdb/regex.c b/gdb/regex.c index 40118055fc..45c34780f6 100644 --- a/gdb/regex.c +++ b/gdb/regex.c @@ -1,106 +1,24 @@ -/* Extended regular expression matching and search. - Copyright (C) 1985 Free Software Foundation, Inc. - - NO WARRANTY - - BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY -NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT -WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, -RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS 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. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. -STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY -WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE -LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR -OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR -DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR -A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS -PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. - - GENERAL PUBLIC LICENSE TO COPY - - 1. You may copy and distribute verbatim copies of this source file -as you receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy a valid copyright notice "Copyright -(C) 1985 Free Software Foundation, Inc."; and include following the -copyright notice a verbatim copy of the above disclaimer of warranty -and of this License. You may charge a distribution fee for the -physical act of transferring a copy. - - 2. You may modify your copy or copies of this source file 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 or is a derivative of this - program or any part thereof, to be licensed at no charge to all - third parties on terms identical to those contained in this - License Agreement (except that you may choose to grant more extensive - warranty protection to some or all third parties, at your option). - - c) You may charge a distribution 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 unrelated program with this program (or its -derivative) on a volume of a storage or distribution medium does not bring -the other program under the scope of these terms. - - 3. You may copy and distribute this 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 - shipping charge) 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.) - -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. - - 4. You may not copy, sublicense, distribute or transfer this program -except as expressly provided under this License Agreement. Any attempt -otherwise to copy, sublicense, distribute or transfer this program is void and -your rights to use the program under this License agreement shall be -automatically terminated. However, parties who have received computer -software programs from you with this License Agreement will not have -their licenses terminated so long as such parties remain in full compliance. - - 5. If you wish to incorporate parts of this program into other free -programs whose distribution conditions are different, write to the Free -Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet -worked out a simple rule that can be stated here, but we will often permit -this. We 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. - - -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! */ +/* Extended regular expression matching and search 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! */ /* To test, compile with -Dtest. @@ -121,10 +39,12 @@ what you give them. Help stamp out software-hoarding! */ #else /* not emacs */ #ifdef USG +#ifndef BSTRING #define bcopy(s,d,n) memcpy((d),(s),(n)) #define bcmp(s1,s2,n) memcmp((s1),(s2),(n)) #define bzero(s,n) memset((s),0,(n)) #endif +#endif /* Make alloca work the best possible way. */ #ifdef __GNUC__ diff --git a/gdb/regex.h b/gdb/regex.h index c9f082df4b..d0d8a82835 100644 --- a/gdb/regex.h +++ b/gdb/regex.h @@ -1,106 +1,24 @@ /* Definitions for data structures callers pass the regex library. - Copyright (C) 1985 Free Software Foundation, Inc. + Copyright (C) 1985, 1989 Free Software Foundation, Inc. - NO WARRANTY + 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. - BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY -NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT -WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, -RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS 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. + 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. - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. -STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY -WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE -LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR -OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR -DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR -A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS -PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. + 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. - GENERAL PUBLIC LICENSE TO COPY - 1. You may copy and distribute verbatim copies of this source file -as you receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy a valid copyright notice "Copyright -(C) 1985 Free Software Foundation, Inc."; and include following the -copyright notice a verbatim copy of the above disclaimer of warranty -and of this License. You may charge a distribution fee for the -physical act of transferring a copy. - - 2. You may modify your copy or copies of this source file 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 or is a derivative of this - program or any part thereof, to be licensed at no charge to all - third parties on terms identical to those contained in this - License Agreement (except that you may choose to grant more extensive - warranty protection to some or all third parties, at your option). - - c) You may charge a distribution 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 unrelated program with this program (or its -derivative) on a volume of a storage or distribution medium does not bring -the other program under the scope of these terms. - - 3. You may copy and distribute this 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 - shipping charge) 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.) - -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. - - 4. You may not copy, sublicense, distribute or transfer this program -except as expressly provided under this License Agreement. Any attempt -otherwise to copy, sublicense, distribute or transfer this program is void and -your rights to use the program under this License agreement shall be -automatically terminated. However, parties who have received computer -software programs from you with this License Agreement will not have -their licenses terminated so long as such parties remain in full compliance. - - 5. If you wish to incorporate parts of this program into other free -programs whose distribution conditions are different, write to the Free -Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet -worked out a simple rule that can be stated here, but we will often permit -this. We 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. - - -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! */ + 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. diff --git a/gdb/remote-multi.shar b/gdb/remote-multi.shar new file mode 100644 index 0000000000..86c9cf0217 --- /dev/null +++ b/gdb/remote-multi.shar @@ -0,0 +1,1313 @@ +#!/bin/sh +# This is a shell archive. +# Run the file through sh to extract its contents. +# shar: Shell Archiver +# Run the following text with /bin/sh to create: +# Remote_Makefile +# remote_gutils.c +# remote_inflow.c +# remote_server.c +# remote_utils.c +# This archive created: Fri Jun 23 17:06:55 1989 +cat << \SHAR_EOF > Remote_Makefile +# Makefile for the remote server 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. */ + +CFLAGS = -g +CC = cc + +SERVER = remote_server.o\ + remote_inflow.o\ + remote_utils.o\ + remote_gutils.o + +prog : $(SERVER) + $(CC) -g -o serve $(SERVER) +SHAR_EOF +cat << \SHAR_EOF > remote_gutils.c +/* General utility routines for the remote server 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. */ + +#include +#include +#include "defs.h" + +void error (); +void fatal (); + +/* Chain of cleanup actions established with make_cleanup, + to be executed if an error happens. */ + +static struct cleanup *cleanup_chain; + +/* Nonzero means a quit has been requested. */ + +int quit_flag; + +/* Nonzero means quit immediately if Control-C is typed now, + rather than waiting until QUIT is executed. */ + +int immediate_quit; + +/* Add a new cleanup to the cleanup_chain, + and return the previous chain pointer + to be passed later to do_cleanups or discard_cleanups. + Args are FUNCTION to clean up with, and ARG to pass to it. */ + +struct cleanup * +make_cleanup (function, arg) + void (*function) (); + int arg; +{ + register struct cleanup *new + = (struct cleanup *) xmalloc (sizeof (struct cleanup)); + register struct cleanup *old_chain = cleanup_chain; + + new->next = cleanup_chain; + new->function = function; + new->arg = arg; + cleanup_chain = new; + + return old_chain; +} + +/* Discard cleanups and do the actions they describe + until we get back to the point OLD_CHAIN in the cleanup_chain. */ + +void +do_cleanups (old_chain) + register struct cleanup *old_chain; +{ + register struct cleanup *ptr; + while ((ptr = cleanup_chain) != old_chain) + { + (*ptr->function) (ptr->arg); + cleanup_chain = ptr->next; + free (ptr); + } +} + +/* Discard cleanups, not doing the actions they describe, + until we get back to the point OLD_CHAIN in the cleanup_chain. */ + +void +discard_cleanups (old_chain) + register struct cleanup *old_chain; +{ + register struct cleanup *ptr; + while ((ptr = cleanup_chain) != old_chain) + { + cleanup_chain = ptr->next; + free (ptr); + } +} + +/* This function is useful for cleanups. + Do + + foo = xmalloc (...); + old_chain = make_cleanup (free_current_contents, &foo); + + to arrange to free the object thus allocated. */ + +void +free_current_contents (location) + char **location; +{ + free (*location); +} + +/* Generally useful subroutines used throughout the program. */ + +/* Like malloc but get error if no storage available. */ + +char * +xmalloc (size) + long size; +{ + register char *val = (char *) malloc (size); + if (!val) + fatal ("virtual memory exhausted.", 0); + return val; +} + +/* Like realloc but get error if no storage available. */ + +char * +xrealloc (ptr, size) + char *ptr; + long size; +{ + register char *val = (char *) realloc (ptr, size); + if (!val) + fatal ("virtual memory exhausted.", 0); + return val; +} + +/* Print the system error message for errno, and also mention STRING + as the file name for which the error was encountered. + Then return to command level. */ + +void +perror_with_name (string) + char *string; +{ + extern int sys_nerr; + extern char *sys_errlist[]; + extern int errno; + char *err; + char *combined; + + if (errno < sys_nerr) + err = sys_errlist[errno]; + else + err = "unknown error"; + + combined = (char *) alloca (strlen (err) + strlen (string) + 3); + strcpy (combined, string); + strcat (combined, ": "); + strcat (combined, err); + + error ("%s.", combined); +} + +/* Print the system error message for ERRCODE, and also mention STRING + as the file name for which the error was encountered. */ + +void +print_sys_errmsg (string, errcode) + char *string; + int errcode; +{ + extern int sys_nerr; + extern char *sys_errlist[]; + char *err; + char *combined; + + if (errcode < sys_nerr) + err = sys_errlist[errcode]; + else + err = "unknown error"; + + combined = (char *) alloca (strlen (err) + strlen (string) + 3); + strcpy (combined, string); + strcat (combined, ": "); + strcat (combined, err); + + printf ("%s.\n", combined); +} + +void +quit () +{ + fflush (stdout); + ioctl (fileno (stdout), TIOCFLUSH, 0); + error ("Quit"); +} + +/* Control C comes here */ + +void +request_quit () +{ + quit_flag = 1; + if (immediate_quit) + quit (); +} + +/* Print an error message and return to command level. + STRING is the error message, used as a fprintf string, + and ARG is passed as an argument to it. */ + +void +error (string, arg1, arg2, arg3) + char *string; + int arg1, arg2, arg3; +{ + fflush (stdout); + fprintf (stderr, string, arg1, arg2, arg3); + fprintf (stderr, "\n"); + /************return_to_top_level ();************/ +} + +/* Print an error message and exit reporting failure. + This is for a error that we cannot continue from. + STRING and ARG are passed to fprintf. */ + +void +fatal (string, arg) + char *string; + int arg; +{ + fprintf (stderr, "gdb: "); + fprintf (stderr, string, arg); + fprintf (stderr, "\n"); + exit (1); +} + +/* Make a copy of the string at PTR with SIZE characters + (and add a null character at the end in the copy). + Uses malloc to get the space. Returns the address of the copy. */ + +char * +savestring (ptr, size) + char *ptr; + int size; +{ + register char *p = (char *) xmalloc (size + 1); + bcopy (ptr, p, size); + p[size] = 0; + return p; +} + +char * +concat (s1, s2, s3) + char *s1, *s2, *s3; +{ + register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1; + register char *val = (char *) xmalloc (len); + strcpy (val, s1); + strcat (val, s2); + strcat (val, s3); + return val; +} + +void +print_spaces (n, file) + register int n; + register FILE *file; +{ + while (n-- > 0) + fputc (' ', file); +} + +/* Ask user a y-or-n question and return 1 iff answer is yes. + Takes three args which are given to printf to print the question. + The first, a control string, should end in "? ". + It should not say how to answer, because we do that. */ + +int +query (ctlstr, arg1, arg2) + char *ctlstr; +{ + register int answer; + + /* Automatically answer "yes" if input is not from a terminal. */ + /***********if (!input_from_terminal_p ()) + return 1; *************************/ + + while (1) + { + printf (ctlstr, arg1, arg2); + printf ("(y or n) "); + fflush (stdout); + answer = fgetc (stdin); + clearerr (stdin); /* in case of C-d */ + if (answer != '\n') + while (fgetc (stdin) != '\n') clearerr (stdin); + if (answer >= 'a') + answer -= 040; + if (answer == 'Y') + return 1; + if (answer == 'N') + return 0; + printf ("Please answer y or n.\n"); + } +} + +/* Parse a C escape sequence. STRING_PTR points to a variable + containing a pointer to the string to parse. That pointer + is updated past the characters we use. The value of the + escape sequence is returned. + + A negative value means the sequence \ newline was seen, + which is supposed to be equivalent to nothing at all. + + If \ is followed by a null character, we return a negative + value and leave the string pointer pointing at the null character. + + If \ is followed by 000, we return 0 and leave the string pointer + after the zeros. A value of 0 does not mean end of string. */ + +int +parse_escape (string_ptr) + char **string_ptr; +{ + register int c = *(*string_ptr)++; + switch (c) + { + case 'a': + return '\a'; + case 'b': + return '\b'; + case 'e': + return 033; + case 'f': + return '\f'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + case 'v': + return '\v'; + case '\n': + return -2; + case 0: + (*string_ptr)--; + return 0; + case '^': + c = *(*string_ptr)++; + if (c == '\\') + c = parse_escape (string_ptr); + if (c == '?') + return 0177; + return (c & 0200) | (c & 037); + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + { + register int i = c - '0'; + register int count = 0; + while (++count < 3) + { + if ((c = *(*string_ptr)++) >= '0' && c <= '7') + { + i *= 8; + i += c - '0'; + } + else + { + (*string_ptr)--; + break; + } + } + return i; + } + default: + return c; + } +} + +void +printchar (ch, stream) + unsigned char ch; + FILE *stream; +{ + register int c = ch; + if (c < 040 || c >= 0177) + { + if (c == '\n') + fprintf (stream, "\\n"); + else if (c == '\b') + fprintf (stream, "\\b"); + else if (c == '\t') + fprintf (stream, "\\t"); + else if (c == '\f') + fprintf (stream, "\\f"); + else if (c == '\r') + fprintf (stream, "\\r"); + else if (c == 033) + fprintf (stream, "\\e"); + else if (c == '\a') + fprintf (stream, "\\a"); + else + fprintf (stream, "\\%03o", c); + } + else + { + if (c == '\\' || c == '"' || c == '\'') + fputc ('\\', stream); + fputc (c, stream); + } +} +SHAR_EOF +cat << \SHAR_EOF > remote_inflow.c +/* Low level interface to ptrace, for GDB when running under Unix. + Copyright (C) 1986, 1987 Free Software Foundation, Inc. +*/ + +#include "defs.h" +#include "param.h" +#include "wait.h" +#include "frame.h" +#include "inferior.h" +/*************************** +#include "initialize.h" +****************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/***************Begin MY defs*********************/ +int quit_flag = 0; +char registers[REGISTER_BYTES]; + +/* Index within `registers' of the first byte of the space for + register N. */ + + +char buf2[MAX_REGISTER_RAW_SIZE]; +/***************End MY defs*********************/ + +#ifdef NEW_SUN_PTRACE +#include +#include +#endif + +extern char **environ; +extern int errno; +extern int inferior_pid; +void error(), quit(), perror_with_name(); +int query(); +void supply_register(), write_register(); +CORE_ADDR read_register(); + +/* Nonzero if we are debugging an attached outside process + rather than an inferior. */ + + +/* Start an inferior process and returns its pid. + ALLARGS is a vector of program-name and args. + ENV is the environment vector to pass. */ + +int +create_inferior (allargs, env) + char **allargs; + char **env; +{ + int pid; + extern int sys_nerr; + extern char *sys_errlist[]; + extern int errno; + + /* exec is said to fail if the executable is open. */ + /****************close_exec_file ();*****************/ + + pid = vfork (); + if (pid < 0) + perror_with_name ("vfork"); + + if (pid == 0) + { + /* Run inferior in a separate process group. */ + setpgrp (getpid (), getpid ()); + +/* Not needed on Sun, at least, and loses there + because it clobbers the superior. */ +/*??? signal (SIGQUIT, SIG_DFL); + signal (SIGINT, SIG_DFL); */ + + errno = 0; + ptrace (0); + + execle ("/bin/sh", "sh", "-c", allargs, 0, env); + + fprintf (stderr, "Cannot exec /bin/sh: %s.\n", + errno < sys_nerr ? sys_errlist[errno] : "unknown error"); + fflush (stderr); + _exit (0177); + } + return pid; +} + +/* Kill the inferior process. Make us have no inferior. */ + +kill_inferior () +{ + if (inferior_pid == 0) + return; + ptrace (8, inferior_pid, 0, 0); + wait (0); + /*************inferior_died ();****VK**************/ +} + +/* Resume execution of the inferior process. + If STEP is nonzero, single-step it. + If SIGNAL is nonzero, give it that signal. */ + +unsigned char +resume (step, signal,status) + int step; + int signal; + char *status; +{ + int pid ; + WAITTYPE w; + + errno = 0; + ptrace (step ? 9 : 7, inferior_pid, 1, signal); + if (errno) + perror_with_name ("ptrace"); + pid = wait(&w); + if(pid != inferior_pid) + perror_with_name ("wait"); + + if(WIFEXITED(w)) + { + printf("\nchild exited with retcode = %x \n",WRETCODE(w)); + *status = 'E'; + return((unsigned char) WRETCODE(w)); + } + else if(!WIFSTOPPED(w)) + { + printf("\nchild did terminated with signal = %x \n",WTERMSIG(w)); + *status = 'T'; + return((unsigned char) WTERMSIG(w)); + } + else + { + printf("\nchild stopped with signal = %x \n",WSTOPSIG(w)); + *status = 'S'; + return((unsigned char) WSTOPSIG(w)); + } + +} + + +#ifdef NEW_SUN_PTRACE + +void +fetch_inferior_registers () +{ + struct regs inferior_registers; + struct fp_status inferior_fp_registers; + extern char registers[]; + + ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers); + if (errno) + perror_with_name ("ptrace"); + /**********debugging begin **********/ + print_some_registers(&inferior_registers); + /**********debugging end **********/ + ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers); + if (errno) + perror_with_name ("ptrace"); + + bcopy (&inferior_registers, registers, 16 * 4); + bcopy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)], + sizeof inferior_fp_registers.fps_regs); + *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps; + *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc; + bcopy (&inferior_fp_registers.fps_control, + ®isters[REGISTER_BYTE (FPC_REGNUM)], + sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs); +} + +/* 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; +{ + struct regs inferior_registers; + struct fp_status inferior_fp_registers; + extern char registers[]; + + bcopy (registers, &inferior_registers, 16 * 4); + bcopy (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers, + sizeof inferior_fp_registers.fps_regs); + inferior_registers.r_ps = *(int *)®isters[REGISTER_BYTE (PS_REGNUM)]; + inferior_registers.r_pc = *(int *)®isters[REGISTER_BYTE (PC_REGNUM)]; + bcopy (®isters[REGISTER_BYTE (FPC_REGNUM)], + &inferior_fp_registers.fps_control, + sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs); + + ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers); + if (errno) + perror_with_name ("ptrace"); + ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers); + if (errno) + perror_with_name ("ptrace"); +} + +#endif /* not NEW_SUN_PTRACE */ + + +/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory + in the NEW_SUN_PTRACE case. + It ought to be straightforward. But it appears that writing did + not write the data that I specified. I cannot understand where + it got the data that it actually did write. */ + +/* Copy LEN bytes from inferior's memory starting at MEMADDR + to debugger memory starting at MYADDR. */ + +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)); + + /* Read all the longwords */ + for (i = 0; i < count; i++, addr += sizeof (int)) + { + buffer[i] = ptrace (1, inferior_pid, addr, 0); + } + + /* Copy appropriate bytes out of the buffer. */ + bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len); +} + +/* 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. */ + + 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; +} + +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."); + + fetch_inferior_registers(); + for (i = 0;i<18 ; i ++) + { + QUIT; + errno = 0; + value = read_register(i); + write_register ( i, value); + if (errno == 0) + { + printf (" Succeeded with register %d; value 0x%x (%d).\n", + i, value, value); + } + else + printf (" Failed with register %d.\n", i); + } +} + +void +initialize () +{ + + inferior_pid = 0; + + +} + + +/* 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) */ + *(int *) ®isters[REGISTER_BYTE (regno)] = val; + + if (have_inferior_p ()) + store_inferior_registers (regno); +} + + +int +have_inferior_p () +{ + return inferior_pid != 0; +} + +print_some_registers(regs) +int regs[]; +{ + register int i; + for (i = 0; i < 18; i++) { + printf("reg[%d] = %x\n", i, regs[i]); + } +} + +SHAR_EOF +cat << \SHAR_EOF > remote_server.c +/* Main code for remote server for GDB, the GNU Debugger. + 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 "param.h" +#include + +void read_inferior_memory(), fetch_inferior_registers(); +unsigned char resume(); +void kill_inferior(); +void initialize(), try_writing_regs_command(); +int create_inferior(), read_register(); + +extern char registers[]; +int inferior_pid; +extern char **environ; + +/* Descriptor for I/O to remote machine. */ +int remote_desc; +int kiodebug = 0; +int remote_debugging; + +void remote_send (); +void putpkt (); +void getpkt (); +void remote_open(); +void write_ok(); +void write_enn(); +void convert_ascii_to_int(); +void convert_int_to_ascii(); +void prepare_resume_reply(); +void decode_m_packet(); +void decode_M_packet(); + + +main(argc,argv) +int argc; char *argv[]; +{ + char ch,status, own_buf[2000], mem_buf[2000]; + int i=0; + unsigned char signal; + unsigned int mem_addr, len; + + initialize(); + printf("\nwill open serial link\n"); + remote_open("/dev/ttya",0); + + if(argc < 2) + { + printf("Enter name of program to be run with command line args\n"); + gets(own_buf); + inferior_pid = create_inferior(own_buf,environ); + printf("\nProcess %s created; pid = %d\n",own_buf,inferior_pid); + } + else + { + inferior_pid = create_inferior(argv[1],environ); + printf("\nProcess %s created; pid = %d\n",argv[1],inferior_pid); + } + + do { + getpkt(own_buf); + printf("\nPacket received is>:%s\n",own_buf); + i = 0; + ch = own_buf[i++]; + switch (ch) { + case 'h': /**********This is only for tweaking the gdb+ program *******/ + signal = resume(1,0,&status); + prepare_resume_reply(own_buf,status,signal); + break; + /*************end tweak*************************************/ + + case 'g': fetch_inferior_registers(); + convert_int_to_ascii(registers,own_buf,REGISTER_BYTES); + break; + case 'G': convert_ascii_to_int(&own_buf[1],registers,REGISTER_BYTES); + if(store_inferior_registers(-1)==0) + write_ok(own_buf); + else + write_enn(own_buf); + break; + case 'm': decode_m_packet(&own_buf[1],&mem_addr,&len); + read_inferior_memory(mem_addr,mem_buf,len); + convert_int_to_ascii(mem_buf,own_buf,len); + break; + case 'M': decode_M_packet(&own_buf[1],&mem_addr,&len,mem_buf); + if(write_inferior_memory(mem_addr,mem_buf,len)==0) + write_ok(own_buf); + else + write_enn(own_buf); + break; + case 'c': signal = resume(0,0,&status); + printf("\nSignal received is >: %0x \n",signal); + prepare_resume_reply(own_buf,status,signal); + break; + case 's': signal = resume(1,0,&status); + prepare_resume_reply(own_buf,status,signal); + break; + case 'k': kill_inferior(); + sprintf(own_buf,"q"); + putpkt(own_buf); + printf("\nObtained kill request...terminating\n"); + close(remote_desc); + exit(0); + case 't': try_writing_regs_command(); + own_buf[0] = '\0'; + break; + default : printf("\nUnknown option chosen by master\n"); + write_enn(own_buf); + break; + } + + putpkt(own_buf); + } while(1) ; + + close(remote_desc); + /** now get out of here**/ + printf("\nFinished reading data from serial link - Bye!\n"); + exit(0); + +} + +SHAR_EOF +cat << \SHAR_EOF > remote_utils.c +/* Remote utility routines for the remote server 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. */ + +#include "param.h" +#include +#include +#include +#include +#include +#include +#include + +extern int remote_desc; +extern int remote_debugging; +extern int kiodebug; + +void remote_open(); +void remote_send(); +void putpkt(); +void getpkt(); + +void write_ok(); +void write_enn(); +void convert_ascii_to_int(); +void convert_int_to_ascii(); +void prepare_resume_reply(); + +/* 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; +{ + struct sgttyb sg; + + remote_debugging = 0; + + remote_desc = open (name, O_RDWR); + if (remote_desc < 0) + printf("\ncould not open remote device\n"); + + ioctl (remote_desc, TIOCGETP, &sg); + sg.sg_flags = RAW; + ioctl (remote_desc, TIOCSETP, &sg); + + if (from_tty) + printf ("Remote debugging using %s\n", name); + remote_debugging = 1; +} + +/* Convert hex digit A to a number. */ + +static int +fromhex (a) + int a; +{ + if (a >= '0' && a <= '9') + return a - '0'; + else if (a >= 'a' && a <= 'f') + return a - 'a' + 10; + else + perror ("Reply contains invalid hex digit"); +} + +/* Convert number NIB to a hex digit. */ + +static int +tohex (nib) + int nib; +{ + if (nib < 10) + return '0'+nib; + else + return 'a'+nib-10; +} + +/* Send the command in BUF to the remote machine, + and read the reply into BUF. + Report an error if we get an error reply. */ + +void +remote_send (buf) + char *buf; +{ + putpkt (buf); + getpkt (buf); + + if (buf[0] == 'E') + perror ("Remote failure reply: %s", buf); +} + +/* Send a packet to the remote machine, with error checking. + The data of the packet is in BUF. */ + +void +putpkt (buf) + char *buf; +{ + int i; + unsigned char csum = 0; + char buf2[500]; + char buf3[1]; + int cnt = strlen (buf); + char *p; + + if (kiodebug) + fprintf (stderr, "Sending packet: %s\n", buf); + + /* Copy the packet into buffer BUF2, encapsulating it + and giving it a checksum. */ + + p = buf2; + *p++ = '$'; + + for (i = 0; i < cnt; i++) + { + csum += buf[i]; + *p++ = buf[i]; + } + *p++ = '#'; + *p++ = tohex ((csum >> 4) & 0xf); + *p++ = tohex (csum & 0xf); + + /* Send it over and over until we get a positive ack. */ + + do { + write (remote_desc, buf2, p - buf2); + read (remote_desc, buf3, 1); + } while (buf3[0] != '+'); +} + +static int +readchar () +{ + char buf[1]; + while (read (remote_desc, buf, 1) != 1) ; + return buf[0] & 0x7f; +} + +/* Read a packet from the remote machine, with error checking, + and store it in BUF. */ + +void +getpkt (buf) + char *buf; +{ + char *bp; + unsigned char csum, c, c1, c2; + extern kiodebug; + + while (1) + { + csum = 0; + while ((c = readchar()) != '$'); + + bp = buf; + while (1) + { + c = readchar (); + if (c == '#') + break; + *bp++ = c; + csum += c; + } + *bp = 0; + + c1 = fromhex (readchar ()); + c2 = fromhex (readchar ()); + if (csum == (c1 << 4) + c2) + break; + + printf ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n", + (c1 << 4) + c2, csum, buf); + write (remote_desc, "-", 1); + } + + write (remote_desc, "+", 1); + + if (kiodebug) + fprintf (stderr,"Packet received :%s\n", buf); +} + + +void +write_ok(buf) + char *buf; +{ + buf[0] = 'O'; + buf[1] = 'k'; + buf[2] = '\0'; +} + +void +write_enn(buf) + char *buf; +{ + buf[0] = 'E'; + buf[1] = 'N'; + buf[2] = 'N'; + buf[3] = '\0'; +} + +void +convert_int_to_ascii(from,to,n) +char *from, *to; int n; +{ + int nib ; + char ch; + while( n-- ) + { + ch = *from++; + nib = ((ch & 0xf0) >> 4)& 0x0f; + *to++ = tohex(nib); + nib = ch & 0x0f; + *to++ = tohex(nib); + } + *to++ = 0; +} + + +void +convert_ascii_to_int(from,to,n) +char *from, *to; int n; +{ + int nib1,nib2 ; + while( n-- ) + { + nib1 = fromhex(*from++); + nib2 = fromhex(*from++); + *to++ = (((nib1 & 0x0f)<< 4)& 0xf0) | (nib2 & 0x0f); + } +} + +void +prepare_resume_reply(buf,status,signal) +char *buf ,status; +unsigned char signal; +{ + int nib; + char ch; + + *buf++ = 'S'; + *buf++ = status; + nib = ((signal & 0xf0) >> 4) ; + *buf++ = tohex(nib); + nib = signal & 0x0f; + *buf++ = tohex(nib); + *buf++ = 0; +} + +void +decode_m_packet(from,mem_addr_ptr,len_ptr) +char *from; +unsigned int *mem_addr_ptr, *len_ptr; +{ + int i = 0, j = 0 ; + char ch; + *mem_addr_ptr = *len_ptr = 0; + /************debugging begin************/ + printf("\nIn decode_m_packet"); + /************debugging end************/ + + while((ch = from[i++]) != ',') + { + *mem_addr_ptr = *mem_addr_ptr << 4; + *mem_addr_ptr |= fromhex(ch) & 0x0f; + } + /************debugging begin************/ + printf("\nFinished mem_addr part"); + /************debugging end************/ + + for(j=0; j < 4; j++) + { + if((ch = from[i++]) == 0) + break; + *len_ptr = *len_ptr << 4; + *len_ptr |= fromhex(ch) & 0x0f; + } + /************debugging begin************/ + printf("\nFinished len_ptr part"); + /************debugging end************/ +} + +void +decode_M_packet(from,mem_addr_ptr,len_ptr,to) +char *from, *to; +unsigned int *mem_addr_ptr, *len_ptr; +{ + int i = 0, j = 0 ; + char ch; + *mem_addr_ptr = *len_ptr = 0; + /************debugging begin************/ + printf("\nIn decode_M_packet"); + /************debugging end************/ + + while((ch = from[i++]) != ',') + { + *mem_addr_ptr = *mem_addr_ptr << 4; + *mem_addr_ptr |= fromhex(ch) & 0x0f; + } + /************debugging begin************/ + printf("\nFinished mem_addr part: memaddr = %x",*mem_addr_ptr); + /************debugging end************/ + + while((ch = from[i++]) != ':') + { + *len_ptr = *len_ptr << 4; + *len_ptr |= fromhex(ch) & 0x0f; + } + /************debugging begin************/ + printf("\nFinished len_ptr part: len = %d",*len_ptr); + /************debugging end************/ + + convert_ascii_to_int(&from[i++],to,*len_ptr); + + /************debugging begin************/ + printf("\nmembuf : %x",*(int *)to); + /************debugging end************/ +} + +SHAR_EOF +# End of shell archive +exit 0 diff --git a/gdb/remote-sa.m68k.shar b/gdb/remote-sa.m68k.shar new file mode 100644 index 0000000000..ca82553f1f --- /dev/null +++ b/gdb/remote-sa.m68k.shar @@ -0,0 +1,893 @@ +# This is a shell archive. Remove anything before this line, +# then unpack it by saving it in a file and typing "sh file". +# +# Wrapped by Glenn Engel on Mon Jun 12 15:19:20 1989 +# +# This archive contains: +# remcom.c +# + +LANG=""; export LANG +PATH=/bin:/usr/bin:$PATH; export PATH + +echo x - remcom.c +cat >remcom.c <<'@EOF' + +/**************************************************************************** + + THIS SOFTWARE IS NOT COPYRIGHTED + + HP offers the following for use in the public domain. HP makes no + warranty with regard to the software or it's performance and the + user accepts the software "AS IS" with all faults. + + HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD + TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +****************************************************************************/ + +/**************************************************************************** + * $Header: remcom.c,v 1.25 89/05/16 14:34:00 glenne Exp $ + * + * $Module name: remcom.c $ + * $Revision: 1.25 $ + * $Date: 89/05/16 14:34:00 $ + * $Contributor: Lake Stevens Instrument Division$ + * + * $Description: low level support for gdb debugger. $ + * + * $Considerations: only works on target hardware $ + * + * $Written by: Glenn Engel $ + * $ModuleState: Experimental $ + * + * $NOTES: See Below $ + * + * To enable debugger support, two things need to happen. One, a + * call to set_debug_traps() is necessary in order to allow any breakpoints + * or error conditions to be properly intercepted and reported to gdb. + * Two, a breakpoint needs to be generated to begin communication. This + * is most easily accomplished by a call to breakpoint(). Breakpoint() + * simulates a breakpoint by executing a trap #1. + * + * Some explanation is probably necessary to explain how exceptions are + * handled. When an exception is encountered the 68000 pushes the current + * program counter and status register onto the supervisor stack and then + * transfers execution to a location specified in it's vector table. + * The handlers for the exception vectors are hardwired to jmp to an address + * given by the relation: (exception - 256) * 6. These are decending + * addresses starting from -6, -12, -18, ... By allowing 6 bytes for + * each entry, a jsr, jmp, bsr, ... can be used to enter the exception + * handler. Using a jsr to handle an exception has an added benefit of + * allowing a single handler to service several exceptions and use the + * return address as the key differentiation. The vector number can be + * computed from the return address by [ exception = (addr + 1530) / 6 ]. + * The sole purpose of the routine _catchException is to compute the + * exception number and push it on the stack in place of the return address. + * The external function exceptionHandler() is + * used to attach a specific handler to a specific 68k exception. + * For 68020 machines, the ability to have a return address around just + * so the vector can be determined is not necessary because the '020 pushes an + * extra word onto the stack containing the vector offset + * + * Because gdb will sometimes write to the stack area to execute function + * calls, this program cannot rely on using the supervisor stack so it + * uses it's own stack area reserved in the int array remcomStack. + * + ************* + * + * The following gdb commands are supported: + * + * command function Return value + * + * g return the value of the CPU registers hex data or ENN + * G set the value of the CPU registers OK or ENN + * + * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN + * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN + * + * c Resume at current address SNN ( signal NN) + * cAA..AA Continue at address AA..AA SNN + * + * s Step one instruction SNN + * sAA..AA Step one instruction from AA..AA SNN + * + * k kill + * + * ? What was the last sigval ? SNN (signal NN) + * + * All commands and responses are sent with a packet which includes a + * checksum. A packet consists of + * + * $#. + * + * where + * :: + * :: < two hex digits computed as modulo 256 sum of > + * + * When a packet is received, it is first acknowledged with either '+' or '-'. + * '+' indicates a successful transfer. '-' indicates a failed transfer. + * + * Example: + * + * Host: Reply: + * $m0,10#2a +$00010203040506070809101112131415#42 + * + ****************************************************************************/ + +#include +#include +#include + +/************************************************************************ + * + * external low-level support routines + */ +typedef void (*ExceptionHook)(int); /* pointer to function with int parm */ +typedef void (*Function)(); /* pointer to a function */ + +extern putDebugChar(); /* write a single character */ +extern getDebugChar(); /* read and return a single char */ + +extern Function exceptionHandler(); /* assign an exception handler */ +extern ExceptionHook exceptionHook; /* hook variable for errors/exceptions */ + + +/************************************************************************/ +/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ +/* at least NUMREGBYTES*2 are needed for register packets */ +#define BUFMAX 400 + +static char initialized; /* boolean flag. != 0 means we've been initialized */ + +int remote_debug = 0; +/* debug > 0 prints ill-formed commands in valid packets & checksum errors */ + +char hexchars[]="0123456789abcdef"; + +/* there are 180 bytes of registers on a 68020 w/68881 */ +/* many of the fpa registers are 12 byte (96 bit) registers */ +#define NUMREGBYTES 180 +enum regnames {D0,D1,D2,D3,D4,D5,D6,D7, + A0,A1,A2,A3,A4,A5,A6,A7, + PS,PC, + FP0,FP1,FP2,FP3,FP4,FP5,FP6,FP7, + FPCONTROL,FPSTATUS,FPIADDR + }; + +typedef struct FrameStruct +{ + struct FrameStruct *previous; + int exceptionPC; /* pc value when this frame created */ + int exceptionVector; /* cpu vector causing exception */ + short frameSize; /* size of cpu frame in words */ + short sr; /* for 68000, this not always sr */ + int pc; + short format; + int fsaveHeader; + int morejunk[0]; /* exception frame, fp save... */ +} Frame; + +#define FRAMESIZE 500 +static Frame *lastFrame; +static int frameStack[FRAMESIZE]; + +/* + * these should not be static cuz they can be used outside this module + */ +int registers[NUMREGBYTES/4]; +int superStack; + +static int remcomStack[400]; +static int* stackPtr = &remcomStack[399]; + +/* + * In many cases, the system will want to continue exception processing + * when a continue command is given. + * oldExceptionHook is a function to invoke in this case. + */ + +static ExceptionHook oldExceptionHook; + +/* the size of the exception stack on the 68020 varies with the type of + * exception. The following table is the number of WORDS used + * for each exception format. + */ +static short exceptionSize[] = { 4,4,6,4,4,4,4,4,29,10,16,46,4,4,4,4 }; + +/************* jump buffer used for setjmp/longjmp **************************/ +jmp_buf env; + +/*************************** ASSEMBLY CODE MACROS *************************/ +/* */ + +#ifdef __HAVE_68881__ +/* do an fsave, then remember the address to begin a restore from */ +#define SAVE_FP_REGS() asm(" fsave a0@-"); \ + asm(" fmovemx fp0-fp7,_registers+72"); \ + asm(" fmoveml fpcr/fpsr/fpi,_registers+168"); +#define RESTORE_FP_REGS() asm(" fmoveml _registers+168,fpcr/fpsr/fpi"); \ + asm(" fmovemx _registers+72,fp0-fp7"); \ + asm(" frestore a0@+"); +#else +#define SAVE_FP_REGS() +#define RESTORE_FP_REGS() +#endif /* __HAVE_68881__ */ + +asm(" +.text +.globl _return_to_super +_return_to_super: + movel _registers+60,sp /* get new stack pointer */ + movel _lastFrame,a0 /* get last frame info */ + bra return_to_any + +.globl _return_to_user +_return_to_user: + movel _registers+60,a0 /* get usp */ + movel a0,usp /* set usp */ + movel _superStack,sp /* get original stack pointer */ + +return_to_any: + movel _lastFrame,a0 /* get last frame info */ + movel a0@+,_lastFrame /* link in previous frame */ + addql #8,a0 /* skip over pc, vector#*/ + movew a0@+,d0 /* get # of words in cpu frame */ + addw d0,a0 /* point to end of data */ + addw d0,a0 /* point to end of data */ + movel a0,a1 +# +# copy the stack frame + subql #1,d0 +copyUserLoop: + movew a1@-,sp@- + dbf d0,copyUserLoop +"); + RESTORE_FP_REGS() + asm(" moveml _registers,d0-d7/a0-a6"); + asm(" rte"); /* pop and go! */ + +#define DISABLE_INTERRUPTS() asm(" oriw #0x0700,sr"); +#define BREAKPOINT() asm(" trap #1"); + +/* this function is called immediately when a level 7 interrupt occurs */ +/* if the previous interrupt level was 7 then we're already servicing */ +/* this interrupt and an rte is in order to return to the debugger. */ +/* For the 68000, the offset for sr is 6 due to the jsr return address */ +asm(" +.text +.globl __debug_level7 +__debug_level7: + movew d0,sp@-"); +#ifdef mc68020 +asm(" movew sp@(2),d0"); +#else +asm(" movew sp@(6),d0"); +#endif +asm(" andiw #0x700,d0 + cmpiw #0x700,d0 + beq _already7 + movew sp@+,d0 + bra __catchException +_already7: + movew sp@+,d0"); +#ifndef mc68020 +asm(" lea sp@(4),sp"); /* pull off 68000 return address */ +#endif +asm(" rte"); + +extern void _catchException(); + +#ifdef mc68020 +/* This function is called when a 68020 exception occurs. It saves + * all the cpu and fpcp regs in the _registers array, creates a frame on a + * linked list of frames which has the cpu and fpcp stack frames needed + * to properly restore the context of these processors, and invokes + * an exception handler (remcom_handler). + * + * stack on entry: stack on exit: + * N bytes of junk exception # MSWord + * Exception Format Word exception # MSWord + * Program counter LSWord + * Program counter MSWord + * Status Register + * + * + */ +asm(" +.text +.globl __catchException +__catchException:"); +DISABLE_INTERRUPTS(); +asm(" + moveml d0-d7/a0-a6,_registers /* save registers */ + movel _lastFrame,a0 /* last frame pointer */ +"); +SAVE_FP_REGS(); +asm(" + lea _registers,a5 /* get address of registers */ + movew sp@,d1 /* get status register */ + movew d1,a5@(66) /* save sr */ + movel sp@(2),a4 /* save pc in a4 for later use */ + movel a4,a5@(68) /* save pc in _regisers[] */ + +# +# figure out how many bytes in the stack frame + movew sp@(6),d0 /* get '020 exception format */ + movew d0,d2 /* make a copy of format word */ + andiw #0xf000,d0 /* mask off format type */ + rolw #5,d0 /* rotate into the low byte *2 */ + lea _exceptionSize,a1 + addw d0,a1 /* index into the table */ + movew a1@,d0 /* get number of words in frame */ + movew d0,d3 /* save it */ + subw d0,a0 /* adjust save pointer */ + subw d0,a0 /* adjust save pointer(bytes) */ + movel a0,a1 /* copy save pointer */ + subql #1,d0 /* predecrement loop counter */ +# +# copy the frame +saveFrameLoop: + movew sp@+,a1@+ + dbf d0,saveFrameLoop +# +# now that the stack has been clenaed, +# save the a7 in use at time of exception + movel sp,_superStack /* save supervisor sp */ + andiw #0x2000,d1 /* were we in supervisor mode ? */ + beq userMode + movel a7,a5@(60) /* save a7 */ + bra a7saveDone +userMode: + movel usp,a1 + movel a1,a5@(60) /* save user stack pointer */ +a7saveDone: + +# +# save size of frame + movew d3,a0@- + +# +# compute exception number + andl #0xfff,d2 /* mask off vector offset */ + lsrw #2,d2 /* divide by 4 to get vect num */ + movel d2,a0@- /* save it */ +# +# save pc causing exception + movel a4,a0@- +# +# save old frame link and set the new value + movel _lastFrame,a1 /* last frame pointer */ + movel a1,a0@- /* save pointer to prev frame */ + movel a0,_lastFrame + + movel d2,sp@- /* push exception num */ + movel _exceptionHook,a0 /* get address of handler */ + jbsr a0@ /* and call it */ + jmp __returnFromException /* now, return */ +"); +#else /* mc68000 */ +/* This function is called when an exception occurs. It translates the + * return address found on the stack into an exception vector # which + * is then handled by either handle_exception or a system handler. + * _catchException provides a front end for both. + * + * stack on entry: stack on exit: + * Program counter MSWord exception # MSWord + * Program counter LSWord exception # MSWord + * Status Register + * Return Address MSWord + * Return Address LSWord + */ +asm(" +.text +.globl __catchException +__catchException:"); +DISABLE_INTERRUPTS(); +asm(" + moveml d0-d7/a0-a6,_registers /* save registers */ + movel _lastFrame,a0 /* last frame pointer */ +"); +SAVE_FP_REGS(); +asm(" + lea _registers,a5 /* get address of registers */ + movel sp@+,d2 /* pop return address */ + addl #1530,d2 /* convert return addr to */ + divs #6,d2 /* exception number */ + extl d2 + + moveql #3,d3 /* assume a three word frame */ + + cmpiw #3,d2 /* bus error or address error ? */ + bgt normal /* if >3 then normal error */ + movel sp@+,a0@- /* copy error info to frame buff*/ + movel sp@+,a0@- /* these are never used */ + moveql #7,d3 /* this is a 7 word frame */ + +normal: + movew sp@+,d1 /* pop status register */ + movel sp@+,a4 /* pop program counter */ + movew d1,a5@(66) /* save sr */ + movel a4,a5@(68) /* save pc in _regisers[] */ + movel a4,a0@- /* copy pc to frame buffer */ + movew d1,a0@- /* copy sr to frame buffer */ + + movel sp,_superStack /* save supervisor sp */ + + andiw #0x2000,d1 /* were we in supervisor mode ? */ + beq userMode + movel a7,a5@(60) /* save a7 */ + bra saveDone +userMode: + movel usp,a1 /* save user stack pointer */ + movel a1,a5@(60) /* save user stack pointer */ +saveDone: + + movew d3,a0@- /* push frame size in words */ + movel d2,a0@- /* push vector number */ + movel a4,a0@- /* push exception pc */ + +# +# save old frame link and set the new value + movel _lastFrame,a1 /* last frame pointer */ + movel a1,a0@- /* save pointer to prev frame */ + movel a0,_lastFrame + + movel d2,sp@- /* push exception num */ + movel _exceptionHook,a0 /* get address of handler */ + jbsr a0@ /* and call it */ + jmp __returnFromException /* now, return */ +"); +#endif + + +/* + * remcomHandler is a front end for handle_exception. It moves the + * stack pointer into an area reserved for debugger use in case the + * breakpoint happened in supervisor mode. + */ +asm("_remcomHandler:"); +asm(" addl #4,sp"); /* pop off return address */ +asm(" movel sp@+,d0"); /* get the exception number */ +asm(" movel _stackPtr,sp"); /* move to remcom stack area */ +asm(" movel d0,sp@-"); /* push exception onto stack */ +asm(" jbsr _handle_exception"); /* this never returns */ +asm(" rts"); /* return */ + +void _returnFromException( Frame *frame ) +{ + /* if no existing frame, dummy one up */ + if (! frame) + { + frame = lastFrame -1; + frame->frameSize = 4; + frame->format = 0; + frame->fsaveHeader = 0; + frame->previous = lastFrame; + } + +#ifndef mc68020 + /* a 68000 cannot use the internal info pushed onto a bus error + * or address error frame when doing an RTE so don't put this info + * onto the stack or the stack will creep every time this happens. + */ + frame->frameSize=3; +#endif + + /* throw away any frames in the list after this frame */ + lastFrame = frame; + + frame->sr = registers[(int) PS]; + frame->pc = registers[(int) PC]; + + if (registers[(int) PS] & 0x2000) + { + /* return to supervisor mode... */ + return_to_super(); + } + else + { /* return to user mode */ + return_to_user(); + } +} + +int hex(ch) +char ch; +{ + if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10); + if ((ch >= '0') && (ch <= '9')) return (ch-'0'); + return (0); +} + + +/* scan for the sequence $# */ +void getpacket(buffer) +char * buffer; +{ + unsigned char checksum; + unsigned char xmitcsum; + int i; + int count; + char ch; + + do { + /* wait around for the start character, ignore all other characters */ + while ((ch = getDebugChar()) != '$'); + checksum = 0; + count = 0; + + /* now, read until a # or end of buffer is found */ + while (count < BUFMAX) { + ch = getDebugChar(); + if (ch == '#') break; + checksum = checksum + ch; + buffer[count] = ch; + count = count + 1; + } + buffer[count] = 0; + + if (ch == '#') { + xmitcsum = hex(getDebugChar()) << 4; + xmitcsum += hex(getDebugChar()); + if ((remote_debug ) && (checksum != xmitcsum)) { + fprintf(stderr,"bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n", + checksum,xmitcsum,buffer); + } + + if (checksum != xmitcsum) putDebugChar('-'); /* failed checksum */ + else { + putDebugChar('+'); /* successful transfer */ + /* if a sequence char is present, reply the sequence ID */ + if (buffer[2] == ':') { + putDebugChar( buffer[0] ); + putDebugChar( buffer[1] ); + /* remove sequence chars from buffer */ + count = strlen(buffer); + for (i=3; i <= count; i++) buffer[i-3] = buffer[i]; + } + } + } + } while (checksum != xmitcsum); + +} + +/* send the packet in buffer. The host get's one chance to read it. + This routine does not wait for a positive acknowledge. */ + + +void putpacket(buffer) +char * buffer; +{ + unsigned char checksum; + int count; + char ch; + + /* $#. */ + do { + putDebugChar('$'); + checksum = 0; + count = 0; + + while (ch=buffer[count]) { + if (! putDebugChar(ch)) return; + checksum += ch; + count += 1; + } + + putDebugChar('#'); + putDebugChar(hexchars[checksum >> 4]); + putDebugChar(hexchars[checksum % 16]); + + } while (1 == 0); /* (getDebugChar() != '+'); */ + +} + +static char inbuffer[BUFMAX]; +static char outbuffer[BUFMAX]; +static short error; + + +void debug_error(format, parm) +char * format; +char * parm; +{ + if (remote_debug) fprintf(stderr,format,parm); +} + +/* convert the memory pointed to by mem into hex, placing result in buf */ +/* return a pointer to the last char put in buf (null) */ +char* mem2hex(mem, buf, count) +char* mem; +char* buf; +int count; +{ + int i; + unsigned char ch; + for (i=0;i> 4]; + *buf++ = hexchars[ch % 16]; + } + *buf = 0; + return(buf); +} + +/* convert the hex array pointed to by buf into binary to be placed in mem */ +/* return a pointer to the character AFTER the last byte written */ +char* hex2mem(buf, mem, count) +char* buf; +char* mem; +int count; +{ + int i; + unsigned char ch; + for (i=0;iexceptionPC, + frame->exceptionVector); + if (frame->exceptionPC == newPC) break; /* bingo! a match */ + /* + * for a breakpoint instruction, the saved pc may + * be off by two due to re-executing the instruction + * replaced by the trap instruction. Check for this. + */ + if ((frame->exceptionVector == 33) && + (frame->exceptionPC == (newPC+2))) break; + frame = frame->previous; + } + + /* + * If we found a match for the PC AND we are not returning + * as a result of a breakpoint (33), + * trace exception (9), nmi (31), jmp to + * the old exception handler as if this code never ran. + */ + if (frame) + { + if ((frame->exceptionVector != 9) && + (frame->exceptionVector != 31) && + (frame->exceptionVector != 33)) + { + /* + * invoke the previous handler. + */ + if (oldExceptionHook) + (*oldExceptionHook) (frame->exceptionVector); + newPC = registers[ PC ]; /* pc may have changed */ + if (newPC != frame->exceptionPC) + { + if (remote_debug) + printf("frame at 0x%x has pc=0x%x, except#=%d\n", + frame,frame->exceptionPC, + frame->exceptionVector); + /* dispose of this frame, we're skipping it (longjump?)*/ + lastFrame = frame->previous; + frame = (Frame *) 0; + } + } + } + + _returnFromException( frame ); + + break; + + /* kill the program */ + case 'k' : /* do nothing */ + break; + } /* switch */ + + /* reply to the request */ + putpacket(outbuffer); + } +} + + +/* this function is used to set up exception handlers for tracing and + breakpoints */ +void set_debug_traps() +{ +extern void _debug_level7(); +extern void remcomHandler(); +int exception; + + for (exception = 2; exception <= 23; exception++) + exceptionHandler(exception,_catchException); + + /* level 7 interrupt */ + exceptionHandler(31,_debug_level7); + + /* breakpoint exception (trap #1) */ + exceptionHandler(33,_catchException); + + /* floating point error (trap #8) */ + exceptionHandler(40,_catchException); + + /* 48 to 54 are floating point coprocessor errors */ + for (exception = 48; exception <= 54; exception++) + exceptionHandler(exception,_catchException); + + if (oldExceptionHook != remcomHandler) + { + oldExceptionHook = exceptionHook; + exceptionHook = remcomHandler; + } + + initialized = 1; + + lastFrame = (Frame *) &frameStack[FRAMESIZE-1]; + lastFrame->previous = (Frame *) 0; +} + +/* This function will generate a breakpoint exception. It is used at the + beginning of a program to sync up with a debugger and can be used + otherwise as a quick means to stop program execution and "break" into + the debugger. */ + +void breakpoint() +{ + if (initialized) BREAKPOINT(); +} + +@EOF + +chmod 444 remcom.c + +exit 0 + diff --git a/gdb/remote.c b/gdb/remote.c index 6abd8e255f..66f3b2c084 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -1,22 +1,21 @@ /* Memory-access and commands for inferior process, for GDB. - Copyright (C) 1988 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! -*/ + 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. */ /* Remote communication protocol. All values are encoded in ascii hex digits. @@ -55,6 +54,11 @@ anyone else from sharing it farther. Help stamp out software hoarding! If AA..AA is omitted, resume at same address. + last signal ? Reply the current reason for stopping. + This is the same reply as is generated + for step or cont : SAA where AA is the + signal number. + There is no immediate reply to step or cont. The reply comes when the machine stops. It is SAA AA is the "signal number" @@ -93,21 +97,44 @@ anyone else from sharing it farther. Help stamp out software hoarding! #define TERMINAL struct sgttyb #endif -int kiodebug; +static int kiodebug; +static int timeout = 5; +#if 0 int icache; +#endif -/* Descriptor for I/O to remote machine. */ -int remote_desc; +/* Descriptor for I/O to remote machine. Initialize it to -1 so that + remote_open knows that we don't have a file open when the program + starts. */ +int remote_desc = -1; #define PBUFSIZ 400 +/* Maximum number of bytes to read/write at once. The value here + is chosen to fill up a packet (the headers account for the 32). */ +#define MAXBUFBYTES ((PBUFSIZ-32)/2) + static void remote_send (); static void putpkt (); static void getpkt (); +#if 0 static void dcache_flush (); +#endif +/* Called when SIGALRM signal sent due to alarm() timeout. */ +#ifndef HAVE_TERMIO +void +remote_timer () +{ + if (kiodebug) + printf ("remote_timer called\n"); + + alarm (timeout); +} +#endif + /* Open a connection to a remote debugger. NAME is the filename used for communication. */ @@ -118,8 +145,13 @@ remote_open (name, from_tty) { TERMINAL sg; + if (remote_desc >= 0) + close (remote_desc); + remote_debugging = 0; +#if 0 dcache_init (); +#endif remote_desc = open (name, O_RDWR); if (remote_desc < 0) @@ -127,7 +159,9 @@ remote_open (name, from_tty) ioctl (remote_desc, TIOCGETP, &sg); #ifdef HAVE_TERMIO - sg.c_lflag &= ~ICANON; + sg.c_cc[VMIN] = 0; /* read with timeout. */ + sg.c_cc[VTIME] = timeout * 10; + sg.c_lflag &= ~(ICANON | ECHO); #else sg.sg_flags = RAW; #endif @@ -136,8 +170,45 @@ remote_open (name, from_tty) if (from_tty) printf ("Remote debugging using %s\n", name); remote_debugging = 1; + +#ifndef HAVE_TERMIO +#ifndef NO_SIGINTERRUPT + /* Cause SIGALRM's to make reads fail. */ + if (siginterrupt (SIGALRM, 1) != 0) + perror ("remote_open: error in siginterrupt"); +#endif + + /* Set up read timeout timer. */ + if ((void (*)) signal (SIGALRM, remote_timer) == (void (*)) -1) + perror ("remote_open: error in signal"); +#endif + + putpkt ("?"); /* initiate a query from remote machine */ } +/* 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 ("Can't close remote connection: not debugging remotely."); + + close (remote_desc); /* This should never be called if + there isn't something valid in + remote_desc. */ + + /* Do not try to close remote_desc again, later in the program. */ + remote_desc = -1; + + if (from_tty) + printf ("Ending remote debugging\n"); + + remote_debugging = 0; +} + /* Convert hex digit A to a number. */ static int @@ -172,7 +243,9 @@ remote_resume (step, signal) { char buf[PBUFSIZ]; +#if 0 dcache_flush (); +#endif strcpy (buf, step ? "s": "c"); @@ -186,7 +259,7 @@ int remote_wait (status) WAITTYPE *status; { - char buf[PBUFSIZ]; + unsigned char buf[PBUFSIZ]; WSETEXIT ((*status), 0); getpkt (buf); @@ -244,10 +317,12 @@ remote_store_registers (regs) *p++ = tohex ((regs[i] >> 4) & 0xf); *p++ = tohex (regs[i] & 0xf); } + *p = '\0'; remote_send (buf); } +#if 0 /* Read a word from remote address ADDR and return it. This goes through the data cache. */ @@ -279,6 +354,18 @@ remote_store_word (addr, word) { dcache_poke (addr, word); } +#else /* not 0 */ +void remote_fetch_word (addr) + CORE_ADDR addr; +{ + error ("Internal error: remote_fetch_word is obsolete.\n"); +} +void remote_store_word (addr) + CORE_ADDR addr; +{ + error ("Internal error: remote_store_word is obsolete.\n"); +} +#endif /* not 0 */ /* Write memory data directly to the remote machine. This does not inform the data cache; the data cache uses this. @@ -310,6 +397,7 @@ remote_write_bytes (memaddr, myaddr, len) *p++ = tohex ((myaddr[i] >> 4) & 0xf); *p++ = tohex (myaddr[i] & 0xf); } + *p = '\0'; remote_send (buf); } @@ -349,6 +437,55 @@ remote_read_bytes (memaddr, myaddr, len) } } +/* Read LEN bytes from inferior memory at MEMADDR. Put the result + at debugger address MYADDR. Returns errno value. */ +int +remote_read_inferior_memory(memaddr, myaddr, len) + CORE_ADDR memaddr; + char *myaddr; + int len; +{ + int xfersize; + while (len > 0) + { + if (len > MAXBUFBYTES) + xfersize = MAXBUFBYTES; + else + xfersize = len; + + remote_read_bytes (memaddr, myaddr, xfersize); + memaddr += xfersize; + myaddr += xfersize; + len -= xfersize; + } + return 0; /* no error */ +} + +/* Copy LEN bytes of data from debugger memory at MYADDR + to inferior's memory at MEMADDR. Returns errno value. */ +int +remote_write_inferior_memory (memaddr, myaddr, len) + CORE_ADDR memaddr; + char *myaddr; + int len; +{ + int xfersize; + while (len > 0) + { + if (len > MAXBUFBYTES) + xfersize = MAXBUFBYTES; + else + xfersize = len; + + remote_write_bytes(memaddr, myaddr, xfersize); + + memaddr += xfersize; + myaddr += xfersize; + len -= xfersize; + } + return 0; /* no error */ +} + /* A debug packet whose contents are @@ -370,6 +507,24 @@ Receiver responds with: */ +static int +readchar () +{ + char buf; + + buf = '\0'; +#ifdef HAVE_TERMIO + /* termio does the timeout for us. */ + read (remote_desc, &buf, 1); +#else + alarm (timeout); + read (remote_desc, &buf, 1); + alarm (0); +#endif + + return buf & 0x7f; +} + /* Send the command in BUF to the remote machine, and read the reply into BUF. Report an error if we get an error reply. */ @@ -394,15 +549,13 @@ putpkt (buf) char *buf; { int i; - char csum = 0; + unsigned char csum = 0; char buf2[500]; char buf3[1]; int cnt = strlen (buf); + char ch; char *p; - if (kiodebug) - fprintf (stderr, "Sending packet: %s\n", buf); - /* Copy the packet into buffer BUF2, encapsulating it and giving it a checksum. */ @@ -421,17 +574,18 @@ putpkt (buf) /* Send it over and over until we get a positive ack. */ do { + if (kiodebug) + { + *p = '\0'; + printf ("Sending packet: %s (%s)\n", buf2, buf); + } write (remote_desc, buf2, p - buf2); - read (remote_desc, buf3, 1); - } while (buf3[0] != '+'); -} -static int -readchar () -{ - char buf[1]; - while (read (remote_desc, buf, 1) != 1) ; - return buf[0] & 0x7f; + /* read until either a timeout occurs (\0) or '+' is read */ + do { + ch = readchar (); + } while ((ch != '+') && (ch != '\0')); + } while (ch != '+'); } /* Read a packet from the remote machine, with error checking, @@ -443,9 +597,13 @@ getpkt (buf) { char *bp; unsigned char csum; - unsigned int c, c1, c2; + int c; + unsigned char c1, c2; extern kiodebug; + /* allow immediate quit while reading from device, it could be hung */ + immediate_quit++; + while (1) { /* Force csum to be zero here because of possible error retry. */ @@ -466,19 +624,31 @@ getpkt (buf) c1 = fromhex (readchar ()); c2 = fromhex (readchar ()); - if (csum == (c1 << 4) + c2) + if ((csum & 0xff) == (c1 << 4) + c2) break; printf ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n", - (c1 << 4) + c2, csum, buf); + (c1 << 4) + c2, csum & 0xff, buf); write (remote_desc, "-", 1); } + immediate_quit--; + write (remote_desc, "+", 1); if (kiodebug) fprintf (stderr,"Packet received :%s\n", buf); } +/* The data cache leads to incorrect results because it doesn't know about + volatile variables, thus making it impossible to debug functions which + use hardware registers. Therefore it is #if 0'd out. Effect on + performance is some, for backtraces of functions with a few + arguments each. For functions with many arguments, the stack + frames don't fit in the cache blocks, which makes the cache less + helpful. Disabling the cache is a big performance win for fetching + large structures, because the cache code fetched data in 16-byte + chunks. */ +#if 0 /* The data cache records all the data read from the remote machine since the last time it stopped. @@ -620,4 +790,4 @@ dcache_init () for (i=0;inext; } if (cs_pst) - current_source_symtab = psymtab_to_symtab (cs_pst); + if (cs_pst->readin) + fatal ("Internal: select_source_symtab: readin pst found and no symtabs."); + else + current_source_symtab = psymtab_to_symtab (cs_pst); else current_source_symtab = 0; current_source_line = 1; @@ -146,6 +159,8 @@ directory_command (dirname, from_tty) { char *old = source_path; + dont_repeat (); + if (dirname == 0) { if (query ("Reinitialize source path to %s? ", current_directory)) @@ -156,76 +171,109 @@ directory_command (dirname, from_tty) } else { - struct stat st; - register int len = strlen (dirname); - register char *tem; - extern char *index (); - - if (index (dirname, ':')) - error ("Please add one directory at a time to the source path."); - if (dirname[len - 1] == '/') - /* Sigh. "foo/" => "foo" */ - dirname[--len] == '\0'; - - while (dirname[len - 1] == '.') + dirname = tilde_expand (dirname); + make_cleanup (free, dirname); + + do { - if (len == 1) - { - /* "." => getwd () */ - dirname = current_directory; - goto append; - } - else if (dirname[len - 2] == '/') + extern char *index (); + char *name = dirname; + register char *p; + struct stat st; + + { + char *colon = index (name, ':'); + char *space = index (name, ' '); + char *tab = index (name, '\t'); + if (colon == 0 && space == 0 && tab == 0) + p = dirname = name + strlen (name); + else + { + p = 0; + if (colon != 0 && (p == 0 || colon < p)) + p = colon; + if (space != 0 && (p == 0 || space < p)) + p = space; + if (tab != 0 && (p == 0 || tab < p)) + p = tab; + dirname = p + 1; + while (*dirname == ':' || *dirname == ' ' || *dirname == '\t') + ++dirname; + } + } + + if (p[-1] == '/') + /* Sigh. "foo/" => "foo" */ + --p; + *p = '\0'; + + while (p[-1] == '.') { - if (len == 2) + if (p - name == 1) { - /* "/." => "/" */ - dirname[--len] = '\0'; + /* "." => getwd (). */ + name = current_directory; goto append; } - else + else if (p[-2] == '/') { - /* "...foo/." => "...foo" */ - dirname[len -= 2] = '\0'; - continue; + if (p - name == 2) + { + /* "/." => "/". */ + *--p = '\0'; + goto append; + } + else + { + /* "...foo/." => "...foo". */ + p -= 2; + *p = '\0'; + continue; + } } + else + break; } - break; - } - - if (dirname[0] != '/') - dirname = concat (current_directory, "/", dirname); - else - dirname = savestring (dirname, len); - make_cleanup (free, dirname); - if (stat (dirname, &st) < 0) - perror_with_name (dirname); - if ((st.st_mode & S_IFMT) != S_IFDIR) - error ("%s is not a directory.", dirname); - - append: - len = strlen (dirname); - tem = source_path; - while (1) - { - if (!strncmp (tem, dirname, len) - && (tem[len] == '\0' || tem[len] == ':')) - { - printf ("\"%s\" is already in the source path.\n", - dirname); - break; - } - tem = index (tem, ':'); - if (tem) - tem++; + if (*name != '/') + name = concat (current_directory, "/", name); else - { - source_path = concat (old, ":", dirname); - free (old); - break; - } - } + name = savestring (name, p - name); + make_cleanup (free, name); + + if (stat (name, &st) < 0) + perror_with_name (name); + if ((st.st_mode & S_IFMT) != S_IFDIR) + error ("%s is not a directory.", name); + + append: + { + register unsigned int len = strlen (name); + + p = source_path; + while (1) + { + if (!strncmp (p, name, len) + && (p[len] == '\0' || p[len] == ':')) + { + if (from_tty) + printf ("\"%s\" is already in the source path.\n", name); + break; + } + p = index (p, ':'); + if (p != 0) + ++p; + else + break; + } + if (p == 0) + { + source_path = concat (old, ":", name); + free (old); + old = source_path; + } + } + } while (*dirname != '\0'); if (from_tty) directories_info (); } @@ -257,6 +305,9 @@ openp (path, try_cwd_first, string, mode, prot, filename_opened) register char *p, *p1; register int len; + if (!path) + path = "."; + /* ./foo => foo */ while (string[0] == '.' && string[1] == '/') string += 2; @@ -433,9 +484,10 @@ identify_source_line (s, line, mid_statement) get_filename_and_charpos (s, line, 0); if (s->fullname == 0) return 0; - printf ("\032\032%s:%d:%d:%s\n", s->fullname, + printf ("\032\032%s:%d:%d:%s:0x%x\n", s->fullname, line, s->line_charpos[line - 1], - mid_statement ? "middle" : "beg"); + mid_statement ? "middle" : "beg", + get_frame_pc (get_current_frame())); current_source_line = line; first_line_listed = line; last_line_listed = line; @@ -495,18 +547,15 @@ print_source_lines (s, line, stopline, noerror) c = fgetc (stream); if (c == EOF) break; last_line_listed = current_source_line; - printf ("%d\t", current_source_line++); + printf_filtered ("%d\t", current_source_line++); do { if (c < 040 && c != '\t' && c != '\n') - { - fputc ('^', stdout); - fputc (c + 0100, stdout); - } + printf_filtered ("^%c", c + 0100); else if (c == 0177) - printf ("^?"); + printf_filtered ("^?"); else - fputc (c, stdout); + printf_filtered ("%c", c); } while (c != '\n' && (c = fgetc (stream)) >= 0); } @@ -550,12 +599,12 @@ list_command (arg, from_tty) char *p; if (symtab_list == 0 && partial_symtab_list == 0) - error ("Listing source lines requires symbols."); + error ("No symbol table is loaded. Use the \"symbol-file\" command."); /* Pull in a current source symtab if necessary */ if (current_source_symtab == 0 && (arg == 0 || arg[0] == '+' || arg[0] == '-')) - select_source_symtab (symtab_list); + select_source_symtab (0); /* "l" or "l +" lists next ten lines. */ @@ -768,8 +817,8 @@ forward_search_command (regex, from_tty) if (msg) error (msg); - if (current_source_symtab == 0) - error ("No default source file yet. Do \"help list\"."); + if (current_source_symtab == 0) + select_source_symtab (0); /* Search from last_line_listed+1 in current_source_symtab */ @@ -838,8 +887,8 @@ reverse_search_command (regex, from_tty) if (msg) error (msg); - if (current_source_symtab == 0) - error ("No default source file yet. Do \"help list\"."); + if (current_source_symtab == 0) + select_source_symtab (0); /* Search from last_line_listed-1 in current_source_symtab */ diff --git a/gdb/sparc-dep.c b/gdb/sparc-dep.c index 2d53a0400f..2a73c680fd 100644 --- a/gdb/sparc-dep.c +++ b/gdb/sparc-dep.c @@ -1,32 +1,29 @@ /* Machine-dependent code which would otherwise be in inflow.c and core.c, for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc. This code is for the sparc cpu. -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. +This file is part of GDB. -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. +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. -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! -*/ +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 "frame.h" #include "inferior.h" #include "obstack.h" -#include "sparc-opcode.h" -#include "gdbcore.h" #include #include @@ -46,6 +43,11 @@ anyone else from sharing it farther. Help stamp out software hoarding! extern int errno; extern int attach_flag; + +typedef enum +{ + Error, not_branch, bicc, bicca, ba, baa, ticc, ta, +} branch_type; /* This function simply calls ptrace with the given arguments. It exists so that all calls to ptrace are isolated in this @@ -130,15 +132,16 @@ single_step (signal) if (br == bicca) { /* Conditional annulled branch will either end up at - npc (if taken) or at npc+4 (if not taken). Trap npc+4. */ + npc (if taken) or at npc+4 (if not taken). + Trap npc+4. */ brknpc4 = 1; read_memory (npc4, break_mem[1], sizeof break_insn); write_memory (npc4, break_insn, sizeof break_insn); } else if (br == baa && target != next_pc) - { + { /* Unconditional annulled branch will always end up at - the target. */ + the target. */ brktrg = 1; read_memory (target, break_mem[2], sizeof break_insn); write_memory (target, break_insn, sizeof break_insn); @@ -426,11 +429,6 @@ write_inferior_memory (memaddr, myaddr, len) /* Machine-dependent code which would otherwise be in core.c */ /* Work with core dump and executable files, for GDB. */ -/* Recognize COFF format systems because a.out.h defines AOUTHDR. */ -#ifdef AOUTHDR -#define COFF_FORMAT -#endif - #ifndef N_TXTADDR #define N_TXTADDR(hdr) 0 #endif /* no N_TXTADDR */ @@ -439,6 +437,15 @@ write_inferior_memory (memaddr, myaddr, len) #define N_DATADDR(hdr) hdr.a_text #endif /* no N_DATADDR */ +/* Non-zero if this is an object (.o) file, rather than an executable. + Distinguishing between the two is rarely necessary (and seems like + a hack, but there is no other way to get the text and data + addresses--N_TXTADDR should probably take care of + this, but it doesn't). */ +/* This definition will not work + if someone decides to make ld preserve relocation info. */ +#define IS_OBJECT_FILE(hdr) (hdr.a_trsize != 0) + /* Make COFF and non-COFF names for things a little more compatible to reduce conditionals later. */ @@ -447,8 +454,10 @@ write_inferior_memory (memaddr, myaddr, len) #endif #ifndef COFF_FORMAT +#ifndef AOUTHDR #define AOUTHDR struct exec #endif +#endif extern char *sys_siglist[]; @@ -456,6 +465,55 @@ extern char *sys_siglist[]; 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 */ @@ -503,6 +561,9 @@ core_file_command (filename, from_tty) 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); @@ -522,8 +583,7 @@ core_file_command (filename, from_tty) error ("\"%s\" has an invalid struct core length (%d, expected %d)", filename, corestr.c_len, (int) sizeof (struct core)); - /* Note that data_start and data_end don't depend on the exec file */ - data_start = N_DATADDR (corestr.c_aouthdr); + data_start = exec_data_start; data_end = data_start + corestr.c_dsize; stack_start = stack_end - corestr.c_ssize; data_offset = sizeof corestr; @@ -604,6 +664,8 @@ exec_file_command (filename, from_tty) if (execfile) free (execfile); execfile = 0; + data_start = 0; + data_end -= exec_data_start; text_start = 0; text_end = 0; exec_data_start = 0; @@ -616,6 +678,9 @@ exec_file_command (filename, from_tty) if (filename) { + filename = tilde_expand (filename); + make_cleanup (free, filename); + execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, &execfile); if (execchan < 0) @@ -647,6 +712,8 @@ exec_file_command (filename, from_tty) 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 */ @@ -657,13 +724,17 @@ exec_file_command (filename, from_tty) if (val < 0) perror_with_name (filename); - text_start = N_TXTADDR (exec_aouthdr); - exec_data_start = N_DATADDR (exec_aouthdr); + text_start = + IS_OBJECT_FILE (exec_aouthdr) ? 0 : N_TXTADDR (exec_aouthdr); + exec_data_start = IS_OBJECT_FILE (exec_aouthdr) + ? exec_aouthdr.a_text : 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; fstat (execchan, &st_exec); exec_mtime = st_exec.st_mtime; @@ -837,29 +908,41 @@ skip_prologue (pc) { union { - union insn_fmt insn; + unsigned long int code; + struct + { + unsigned int op:2; + unsigned int rd:5; + unsigned int op2:3; + unsigned int imm22:22; + } sethi; + struct + { + unsigned int op:2; + unsigned int rd:5; + unsigned int op3:6; + unsigned int rs1:5; + unsigned int i:1; + unsigned int simm13:13; + } add; int i; } x; int dest = -1; x.i = read_memory_integer (pc, 4); - /* Recognize sethi insn. Record destination. */ - if (x.insn.sethi.op == 0 - && x.insn.sethi.op2 == 4) + /* Recognize the `sethi' insn and record its destination. */ + if (x.sethi.op == 0 && x.sethi.op2 == 4) { - dest = x.insn.sethi.rd; + dest = x.sethi.rd; pc += 4; x.i = read_memory_integer (pc, 4); } - /* Recognizes an add immediate value to register to either %g1 or + /* Recognize an add immediate value to register to either %g1 or the destination register recorded above. Actually, this might - well recognize several different arithmetic operations.*/ - if (x.insn.arith_imm.op == 2 - && x.insn.arith_imm.i == 1 - && (x.insn.arith_imm.rd == 1 - || x.insn.arith_imm.rd == dest)) + well recognize several different arithmetic operations. */ + if (x.add.op == 2 && x.add.i && (x.add.rd == 1 || x.add.rd == dest)) { pc += 4; x.i = read_memory_integer (pc, 4); @@ -868,8 +951,7 @@ skip_prologue (pc) /* This recognizes any SAVE insn. But why do the XOR and then the compare? That's identical to comparing against 60 (as long as there isn't any sign extension). */ - if (x.insn.arith.op == 2 - && (x.insn.arith.op3 ^ 32) == 28) + if (x.add.op == 2 && (x.add.op3 ^ 32) == 28) { pc += 4; x.i = read_memory_integer (pc, 4); @@ -877,14 +959,15 @@ skip_prologue (pc) /* Now we need to recognize stores into the frame from the input registers. This recognizes all non alternate stores of input - register, into a location offset from the frame pointer. */ - while (x.insn.arith_imm.op == 3 - && (x.insn.arith_imm.op3 & 0x3c) == 4 /* Store, non-alt */ - && (x.insn.arith_imm.rd & 0x18) == 0x18 /* Input register */ - && x.insn.arith_imm.i == 1 /* Immediate mode */ - && x.insn.arith_imm.rs1 == 30 /* Off of frame pointer */ - && x.insn.arith_imm.simm >= 0x44 /* Into reserved */ - && x.insn.arith_imm.simm < 0x5b) /* stack space. */ + register, into a location offset from the frame pointer. */ + while (x.add.op == 3 + && (x.add.op3 & 0x3c) == 4 /* Store, non-alternate. */ + && (x.add.rd & 0x18) == 0x18 /* Input register. */ + && x.add.i /* Immediate mode. */ + && x.add.rs1 == 30 /* Off of frame pointer. */ + /* Into reserved stack space. */ + && x.add.simm13 >= 0x44 + && x.add.simm13 < 0x5b) { pc += 4; x.i = read_memory_integer (pc, 4); @@ -892,41 +975,43 @@ skip_prologue (pc) return pc; } -/* - * Check instruction at "addr" to see if it is an annulled branch. - * All other instructions will go to NPC or will trap. - * - * Set *target if we find a candidate branch; set to zero if not. - */ - +/* Check instruction at ADDR to see if it is an annulled branch. + All other instructions will go to NPC or will trap. + Set *TARGET if we find a canidate branch; set to zero if not. */ + branch_type isannulled (addr, target) CORE_ADDR addr, *target; { - union insn_fmt instr; branch_type val = not_branch; - long offset; /* Must be signed for sign-extend */ + long int offset; /* Must be signed for sign-extend. */ + union + { + unsigned long int code; + struct + { + unsigned int op:2; + unsigned int a:1; + unsigned int cond:4; + unsigned int op2:3; + unsigned int disp22:22; + } b; + } insn; *target = 0; - instr.intval = read_memory_integer (addr, 4); - /* printf("intval = %x\n",instr.intval); */ - switch (instr.op1.op1) + insn.code = read_memory_integer (addr, 4); + + if (insn.b.op == 0 + && (insn.b.op2 == 2 || insn.b.op2 == 6 || insn.b.op2 == 7)) { - case 0: /* Format 2 */ - switch(instr.op2.op2) - { - case 2: case 6: case 7: /* Bcc, FBcc, CBcc */ - if (instr.branch.cond == 8) - val = instr.branch.a ? baa : ba; - else - val = instr.branch.a ? bicca : bicc; - /* 22 bits, sign extended */ - offset = 4 * ((int) (instr.branch.disp << 10) >> 10); - *target = addr + offset; - break; - } - break; + if (insn.b.cond == 8) + val = insn.b.a ? baa : ba; + else + val = insn.b.a ? bicca : bicc; + offset = 4 * ((int) (insn.b.disp22 << 10) >> 10); + *target = addr + offset; } - /*printf("isannulled ret: %d\n",val); */ + return val; } + diff --git a/gdb/sparc-opcode.h b/gdb/sparc-opcode.h index f20a209c59..283ba762fe 100644 --- a/gdb/sparc-opcode.h +++ b/gdb/sparc-opcode.h @@ -1,116 +1,632 @@ -/* Sparc opcde list for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. - Contributed by Michael Tiemann (tiemann@mcc.com) - -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! -*/ +/* Table of opcodes for the sparc. + Copyright (C) 1989 Free Software Foundation, Inc. -struct op1_fmt -{ - unsigned op1 : 2; - unsigned dummy : 30; -}; +This file is part of GAS, the GNU Assembler, and GDB, the GNU disassembler. -struct op2_fmt -{ - unsigned dummy1 : 7; - unsigned op2 : 3; - unsigned dummy2 : 22; -}; +GAS/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. -struct op3_fmt -{ - unsigned dummy1 : 7; - unsigned op3 : 6; - unsigned dummy2 : 19; -}; +GAS/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. -struct call_fmt -{ - unsigned op : 2; - unsigned disp : 30; -}; +You should have received a copy of the GNU General Public License +along with GAS or GDB; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -struct sethi_fmt -{ - unsigned op : 2; - unsigned rd : 5; - unsigned op2 : 3; - unsigned imm : 22; -}; +#if !defined(__STDC__) && !defined(const) +#define const +#endif -struct branch_fmt +/* + * Structure of an opcode table entry. + */ +struct sparc_opcode { - unsigned op : 2; - unsigned a : 1; - unsigned cond : 4; - unsigned op2 : 3; - unsigned disp : 22; /* this should really be signed. */ + const char *name; + unsigned long int match; /* Bits that must be set. */ + unsigned long int lose; /* Bits that must not be set. */ + const char *args; + /* Nonzero if this is a delayed branch instruction. */ + char delayed; }; -struct ldst_fmt -{ - unsigned op : 2; - unsigned rd : 5; - unsigned op3 : 6; - unsigned rs1 : 5; - unsigned i : 1; - unsigned asi : 8; - unsigned rs2 : 5; -}; +/* + All sparc opcodes are 32 bits, except for the `set' instruction (really + a macro), which is 64 bits. It is handled as a special case. -struct arith_imm_fmt -{ - unsigned op : 2; - unsigned rd : 5; - unsigned op3 : 6; - unsigned rs1 : 5; - unsigned i : 1; - int simm : 13; /* Hopefully signed, but . . . */ -}; + The match component is a mask saying which bits must match a + particular opcode in order for an instruction to be an instance + of that opcode. -struct arith_fmt -{ - unsigned op : 2; - unsigned rd : 5; - unsigned op3 : 6; - unsigned rs1 : 5; - unsigned i : 1; - unsigned opf : 8; - unsigned rs2 : 5; -}; + The args component is a string containing one character + for each operand of the instruction. + +Kinds of operands: + # Number used by optimizer. It is ignored. + 1 rs1 register. + 2 rs2 register. + d rd register. + e frs1 floating point register. + f frs2 floating point register. + g frsd floating point register. + b crs1 coprocessor register + c crs2 coprocessor register + D crsd coprocessor register + h 22 high bits. + i 13 bit Immediate. + l 22 bit PC relative immediate. + L 30 bit PC relative immediate. + a Annul. The annul bit is set. + A Alternate address space. Stored as 8 bits. + C Coprocessor state register. + F floating point state register. + p Processor state register. + q Floating point queue. + r Single register that is both rs1 and rsd. + Q Coprocessor queue. + S Special case. + t Trap base register. + w Window invalid mask register. + y Y register. -union insn_fmt +*/ + +/* The order of the opcodes in this table is significant: + + * The assembler requires that all instances of the same mnemonic must be + consecutive. If they aren't, the assembler will bomb at runtime. + + * The disassembler should not care about the order of the opcodes. */ + +static struct sparc_opcode sparc_opcodes[] = { - struct op1_fmt op1; - struct op2_fmt op2; - struct op3_fmt op3; - struct call_fmt call; - struct sethi_fmt sethi; - struct branch_fmt branch; - struct ldst_fmt ldst; - struct arith_imm_fmt arith_imm; - struct arith_fmt arith; - int intval; - float floatval; /* ?? */ + +{ "ldd", 0xc1980000, 0x0060201f, "[1],D", 0 }, /* ldd [rs1+%g0],d */ +{ "ldd", 0xc1982000, 0x00601fff, "[1],D", 0 }, /* ldd [rs1+0],d */ +{ "ldd", 0xc1982000, 0x00600000, "[1+i],D", 0 }, +{ "ldd", 0xc1982000, 0x00600000, "[i+1],D", 0 }, +{ "ldd", 0xc1980000, 0x00602000, "[1+2],D", 0 }, +{ "ldd", 0xc1180000, 0x00e0201f, "[1],g", 0 }, /* ldd [rs1+%g0],d */ +{ "ldd", 0xc1182000, 0x00e01fff, "[1],g", 0 }, /* ldd [rs1+0],d */ +{ "ldd", 0xc1182000, 0x00e00000, "[1+i],g", 0 }, +{ "ldd", 0xc1182000, 0x00e00000, "[i+1],g", 0 }, +{ "ldd", 0xc1180000, 0x00e02000, "[1+2],g", 0 }, +{ "ldd", 0xc0180000, 0x01e0201f, "[1],d", 0 }, /* ldd [rs1+%g0],d */ +{ "ldd", 0xc0182000, 0x01e01fff, "[1],d", 0 }, /* ldd [rs1+0],d */ +{ "ldd", 0xc0182000, 0x01e00000, "[1+i],d", 0 }, +{ "ldd", 0xc0182000, 0x01e00000, "[i+1],d", 0 }, +{ "ldd", 0xc0180000, 0x01e02000, "[1+2],d", 0 }, +{ "ld", 0xc1880000, 0x0070201f, "[1],C", 0 }, /* ld [rs1+%g0],d */ +{ "ld", 0xc1882000, 0x00701fff, "[1],C", 0 }, /* ld [rs1+0],d */ +{ "ld", 0xc1882000, 0x00700000, "[1+i],C", 0 }, +{ "ld", 0xc1882000, 0x00700000, "[i+1],C", 0 }, +{ "ld", 0xc1880000, 0x00702000, "[1+2],C", 0 }, +{ "ld", 0xc1800000, 0x0078201f, "[1],D", 0 }, /* ld [rs1+%g0],d */ +{ "ld", 0xc1802000, 0x00781fff, "[1],D", 0 }, /* ld [rs1+0],d */ +{ "ld", 0xc1802000, 0x00780000, "[1+i],D", 0 }, +{ "ld", 0xc1802000, 0x00780000, "[i+1],D", 0 }, +{ "ld", 0xc1800000, 0x00782000, "[1+2],D", 0 }, +{ "ld", 0xc1080000, 0x00f0201f, "[1],F", 0 }, /* ld [rs1+%g0],d */ +{ "ld", 0xc1082000, 0x00f01fff, "[1],F", 0 }, /* ld [rs1+0],d */ +{ "ld", 0xc1082000, 0x00f00000, "[1+i],F", 0 }, +{ "ld", 0xc1082000, 0x00f00000, "[i+1],F", 0 }, +{ "ld", 0xc1080000, 0x00f02000, "[1+2],F", 0 }, +{ "ld", 0xc1000000, 0x00f8201f, "[1],g", 0 }, /* ld [rs1+%g0],d */ +{ "ld", 0xc1002000, 0x00f81fff, "[1],g", 0 }, /* ld [rs1+0],d */ +{ "ld", 0xc1002000, 0x00f80000, "[1+i],g", 0 }, +{ "ld", 0xc1002000, 0x00f80000, "[i+1],g", 0 }, +{ "ld", 0xc1000000, 0x00f82000, "[1+2],g", 0 }, +{ "ld", 0xc0000000, 0x01f8201f, "[1],d", 0 }, /* ld [rs1+%g0],d */ +{ "ld", 0xc0002000, 0x01f81fff, "[1],d", 0 }, /* ld [rs1+0],d */ +{ "ld", 0xc0002000, 0x01f80000, "[1+i],d", 0 }, +{ "ld", 0xc0002000, 0x01f80000, "[i+1],d", 0 }, +{ "ld", 0xc0000000, 0x01f82000, "[1+2],d", 0 }, +{ "ldstuba", 0xc0d80000, 0x0100201f, "[1]A,d", 0 }, /* ldstuba [rs1+%g0],d */ +{ "ldstuba", 0xc0d80000, 0x01002000, "[1+2]A,d", 0 }, +{ "ldsha", 0xc0d00000, 0x0128201f, "[1]A,d", 0 }, /* ldsha [rs1+%g0],d */ +{ "ldsha", 0xc0d00000, 0x01282000, "[1+2]A,d", 0 }, +{ "ldsba", 0xc0c80000, 0x0130201f, "[1]A,d", 0 }, /* ldsba [rs1+%g0],d */ +{ "ldsba", 0xc0c80000, 0x01302000, "[1+2]A,d", 0 }, +{ "ldda", 0xc0980000, 0x0160201f, "[1]A,d", 0 }, /* ldda [rs1+%g0],d */ +{ "ldda", 0xc0980000, 0x01602000, "[1+2]A,d", 0 }, +{ "lduha", 0xc0900000, 0x0168201f, "[1]A,d", 0 }, /* lduha [rs1+%g0],d */ +{ "lduha", 0xc0900000, 0x01682000, "[1+2]A,d", 0 }, +{ "ldstub", 0xc0680000, 0x0190201f, "[1],d", 0 }, /* ldstub [rs1+%g0],d */ +{ "ldstub", 0xc0682000, 0x01900000, "[1+i],d", 0 }, +{ "ldstub", 0xc0682000, 0x01900000, "[i+1],d", 0 }, +{ "ldstub", 0xc0680000, 0x01902000, "[1+2],d", 0 }, +{ "lda", 0xc0800000, 0x0178201f, "[1]A,d", 0 }, /* lda [rs1+%g0],d */ +{ "lda", 0xc0800000, 0x01782000, "[1+2]A,d", 0 }, +{ "ldsh", 0xc0500000, 0x0000000d, "[1],d", 0 }, /* ldsh [rs1+%g0],d */ +{ "ldsh", 0xc0502000, 0x01a81fff, "[1],d", 0 }, /* ldsh [rs1+0],d */ +{ "ldsh", 0xc0502000, 0x01a80000, "[1+i],d", 0 }, +{ "ldsh", 0xc0502000, 0x01a80000, "[i+1],d", 0 }, +{ "ldsh", 0xc0500000, 0x01a82000, "[1+2],d", 0 }, +{ "ldsb", 0xc0480000, 0x01b0201f, "[1],d", 0 }, /* ldsb [rs1+%g0],d */ +{ "ldsb", 0xc0482000, 0x01b01fff, "[1],d", 0 }, /* ldsb [rs1+0],d */ +{ "ldsb", 0xc0482000, 0x01b00000, "[1+i],d", 0 }, +{ "ldsb", 0xc0482000, 0x01b00000, "[i+1],d", 0 }, +{ "ldsb", 0xc0480000, 0x01b02000, "[1+2],d", 0 }, +{ "ldub", 0xc0080000, 0x01f0201f, "[1],d", 0 }, /* ldub [rs1+%g0],d */ +{ "ldub", 0xc0082000, 0x01f01fff, "[1],d", 0 }, /* ldub [rs1+0],d */ +{ "ldub", 0xc0082000, 0x01f00000, "[1+i],d", 0 }, +{ "ldub", 0xc0082000, 0x01f00000, "[i+1],d", 0 }, +{ "ldub", 0xc0080000, 0x01f02000, "[1+2],d", 0 }, +{ "lduba", 0xc0880000, 0x0170201f, "[1]A,d", 0 }, /* lduba [rs1+%g0],d */ +{ "lduba", 0xc0880000, 0x01702000, "[1+2]A,d", 0 }, +{ "lduh", 0xc0102000, 0x01e80000, "[1+i],d", 0 }, +{ "lduh", 0xc0102000, 0x01e80000, "[i+1],d", 0 }, +{ "lduh", 0xc0100000, 0x01e8201f, "[1],d", 0 }, /* lduh [rs1+%g0],d */ +{ "lduh", 0xc0102000, 0x01e81fff, "[1],d", 0 }, /* lduh [rs1+0],d */ +{ "lduh", 0xc0100000, 0x01e82000, "[1+2],d", 0 }, + +{ "st", 0xc0200000, 0x01d8201f, "d,[1]", 0 }, /* st d,[rs1+%g0] */ +{ "st", 0xc0202000, 0x01d81fff, "d,[1]", 0 }, /* st d,[rs1+0] */ +{ "st", 0xc0202000, 0x01d80000, "d,[1+i]", 0 }, +{ "st", 0xc0202000, 0x01d80000, "d,[i+1]", 0 }, +{ "st", 0xc0200000, 0x01d82000, "d,[1+2]", 0 }, +{ "st", 0xc1200000, 0x00d8201f, "g,[1]", 0 }, /* st d[rs1+%g0] */ +{ "st", 0xc1202000, 0x00d81fff, "g,[1]", 0 }, /* st d,[rs1+0] */ +{ "st", 0xc1202000, 0x00d80000, "g,[1+i]", 0 }, +{ "st", 0xc1202000, 0x00d80000, "g,[i+1]", 0 }, +{ "st", 0xc1200000, 0x00d82000, "g,[1+2]", 0 }, +{ "st", 0xc1100000, 0x00c0201f, "F,[1]", 0 }, /* st d,[rs1+%g0] */ +{ "st", 0xc1102000, 0x00c01fff, "F,[1]", 0 }, /* st d,[rs1+0] */ +{ "st", 0xc1102000, 0x00c00000, "F,[1+i]", 0 }, +{ "st", 0xc1102000, 0x00c00000, "F,[i+1]", 0 }, +{ "st", 0xc1100000, 0x00c02000, "F,[1+2]", 0 }, +{ "st", 0xc1a00000, 0x0058201f, "D,[1]", 0 }, /* st d,[rs1+%g0] */ +{ "st", 0xc1a02000, 0x00581fff, "D,[1]", 0 }, /* st d,[rs1+0] */ +{ "st", 0xc1a02000, 0x00580000, "D,[1+i]", 0 }, +{ "st", 0xc1a02000, 0x00580000, "D,[i+1]", 0 }, +{ "st", 0xc1a00000, 0x00582000, "D,[1+2]", 0 }, +{ "st", 0xc1a80000, 0x0050201f, "C,[1]", 0 }, /* st d,[rs1+%g0] */ +{ "st", 0xc1a82000, 0x00501fff, "C,[1]", 0 }, /* st d,[rs1+0] */ +{ "st", 0xc1a82000, 0x00500000, "C,[1+i]", 0 }, +{ "st", 0xc1a82000, 0x00500000, "C,[i+1]", 0 }, +{ "st", 0xc1a80000, 0x00502000, "C,[1+2]", 0 }, +{ "sta", 0xc0a00000, 0x0108201f, "d,[1]A", 0 }, /* sta d,[rs1+%g0] */ +{ "sta", 0xc0a00000, 0x01082000, "d,[1+2]A", 0 }, + +{ "stb", 0xc0280000, 0x01d0201f, "d,[1]", 0 }, /* stb d,[rs1+%g0] */ +{ "stb", 0xc0282000, 0x01d01fff, "d,[1]", 0 }, /* stb d,[rs1+0] */ +{ "stb", 0xc0282000, 0x01d00000, "d,[1+i]", 0 }, +{ "stb", 0xc0282000, 0x01d00000, "d,[i+1]", 0 }, +{ "stb", 0xc0280000, 0x01d02000, "d,[1+2]", 0 }, +{ "stba", 0xc0a80000, 0x01002000, "d,[1+2]A", 0 }, +{ "stba", 0xc0a80000, 0x0100201f, "d,[1]A", 0 }, /* stba d,[rs1+%g0] */ + +{ "std", 0xc0380000, 0x01c0201f, "d,[1]", 0 }, /* std d,[rs1+%g0] */ +{ "std", 0xc0382000, 0x01c01fff, "d,[1]", 0 }, /* std d,[rs1+0] */ +{ "std", 0xc0382000, 0x01c00000, "d,[1+i]", 0 }, +{ "std", 0xc0382000, 0x01c00000, "d,[i+1]", 0 }, +{ "std", 0xc0380000, 0x01c02000, "d,[1+2]", 0 }, +{ "std", 0xc1380000, 0x00c0201f, "g,[1]", 0 }, /* std d,[rs1+%g0] */ +{ "std", 0xc1382000, 0x00c01fff, "g,[1]", 0 }, /* std d,[rs1+0] */ +{ "std", 0xc1382000, 0x00c00000, "g,[1+i]", 0 }, +{ "std", 0xc1382000, 0x00c00000, "g,[i+1]", 0 }, +{ "std", 0xc1380000, 0x00c02000, "g,[1+2]", 0 }, +{ "std", 0xc1300000, 0x00c8201f, "q,[1]", 0 }, /* std d,[rs1+%g0] */ +{ "std", 0xc1302000, 0x00c81fff, "q,[1]", 0 }, /* std d,[rs1+0] */ +{ "std", 0xc1302000, 0x00c80000, "q,[1+i]", 0 }, +{ "std", 0xc1302000, 0x00c80000, "q,[i+1]", 0 }, +{ "std", 0xc1300000, 0x00c82000, "q,[1+2]", 0 }, +{ "std", 0xc1b80000, 0x0040201f, "D,[1]", 0 }, /* std d,[rs1+%g0] */ +{ "std", 0xc1b82000, 0x00401fff, "D,[1]", 0 }, /* std d,[rs1+0] */ +{ "std", 0xc1b82000, 0x00400000, "D,[1+i]", 0 }, +{ "std", 0xc1b82000, 0x00400000, "D,[i+1]", 0 }, +{ "std", 0xc1b80000, 0x00402000, "D,[1+2]", 0 }, +{ "std", 0xc1b00000, 0x0048201f, "Q,[1]", 0 }, /* std d,[rs1+%g0] */ +{ "std", 0xc1b02000, 0x00481fff, "Q,[1]", 0 }, /* std d,[rs1+0] */ +{ "std", 0xc1b02000, 0x00480000, "Q,[1+i]", 0 }, +{ "std", 0xc1b02000, 0x00480000, "Q,[i+1]", 0 }, +{ "std", 0xc1b00000, 0x00482000, "Q,[1+2]", 0 }, +{ "stda", 0xc0b80000, 0x01402000, "d,[1+2]A", 0 }, +{ "stda", 0xc0b80000, 0x0140201f, "d,[1]A", 0 }, /* stda d,[rs1+%g0] */ + +{ "sth", 0xc0300000, 0x01c8201f, "d,[1]", 0 }, /* sth d,[rs1+%g0] */ +{ "sth", 0xc0302000, 0x01c81fff, "d,[1]", 0 }, /* sth d,[rs1+0] */ +{ "sth", 0xc0300000, 0x01c82000, "d,[1+2]", 0 }, +{ "sth", 0xc0302000, 0x01c80000, "d,[1+i]", 0 }, +{ "sth", 0xc0302000, 0x01c80000, "d,[i+1]", 0 }, +{ "stha", 0xc0b00000, 0x0148201f, "d,[1]A", 0 }, /* stha d,[rs1+%g0] */ +{ "stha", 0xc0b00000, 0x01482000, "d,[1+2]A", 0 }, + +{ "swap", 0xc0780000, 0x0180201f, "[1],d", 0 }, /* swap [rs1+%g0],d */ +{ "swap", 0xc0782000, 0x01801fff, "[1],d", 0 }, /* swap [rs1+0],d */ +{ "swap", 0xc0782000, 0x01800000, "[1+i],d", 0 }, +{ "swap", 0xc0782000, 0x01800000, "[i+1],d", 0 }, +{ "swap", 0xc0780000, 0x01802000, "[1+2],d", 0 }, +{ "swapa", 0xc0f80000, 0x01002000, "[1+2]A,d", 0 }, +{ "swapa", 0xc0f80000, 0x0100201f, "[1]A,d", 0 }, /* swapa [rs1+%g0],d */ + +{ "restore", 0x81e80000, 0x7e17e01f, "", 0 }, /* restore %g0,%g0,%g0 */ +{ "restore", 0x81e82000, 0x7e14dfff, "", 0 }, /* restore %g0,0,%g0 */ +{ "restore", 0x81e82000, 0x00000000, "1,i,d", 0 }, +{ "restore", 0x81e80000, 0x00000000, "1,2,d", 0 }, +{ "rett", 0x81c82000, 0x40300000, "1+i", 1 }, +{ "rett", 0x81c82000, 0x40300000, "i+1", 1 }, +{ "rett", 0x81c80000, 0x40302000, "1+2", 1 }, +{ "save", 0x81e02000, 0x40180000, "1,i,d", 0 }, +{ "save", 0x81e00000, 0x40180000, "1,2,d", 0 }, + +{ "ret", 0x81c7e008, 0x00001ff7, "", 1 }, /* jmpl %i7+8,%g0 */ +{ "retl", 0x81c3e008, 0x00001ff7, "", 1 }, /* jmpl %o7+8,%g0 */ + +{ "jmpl", 0x81c00000, 0x4038201f, "1,d", 1 }, /* jmpl rs1+%g0,d */ +{ "jmpl", 0x81c02000, 0x4037c000, "i,d", 1 }, /* jmpl %g0+i,d */ +{ "jmpl", 0x81c02000, 0x40380000, "1+i,d", 1 }, +{ "jmpl", 0x81c02000, 0x40380000, "i+1,d", 1 }, +{ "jmpl", 0x81c00000, 0x40382000, "1+2,d", 1 }, +{ "wr", 0x81982000, 0x40600000, "1,i,t", 0 }, +{ "wr", 0x81980000, 0x40600000, "1,2,t", 0 }, +{ "wr", 0x81902000, 0x40680000, "1,i,w", 0 }, +{ "wr", 0x81900000, 0x40680000, "1,2,w", 0 }, +{ "wr", 0x81882000, 0x40700000, "1,i,p", 0 }, +{ "wr", 0x81880000, 0x40700000, "1,2,p", 0 }, +{ "wr", 0x81802000, 0x40780000, "1,i,y", 0 }, +{ "wr", 0x81800000, 0x40780000, "1,2,y", 0 }, + +{ "rd", 0x81580000, 0x40a00000, "t,d", 0 }, +{ "rd", 0x81500000, 0x40a80000, "w,d", 0 }, +{ "rd", 0x81480000, 0x40b00000, "p,d", 0 }, +{ "rd", 0x81400000, 0x40b80000, "y,d", 0 }, + +{ "sra", 0x81382000, 0x00000000, "1,i,d", 0 }, +{ "sra", 0x81380000, 0x00000000, "1,2,d", 0 }, +{ "srl", 0x81302000, 0x40c80000, "1,i,d", 0 }, +{ "srl", 0x81300000, 0x40c80000, "1,2,d", 0 }, +{ "sll", 0x81282000, 0x40d00000, "1,i,d", 0 }, +{ "sll", 0x81280000, 0x40d00000, "1,2,d", 0 }, + +{ "mulscc", 0x81202000, 0x40d80000, "1,i,d", 0 }, +{ "mulscc", 0x81200000, 0x40d80000, "1,2,d", 0 }, + +{ "clr", 0x80100000, 0x4e87e01f, "d", 0 }, /* or %g0,%g0,d */ +{ "clr", 0x80102000, 0x41efdfff, "d", 0 }, /* or %g0,0,d */ + +{ "orncc", 0x80b02000, 0x04048000, "1,i,d", 0 }, +{ "orncc", 0x80b02000, 0x04048000, "i,1,d", 0 }, +{ "orncc", 0x80b00000, 0x04048000, "1,2,d", 0 }, + +{ "tst", 0x80900000, 0x7f6fe000, "2", 0 }, /* orcc %g0, rs2, %g0 */ +{ "tst", 0x80900000, 0x7f68201f, "1", 0 }, /* orcc rs1, %g0, %g0 */ +{ "tst", 0x80902000, 0x7f681fff, "1", 0 }, /* orcc rs1, 0, %g0 */ + +{ "orcc", 0x80902000, 0x41680000, "1,i,d", 0 }, +{ "orcc", 0x80902000, 0x41680000, "i,1,d", 0 }, +{ "orcc", 0x80900000, 0x41680000, "1,2,d", 0 }, +{ "orn", 0x80302000, 0x41c80000, "1,i,d", 0 }, +{ "orn", 0x80302000, 0x41c80000, "i,1,d", 0 }, +{ "orn", 0x80300000, 0x41c80000, "1,2,d", 0 }, + +{ "mov", 0x81800000, 0x4078201f, "1,y", 0 }, /* wr rs1,%g0,%y */ +{ "mov", 0x81802000, 0x40781fff, "1,y", 0 }, /* wr rs1,0,%y */ +{ "mov", 0x81400000, 0x40b80000, "y,d", 0 }, /* rd %y,d */ +{ "mov", 0x81980000, 0x4060201f, "1,t", 0 }, /* wr rs1,%g0,%tbr */ +{ "mov", 0x81982000, 0x40601fff, "1,t", 0 }, /* wr rs1,0,%tbr */ +{ "mov", 0x81580000, 0x40a00000, "t,d", 0 }, /* rd %tbr,d */ +{ "mov", 0x81900000, 0x4068201f, "1,w", 0 }, /* wr rs1,%g0,%wim */ +{ "mov", 0x81902000, 0x40681fff, "1,w", 0 }, /* wr rs1,0,%wim */ +{ "mov", 0x81500000, 0x40a80000, "w,d", 0 }, /* rd %wim,d */ +{ "mov", 0x81880000, 0x4070201f, "1,p", 0 }, /* wr rs1,%g0,%psr */ +{ "mov", 0x81882000, 0x40701fff, "1,p", 0 }, /* wr rs1,0,%psr */ +{ "mov", 0x81480000, 0x40b00000, "p,d", 0 }, /* rd %psr,d */ + +{ "mov", 0x80102000, 0x41efc000, "i,d", 0 }, /* or %g0,i,d */ +{ "mov", 0x80100000, 0x41efe000, "2,d", 0 }, /* or %g0,rs2,d */ + +{ "or", 0x80102000, 0x40800000, "1,i,d", 0 }, +{ "or", 0x80102000, 0x40800000, "i,1,d", 0 }, +{ "or", 0x80100000, 0x40800000, "1,2,d", 0 }, + +{ "andncc", 0x80a82000, 0x41500000, "1,i,d", 0 }, +{ "andncc", 0x80a82000, 0x41500000, "i,1,d", 0 }, +{ "andncc", 0x80a80000, 0x41500000, "1,2,d", 0 }, +{ "andn", 0x80282000, 0x41d00000, "1,i,d", 0 }, +{ "andn", 0x80282000, 0x41d00000, "i,1,d", 0 }, +{ "andn", 0x80280000, 0x41d00000, "1,2,d", 0 }, + +{ "cmp", 0x80a02000, 0x7d580000, "1,i", 0 }, /* subcc rs1,i,%g0 */ +{ "cmp", 0x80a00000, 0x7d580000, "1,2", 0 }, /* subcc rs1,rs2,%g0 */ + +{ "subcc", 0x80a02000, 0x41580000, "1,i,d", 0 }, +{ "subcc", 0x80a00000, 0x41580000, "1,2,d", 0 }, +{ "sub", 0x80202000, 0x41d80000, "1,i,d", 0 }, +{ "sub", 0x80200000, 0x41d80000, "1,2,d", 0 }, +{ "subx", 0x80602000, 0x41980000, "1,i,d", 0 }, +{ "subx", 0x80600000, 0x41980000, "1,2,d", 0 }, +{ "subxcc", 0x80e02000, 0x41180000, "1,i,d", 0 }, +{ "subxcc", 0x80e00000, 0x41180000, "1,2,d", 0 }, + +{ "andcc", 0x80882000, 0x41700000, "1,i,d", 0 }, +{ "andcc", 0x80882000, 0x41700000, "i,1,d", 0 }, +{ "andcc", 0x80880000, 0x41700000, "1,2,d", 0 }, +{ "and", 0x80082000, 0x41f00000, "1,i,d", 0 }, +{ "and", 0x80082000, 0x41f00000, "i,1,d", 0 }, +{ "and", 0x80080000, 0x41f00000, "1,2,d", 0 }, + +{ "inc", 0x80002001, 0x00001ffe, "r", 0 }, /* add rs1,1,rsd */ + +{ "addxcc", 0x80c02000, 0x41380000, "1,i,d", 0 }, +{ "addxcc", 0x80c02000, 0x41380000, "i,1,d", 0 }, +{ "addxcc", 0x80c00000, 0x41380000, "1,2,d", 0 }, +{ "addcc", 0x80802000, 0x41780000, "1,i,d", 0 }, +{ "addcc", 0x80802000, 0x41780000, "i,1,d", 0 }, +{ "addcc", 0x80800000, 0x41780000, "1,2,d", 0 }, +{ "addx", 0x80402000, 0x41b80000, "1,i,d", 0 }, +{ "addx", 0x80402000, 0x41b80000, "i,1,d", 0 }, +{ "addx", 0x80400000, 0x41b80000, "1,2,d", 0 }, +{ "add", 0x80002000, 0x41f80000, "1,i,d", 0 }, +{ "add", 0x80002000, 0x41f80000, "i,1,d", 0 }, +{ "add", 0x80000000, 0x41f80000, "1,2,d", 0 }, + +{ "call", 0x9fc00000, 0x4038201f, "1", 1 }, /* jmpl rs1+%g0, %o7 */ +{ "call", 0x9fc00000, 0x4038201f, "1,#", 1 }, +{ "call", 0x40000000, 0x80000000, "L", 1 }, +{ "call", 0x40000000, 0x80000000, "L,#", 1 }, + +{ "bvc", 0x3e800000, 0xc1400000, ",al", 1 }, +{ "bvc", 0x1e800000, 0xc1400000, "l", 1 }, +{ "bvs", 0x2e800000, 0xc1400000, ",al", 1 }, +{ "bvs", 0x0e800000, 0xc1400000, "l", 1 }, +{ "bpos", 0x3c800000, 0xc1400000, ",al", 1 }, +{ "bpos", 0x1c800000, 0xc1400000, "l", 1 }, +{ "bneg", 0x2c800000, 0xc1400000, ",al", 1 }, +{ "bneg", 0x0c800000, 0xc1400000, "l", 1 }, +{ "bcc", 0x3a800000, 0xc1400000, ",al", 1 }, +{ "bcc", 0x1a800000, 0xc1400000, "l", 1 }, +{ "bcs", 0x2a800000, 0xc1400000, ",al", 1 }, +{ "bcs", 0x0a800000, 0xc1400000, "l", 1 }, +{ "blu", 0x2a800000, 0xc1400000, ",al", 1 }, +{ "blu", 0x0a800000, 0xc1400000, "l", 1 }, /* same as bcs */ +{ "bgeu", 0x3a800000, 0xc1400000, ",al", 1 }, +{ "bgeu", 0x1a800000, 0xc1400000, "l", 1 }, /* same as bcc */ +{ "bgu", 0x38800000, 0xc1400000, ",al", 1 }, +{ "bgu", 0x18800000, 0xc1400000, "l", 1 }, +{ "bleu", 0x28800000, 0xc1400000, ",al", 1 }, +{ "bleu", 0x08800000, 0xc1400000, "l", 1 }, +{ "bge", 0x36800000, 0xc1400000, ",al", 1 }, +{ "bge", 0x16800000, 0xc1400000, "l", 1 }, +{ "bl", 0x26800000, 0xc1400000, ",al", 1 }, +{ "bl", 0x06800000, 0xc1400000, "l", 1 }, +{ "bg", 0x34800000, 0xc1400000, ",al", 1 }, +{ "bg", 0x14800000, 0xc1400000, "l", 1 }, +{ "ble", 0x24800000, 0xc1400000, ",al", 1 }, +{ "ble", 0x04800000, 0xc1400000, "l", 1 }, +{ "be", 0x22800000, 0xc1400000, ",al", 1 }, +{ "be", 0x02800000, 0xc1400000, "l", 1 }, +{ "bne", 0x32800000, 0xc1400000, ",al", 1 }, +{ "bne", 0x12800000, 0xc1400000, "l", 1 }, +{ "b", 0x30800000, 0xc1400000, ",al", 1 }, +{ "b", 0x10800000, 0xc1400000, "l", 1 }, +{ "ba", 0x30800000, 0xc1400000, ",al", 1 }, +{ "ba", 0x10800000, 0xc1400000, "l", 1 }, +{ "bn", 0x20800000, 0xc1400000, ",al", 1 }, +{ "bn", 0x00800000, 0xc1400000, "l", 1 }, + +{ "jmp", 0x81c00000, 0x7e38201f, "1", 1 }, /* jmpl rs1+%g0,%g0 */ +{ "jmp", 0x81c02000, 0x7e3fc000, "i", 1 }, /* jmpl %g0+i,%g0 */ + +{ "nop", 0x01000000, 0xfe3fffff, "", 0 }, /* sethi 0, %g0 */ + +{ "set", 0x01000000, 0xc0c00000, "Sh,d", 0 }, + +{ "sethi", 0x01000000, 0xc0c00000, "h,d", 0 }, + +{ "taddcctv", 0x81102000, 0x40e00000, "1,i,d", 0 }, +{ "taddcctv", 0x81100000, 0x40e00000, "1,2,d", 0 }, +{ "taddcc", 0x81002000, 0x40f80000, "1,i,d", 0 }, +{ "taddcc", 0x81000000, 0x40f80000, "1,2,d", 0 }, + +{ "tvc", 0x9fd02000, 0x402fc000, "i", 0 }, /* tvc %g0+i */ +{ "tvc", 0x9fd02000, 0x40280000, "1+i", 0 }, +{ "tvc", 0x9fd00000, 0x40282000, "1+2", 0 }, +{ "tvc", 0x9fd00000, 0x4028201f, "1", 0 }, /* tvc rs1+%g0 */ +{ "tpos", 0x9dd02000, 0x402fc000, "i", 0 }, /* tpos %g0+i */ +{ "tpos", 0x9dd02000, 0x40280000, "1+i", 0 }, +{ "tpos", 0x9dd00000, 0x40282000, "1+2", 0 }, +{ "tpos", 0x9dd00000, 0x4028201f, "1", 0 }, /* tpos rs1+%g0 */ +{ "tcc", 0x9bd02000, 0x402fc000, "i", 0 }, /* tcc %g0+i */ +{ "tcc", 0x9bd02000, 0x40280000, "1+i", 0 }, +{ "tcc", 0x9bd00000, 0x40282000, "1+2", 0 }, +{ "tcc", 0x9bd00000, 0x4028201f, "1", 0 }, /* tcc rs1+%g0 */ +{ "tgu", 0x99d02000, 0x402fc000, "i", 0 }, /* tgu %g0+i */ +{ "tgu", 0x99d02000, 0x40280000, "1+i", 0 }, +{ "tgu", 0x99d00000, 0x40282000, "1+2", 0 }, +{ "tgu", 0x99d00000, 0x4028201f, "1", 0 }, /* tgu rs1+%g0 */ +{ "tge", 0x97d02000, 0x402fc000, "i", 0 }, /* tge %g0+i */ +{ "tge", 0x97d02000, 0x40280000, "1+i", 0 }, +{ "tge", 0x97d00000, 0x40282000, "1+2", 0 }, +{ "tge", 0x97d00000, 0x4028201f, "1", 0 }, /* tge rs1+%g0 */ +{ "tg", 0x95d02000, 0x402fc000, "i", 0 }, /* tg %g0+i */ +{ "tg", 0x95d02000, 0x40280000, "1+i", 0 }, +{ "tg", 0x95d00000, 0x40282000, "1+2", 0 }, +{ "tg", 0x95d00000, 0x4028201f, "1", 0 }, /* tg rs1+%g0 */ +{ "tne", 0x93d02000, 0x402fc000, "i", 0 }, /* tne %g0+i */ +{ "tne", 0x93d02000, 0x40280000, "1+i", 0 }, +{ "tne", 0x93d00000, 0x40282000, "1+2", 0 }, +{ "tne", 0x93d00000, 0x4028201f, "1", 0 }, /* tne rs1+%g0 */ +{ "tleu", 0x8bd02000, 0x502fc000, "i", 0 }, /* tleu %g0+i */ +{ "tleu", 0x8bd02000, 0x50280000, "1+i", 0 }, +{ "tleu", 0x8bd00000, 0x50282000, "1+2", 0 }, +{ "tleu", 0x8bd00000, 0x5028201f, "1", 0 }, /* tleu rs1+%g0 */ +{ "ta", 0x91d02000, 0x402fc000, "i", 0 }, /* ta %g0+i */ +{ "ta", 0x91d02000, 0x402d0000, "1+i", 0 }, +{ "ta", 0x91d00000, 0x40282000, "1+2", 0 }, +{ "ta", 0x91d00000, 0x4028201f, "1", 0 }, /* ta rs1+%g0 */ +{ "tvs", 0x8fd02000, 0x502fc000, "i", 0 }, /* tvs %g0+i */ +{ "tvs", 0x8fd02000, 0x50280000, "1+i", 0 }, +{ "tvs", 0x8fd00000, 0x50282000, "1+2", 0 }, +{ "tvs", 0x8fd00000, 0x5028201f, "1", 0 }, /* tvs rs1+%g0 */ +{ "tneg", 0x8dd02000, 0x502fc000, "i", 0 }, /* tneg %g0+i */ +{ "tneg", 0x8dd02000, 0x50280000, "1+i", 0 }, +{ "tneg", 0x8dd00000, 0x50282000, "1+2", 0 }, +{ "tneg", 0x8dd00000, 0x5028201f, "1", 0 }, /* tneg rs1+%g0 */ +{ "tcs", 0x8bd02000, 0x502fc000, "i", 0 }, /* tcs %g0+i */ +{ "tcs", 0x8bd02000, 0x50280000, "1+i", 0 }, +{ "tcs", 0x8bd00000, 0x50282000, "1+2", 0 }, +{ "tcs", 0x8bd00000, 0x5028201f, "1", 0 }, /* tcs rs1+%g0 */ +{ "tl", 0x87d02000, 0x502fc000, "i", 0 }, /* tl %g0+i */ +{ "tl", 0x87d02000, 0x50280000, "1+i", 0 }, +{ "tl", 0x87d00000, 0x50282000, "1+2", 0 }, +{ "tl", 0x87d00000, 0x5028201f, "1", 0 }, /* tl rs1+%g0 */ +{ "tle", 0x85d02000, 0x502fc000, "i", 0 }, /* tle %g0+i */ +{ "tle", 0x85d02000, 0x50280000, "1+i", 0 }, +{ "tle", 0x85d00000, 0x50282000, "1+2", 0 }, +{ "tle", 0x85d00000, 0x5028201f, "1", 0 }, /* tle rs1+%g0 */ +{ "te", 0x83d02000, 0x502fc000, "i", 0 }, /* te %g0+i */ +{ "te", 0x83d02000, 0x50280000, "1+i", 0 }, +{ "te", 0x83d00000, 0x50282000, "1+2", 0 }, +{ "te", 0x83d00000, 0x5028201f, "1", 0 }, /* te rs1+%g0 */ +{ "tn", 0x81d02000, 0x502fc000, "i", 0 }, /* tn %g0+i */ +{ "tn", 0x81d02000, 0x50280000, "1+i", 0 }, +{ "tn", 0x81d00000, 0x50282000, "1+2", 0 }, +{ "tn", 0x81d00000, 0x5028201f, "1", 0 }, /* tn rs1+%g0 */ + +{ "tsubcc", 0x81080000, 0x40f00000, "1,2,d", 0 }, +{ "tsubcc", 0x81082000, 0x40f00000, "1,i,d", 0 }, +{ "tsubcctv", 0x80580000, 0x40a00000, "1,2,d", 0 }, +{ "tsubcctv", 0x80582000, 0x40a00000, "1,i,d", 0 }, + +{ "unimp", 0x00000000, 0x00000000, "l", 0 }, + +{ "iflush", 0x81d80000, 0x40202000, "1+2", 0 }, +{ "iflush", 0x81d82000, 0x40200000, "1+i", 0 }, + +{ "xnorcc", 0x80b80000, 0x41400000, "1,2,d", 0 }, +{ "xnorcc", 0x80b82000, 0x41400000, "1,i,d", 0 }, +{ "xnorcc", 0x80b82000, 0x41400000, "i,1,d", 0 }, +{ "xorcc", 0x80980000, 0x41600000, "1,2,d", 0 }, +{ "xorcc", 0x80982000, 0x41600000, "1,i,d", 0 }, +{ "xorcc", 0x80982000, 0x41600000, "i,1,d", 0 }, +{ "xnor", 0x80380000, 0x41c00000, "1,2,d", 0 }, +{ "xnor", 0x80382000, 0x41c00000, "1,i,d", 0 }, +{ "xnor", 0x80382000, 0x41c00000, "i,1,d", 0 }, +{ "xor", 0x80180000, 0x41e00000, "1,2,d", 0 }, +{ "xor", 0x80182000, 0x41e00000, "1,i,d", 0 }, +{ "xor", 0x80182000, 0x41e00000, "i,1,d", 0 }, + +{ "fpop1", 0x81a00000, 0x40580000, "[1+2],d", 0 }, +{ "fpop2", 0x81a80000, 0x40500000, "[1+2],d", 0 }, + +{ "fb", 0x31800000, 0xc0400000, ",al", 1 }, +{ "fb", 0x11800000, 0xc0400000, "l", 1 }, +{ "fba", 0x31800000, 0xc0400000, ",al", 1 }, +{ "fba", 0x11800000, 0xc0400000, "l", 1 }, +{ "fbn", 0x21800000, 0xc0400000, ",al", 1 }, +{ "fbn", 0x01800000, 0xc0400000, "l", 1 }, +{ "fbu", 0x2f800000, 0xc0400000, ",al", 1 }, +{ "fbu", 0x0f800000, 0xc0400000, "l", 1 }, +{ "fbg", 0x2d800000, 0xc0400000, ",al", 1 }, +{ "fbg", 0x0d800000, 0xc0400000, "l", 1 }, +{ "fbug", 0x2b800000, 0xc0400000, ",al", 1 }, +{ "fbug", 0x0b800000, 0xc0400000, "l", 1 }, +{ "fbl", 0x29800000, 0xc0400000, ",al", 1 }, +{ "fbl", 0x09800000, 0xc0400000, "l", 1 }, +{ "fbul", 0x27800000, 0xc0400000, ",al", 1 }, +{ "fbul", 0x07800000, 0xc0400000, "l", 1 }, +{ "fblg", 0x25800000, 0xc0400000, ",al", 1 }, +{ "fblg", 0x05800000, 0xc0400000, "l", 1 }, +{ "fbne", 0x23800000, 0xc0400000, ",al", 1 }, +{ "fbne", 0x03800000, 0xc0400000, "l", 1 }, +{ "fbe", 0x33800000, 0xc0400000, ",al", 1 }, +{ "fbe", 0x13800000, 0xc0400000, "l", 1 }, +{ "fbue", 0x35800000, 0xc0400000, ",al", 1 }, +{ "fbue", 0x15800000, 0xc0400000, "l", 1 }, +{ "fbge", 0x37800000, 0xc0400000, ",al", 1 }, +{ "fbge", 0x17800000, 0xc0400000, "l", 1 }, +{ "fbuge", 0x39800000, 0xc0400000, ",al", 1 }, +{ "fbuge", 0x19800000, 0xc0400000, "l", 1 }, +{ "fble", 0x3b800000, 0xc0400000, ",al", 1 }, +{ "fble", 0x1b800000, 0xc0400000, "l", 1 }, +{ "fbule", 0x3d800000, 0xc0400000, ",al", 1 }, +{ "fbule", 0x1d800000, 0xc0400000, "l", 1 }, +{ "fbo", 0x3f800000, 0xc0400000, ",al", 1 }, +{ "fbo", 0x1f800000, 0xc0400000, "l", 1 }, + +{ "cba", 0x31c00000, 0xce000000, ",al", 1 }, +{ "cba", 0x11c00000, 0xce000000, "l", 1 }, +{ "cbn", 0x21c00000, 0xde000000, ",al", 1 }, +{ "cbn", 0x01c00000, 0xde000000, "l", 1 }, +{ "cb3", 0x2fc00000, 0xc0000000, ",al", 1 }, +{ "cb3", 0x0fc00000, 0xc0000000, "l", 1 }, +{ "cb2", 0x2dc00000, 0xc0000000, ",al", 1 }, +{ "cb2", 0x0dc00000, 0xc0000000, "l", 1 }, +{ "cb23", 0x2bc00000, 0xc0000000, ",al", 1 }, +{ "cb23", 0x0bc00000, 0xc0000000, "l", 1 }, +{ "cb1", 0x29c00000, 0xc0000000, ",al", 1 }, +{ "cb1", 0x09c00000, 0xc0000000, "l", 1 }, +{ "cb13", 0x27c00000, 0xc0000000, ",al", 1 }, +{ "cb13", 0x07c00000, 0xc0000000, "l", 1 }, +{ "cb12", 0x25c00000, 0xc0000000, ",al", 1 }, +{ "cb12", 0x05c00000, 0xc0000000, "l", 1 }, +{ "cb123", 0x23c00000, 0xc0000000, ",al", 1 }, +{ "cb123", 0x03c00000, 0xc0000000, "l", 1 }, +{ "cb0", 0x33c00000, 0xc0000000, ",al", 1 }, +{ "cb0", 0x13c00000, 0xc0000000, "l", 1 }, +{ "cb03", 0x35c00000, 0xc0000000, ",al", 1 }, +{ "cb03", 0x15c00000, 0xc0000000, "l", 1 }, +{ "cb02", 0x37c00000, 0xc0000000, ",al", 1 }, +{ "cb02", 0x17c00000, 0xc0000000, "l", 1 }, +{ "cb023", 0x39c00000, 0xc0000000, ",al", 1 }, +{ "cb023", 0x19c00000, 0xc0000000, "l", 1 }, +{ "cb013", 0x3dc00000, 0xc0000000, ",al", 1 }, +{ "cb013", 0x1dc00000, 0xc0000000, "l", 1 }, +{ "cb012", 0x3fc00000, 0xc0000000, ",al", 1 }, +{ "cb012", 0x1fc00000, 0xc0000000, "l", 1 }, + +{ "fstoi", 0x81a01a20, 0x400025c0, "f,g", 0 }, +{ "fdtoi", 0x81a01a40, 0x400025a0, "f,g", 0 }, +{ "fxtoi", 0x81a01a60, 0x40002580, "f,g", 0 }, + +{ "fitox", 0x81a01980, 0x40002660, "f,g", 0 }, +{ "fitod", 0x81a01900, 0x400026e0, "f,g", 0 }, +{ "fitos", 0x81a01880, 0x40002660, "f,g", 0 }, + +{ "fstod", 0x81a01920, 0x400026c0, "f,g", 0 }, +{ "fstox", 0x81a019a0, 0x40002640, "f,g", 0 }, +{ "fdtos", 0x81a018c0, 0x40002720, "f,g", 0 }, +{ "fdtox", 0x81a019c0, 0x40002620, "f,g", 0 }, +{ "fxtos", 0x81a018e0, 0x40002700, "f,g", 0 }, +{ "fxtod", 0x81a01960, 0x40002680, "f,g", 0 }, + +{ "fdivx", 0x81a009e0, 0x40083600, "e,f,g", 0 }, +{ "fdivd", 0x81a009c0, 0x40003620, "e,f,g", 0 }, +{ "fdivs", 0x81a009a0, 0x40003640, "e,f,g", 0 }, +{ "fmuls", 0x81a00920, 0x400036c0, "e,f,g", 0 }, +{ "fmuld", 0x81a00940, 0x400036a0, "e,f,g", 0 }, +{ "fmulx", 0x81a00960, 0x40003680, "e,f,g", 0 }, + +{ "fsqrts", 0x81a00520, 0x40003ac0, "f,g", 0 }, +{ "fsqrtd", 0x81a00540, 0x40003aa8, "f,g", 0 }, +{ "fsqrtx", 0x81a00560, 0x40003a80, "f,g", 0 }, + +{ "fabss", 0x81a00120, 0x40003ec0, "f,g", 0 }, +{ "fnegs", 0x81a000a0, 0x40003f40, "f,g", 0 }, +{ "fmovs", 0x81a00020, 0x40003fc0, "f,g", 0 }, + +{ "fsubx", 0x81a008e0, 0x40003700, "e,f,g", 0 }, +{ "fsubd", 0x81a008c0, 0x40003720, "e,f,g", 0 }, +{ "fsubs", 0x81a008a0, 0x40003740, "e,f,g", 0 }, +{ "faddx", 0x81a00860, 0x40003780, "e,f,g", 0 }, +{ "faddd", 0x81a00840, 0x400037a0, "e,f,g", 0 }, +{ "fadds", 0x81a00820, 0x400037c0, "e,f,g", 0 }, + +{ "fcmpex", 0x81a80ae0, 0x40003500, "e,f", 0 }, +{ "fcmped", 0x81a80ac0, 0x40003520, "e,f", 0 }, +{ "fcmpes", 0x81a80aa0, 0x40003540, "e,f", 0 }, +{ "fcmpx", 0x81a80a60, 0x40003580, "e,f", 0 }, +{ "fcmpd", 0x81a80a40, 0x400035a0, "e,f", 0 }, +{ "fcmps", 0x81a80a20, 0x400035c0, "e,f", 0 }, + +{ "cpop1", 0x81b00000, 0x40480000, "[1+2],d", 0 }, +{ "cpop2", 0x81b80000, 0x40400000, "[1+2],d", 0 }, }; -typedef enum -{ - Error, not_branch, bicc, bicca, ba, baa, ticc, ta, -} branch_type; +#define NUMOPCODES ((sizeof sparc_opcodes)/(sizeof sparc_opcodes[0])) diff --git a/gdb/sparc-pinsn.c b/gdb/sparc-pinsn.c index f7ba3764a1..3c1708c6f9 100644 --- a/gdb/sparc-pinsn.c +++ b/gdb/sparc-pinsn.c @@ -1,23 +1,21 @@ -/* Print sparc instructions for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. - Contributed by Michael Tiemann (tiemann@mcc.com) - -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! -*/ +/* Disassembler for the sparc. + Copyright (C) 1989 Free Software Foundation, Inc. + +This file is part of GDB, the GNU disassembler. + +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 @@ -26,618 +24,425 @@ anyone else from sharing it farther. Help stamp out software hoarding! #include "symtab.h" #include "sparc-opcode.h" -/* sparc instructions are never longer than this many bytes. */ -#define MAXLEN 4 - -/* Print the sparc instruction at address MEMADDR in debugged memory, - on STREAM. Returns length of the instruction, in bytes, which - is always 4. */ - -static char *icc_name[] = -{ "~", "eq", "le", "lt", "leu", "ltu", "neg", "vs", - "", "ne", "gt", "ge", "gtu", "geu", "pos", "vc"}; - -static char *fcc_name[] = -{ "~fb", "fbne", "fblg", "fbul", "fbl", "fbug", "fbg", "fbu", - "fb", "fbe", "fbue", "fbge", "fbuge", "fble", "fbule", "fbo"}; - -static char *ccc_name[] = -{ "~cb", "cb123", "cb12", "cb13", "cb1", "cb23", "cb2", "cb3", - "cb", "cb0", "cb03", "cb02", "cb023", "cb01", "cb013", "cb012"}; - -static char *arith_name[] = -{ "add", "and", "or", "xor", "sub", "andn", "orn", "xnor", - "addx", 0, 0, 0, "subx", 0, 0, 0}; - -static char *xarith_name[] = -{ "taddcc", "tsubcc", "taddcctv", "tsubcctv", "mulscc", "sll", "srl", "sra"}; +extern char *reg_names[]; +#define freg_names (®_names[4 * 8]) -static char *state_reg_name[] = -{ "%y", "%psr", "%wim", "%tbr", 0, 0, 0, 0}; - -static char *ldst_i_name[] = -{ "ld", "ldub", "lduh", "ldd", "st", "stb", "sth", "std", - 0, "ldsb", "ldsh", 0, 0, "ldstub", 0, "swap", - "lda", "lduba", "lduha", "ldda", "sta", "stba", "stha", "stda", - 0, "ldsba", "ldsha", 0, 0, "ldstuba", 0, "swapa"}; - -static char *ldst_f_name[] = -{ "ldf", "ldfsr", 0, "lddf", "stf", "stfsr", "stdfq", "stdf"}; - -static char *ldst_c_name[] = -{ "ldc", "ldcsr", 0, "lddc", "stc", "stcsr", "stdcq", "stdc"}; +union sparc_insn + { + unsigned long int code; + struct + { + unsigned int OP:2; +#define op ldst.OP + unsigned int RD:5; +#define rd ldst.RD + unsigned int op3:6; + unsigned int RS1:5; +#define rs1 ldst.RS1 + unsigned int i:1; + unsigned int ASI:8; +#define asi ldst.ASI + unsigned int RS2:5; +#define rs2 ldst.RS2 +#define shcnt rs2 + } ldst; + struct + { + unsigned int OP:2, RD:5, op3:6, RS1:5, i:1; + unsigned int IMM13:13; +#define imm13 IMM13.IMM13 + } IMM13; + struct + { + unsigned int OP:2; + unsigned int a:1; + unsigned int cond:4; + unsigned int op2:3; + unsigned int DISP22:22; +#define disp22 branch.DISP22 + } branch; +#define imm22 disp22 + struct + { + unsigned int OP:2; + unsigned int DISP30:30; +#define disp30 call.DISP30 + } call; + }; + +/* Nonzero if INSN is the opcode for a delayed branch. */ +static int +is_delayed_branch (insn) + union sparc_insn insn; +{ + unsigned int i; -static int this_sethi_target = -1; -static int last_sethi_target = -1; -static int sethi_value = 0; + for (i = 0; i < NUMOPCODES; ++i) + { + const struct sparc_opcode *opcode = &sparc_opcodes[i]; + if ((opcode->match & insn.code) == opcode->match + && (opcode->lose & insn.code) == 0 + && (opcode->delayed)) + return 1; + } + return 0; +} -static void fprint_addr1 (); -static void fprint_ldst (); -static void fprint_f_ldst (); -static void fprint_c_ldst (); -static void fprint_fpop (); +static int opcodes_sorted = 0; +/* Print one instruction from MEMADDR on STREAM. */ int print_insn (memaddr, stream) CORE_ADDR memaddr; FILE *stream; { - union insn_fmt insn; - int disp22; + union sparc_insn insn; + + register unsigned int i; - read_memory (memaddr, &insn, MAXLEN); + if (!opcodes_sorted) + { + static int compare_opcodes (); + qsort ((char *) sparc_opcodes, NUMOPCODES, + sizeof (sparc_opcodes[0]), compare_opcodes); + opcodes_sorted = 1; + } - this_sethi_target = -1; - switch (insn.op1.op1) + read_memory (memaddr, &insn, sizeof (insn)); + + for (i = 0; i < NUMOPCODES; ++i) { - case 1: - /* CALL format. */ - fprintf (stream, "call "); - print_address (memaddr + (insn.call.disp << 2), stream); - break; - case 0: - /* Bicc, FBfcc, CBccc, SETHI format. */ - switch (insn.op2.op2) + const struct sparc_opcode *opcode = &sparc_opcodes[i]; + if ((opcode->match & insn.code) == opcode->match + && (opcode->lose & insn.code) == 0) { - case 0: - fprintf (stream, "unimp"); - break; - case 2: - /* Bicc. */ - fprintf (stream, "b%s", icc_name[insn.branch.cond]); - if (insn.branch.a) fprintf (stream, ",a "); - else fprintf (stream, " "); - disp22 = insn.branch.disp; - disp22 = ((disp22 << 10) >> 10); - print_address (memaddr + (disp22 << 2), stream); - break; - case 4: - /* SETHI. */ - fprintf (stream, "sethi %%hi(0x%x),%s", - insn.sethi.imm << 10, reg_names[insn.sethi.rd]); - this_sethi_target = insn.sethi.rd; - sethi_value = insn.sethi.imm << 12; - break; - case 6: - /* FBdfcc. */ - fprintf (stream, "fb%s", fcc_name[insn.branch.cond]); - if (insn.branch.a) fprintf (stream, ",a "); - else fprintf (stream, " "); - disp22 = insn.branch.disp; - disp22 = ((disp22 << 10) >> 10); - print_address (memaddr + (disp22 << 2), stream); - break; - case 7: - /* CBccc. */ - fprintf (stream, "cb%s", ccc_name[insn.branch.cond]); - if (insn.branch.a) fprintf (stream, ",a "); - else fprintf (stream, " "); - disp22 = insn.branch.disp; - disp22 = ((disp22 << 10) >> 10); - print_address (memaddr + (disp22 << 2), stream); - break; - default: - fprintf (stream, "0x%x (illegal op2 format)", insn.intval); - break; - } - break; - case 2: - { - /* vaguely arithmetic insns. */ - char *rd = reg_names[insn.arith.rd]; - char *rs1 = reg_names[insn.arith.rs1]; + /* Nonzero means that we have found an instruction which has + the effect of adding or or'ing the imm13 field to rs1. */ + int imm_added_to_rs1 = 0; + + /* Nonzero means that we have found a plus sign in the args + field of the opcode table. */ + int found_plus = 0; + + /* Do we have an 'or' instruction where rs1 is the same + as rsd, and which has the i bit set? */ + if (opcode->match == 0x80102000 + && insn.rs1 == insn.rd) + imm_added_to_rs1 = 1; + + if (index (opcode->args, 'S') != 0) + /* Reject the special case for `set'. + The real `sethi' will match. */ + continue; + if (insn.rs1 != insn.rd + && index (opcode->args, 'r') != 0) + /* Can't do simple format if source and dest are different. */ + continue; + + fputs_filtered (opcode->name, stream); - if (insn.op3.op3 <= 28) { - /* Arithmetic insns, with a few unimplemented. */ - register int affect_cc = insn.op3.op3 & 16; - char *name = arith_name[insn.op3.op3 ^ affect_cc]; - char *tmp = affect_cc ? "cc" : ""; + register const char *s; - if (name == 0) - { - fprintf (stream, "0x%08x (unimplemented arithmetic insn)", - insn.intval); - } - else if (insn.arith.i) + if (opcode->args[0] != ',') + fputs_filtered (" ", stream); + for (s = opcode->args; *s != '\0'; ++s) { - /* With explicit sign extension. */ - fprintf (stream, "%s%s %s,0x%x,%s", - name, tmp, rs1, - (int) (insn.arith_imm.simm << 19) >> 19, - rd); - if (last_sethi_target == insn.arith.rd) + if (*s == ',') { - fprintf (stream, "\t! "); - print_address (sethi_value + - (int) (insn.arith_imm.simm << 19) >> 19); + fputs_filtered (",", stream); + ++s; + if (*s == 'a') + { + fputs_filtered ("a", stream); + ++s; + } + fputs_filtered (" ", stream); } - } - else - { - fprintf (stream, "%s%s %s,%s,%s", - name, tmp, rs1, reg_names[insn.arith.rs2], rd); - } - break; - } - if (insn.op3.op3 < 32) - { - fprintf (stream, "0x%08x (unimplemented arithmetic insn)", - insn.intval); - break; - } - else - { - int op = insn.op3.op3 ^ 32; - if (op < 8) - { - char *name = xarith_name[op]; - /* tagged add/sub insns and shift insns. */ - if (insn.arith.i) + switch (*s) { - int i = (int) (insn.arith_imm.simm << 19) >> 19; - if (op > 4) - /* Its a shift insn. */ - i &= 31; - - fprintf (stream, "%s %s,0x%x,%s", - name, rs1, i, rd); + case '+': + found_plus = 1; + + /* note fall-through */ + default: + fprintf_filtered (stream, "%c", *s); + break; + + case '#': + fputs_filtered ("0", stream); + break; + +#define reg(n) fprintf_filtered (stream, "%%%s", reg_names[n]) + case '1': + case 'r': + reg (insn.rs1); + break; + + case '2': + reg (insn.rs2); + break; + + case 'd': + reg (insn.rd); + break; +#undef reg + +#define freg(n) fprintf_filtered (stream, "%%%s", freg_names[n]) + case 'e': + freg (insn.rs1); + break; + + case 'f': + freg (insn.rs2); + break; + + case 'g': + freg (insn.rd); + break; +#undef freg + +#define creg(n) fprintf_filtered (stream, "%%c%u", (unsigned int) (n)) + case 'b': + creg (insn.rs1); + break; + + case 'c': + creg (insn.rs2); + break; + + case 'D': + creg (insn.rd); + break; +#undef creg + + case 'h': + fprintf_filtered (stream, "%%hi(%#x)", + (int) insn.imm22 << 10); + break; + + case 'i': + { + /* We cannot trust the compiler to sign-extend + when extracting the bitfield, hence the shifts. */ + int imm = ((int) insn.imm13 << 19) >> 19; + + /* Check to see whether we have a 1+i, and take + note of that fact. + + Note: because of the way we sort the table, + we will be matching 1+i rather than i+1, + so it is OK to assume that i is after +, + not before it. */ + if (found_plus) + imm_added_to_rs1 = 1; + + if (imm <= 9) + fprintf_filtered (stream, "%d", imm); + else + fprintf_filtered (stream, "%#x", imm); + } + break; + + case 'L': + print_address ((CORE_ADDR) memaddr + insn.disp30 * 4, + stream); + break; + + case 'l': + if ((insn.code >> 22) == 0) + /* Special case for `unimp'. Don't try to turn + it's operand into a function offset. */ + fprintf_filtered (stream, "%#x", + (int) (((int) insn.disp22 << 10) >> 10)); + else + /* We cannot trust the compiler to sign-extend + when extracting the bitfield, hence the shifts. */ + print_address ((CORE_ADDR) + (memaddr + + (((int) insn.disp22 << 10) >> 10) * 4), + stream); + break; + + case 'A': + fprintf_filtered (stream, "(%d)", (int) insn.asi); + break; + + case 'C': + fputs_filtered ("%csr", stream); + break; + + case 'F': + fputs_filtered ("%fsr", stream); + break; + + case 'p': + fputs_filtered ("%psr", stream); + break; + + case 'q': + fputs_filtered ("%fq", stream); + break; + + case 'Q': + fputs_filtered ("%cq", stream); + break; + + case 't': + fputs_filtered ("%tbr", stream); + break; + + case 'w': + fputs_filtered ("%wim", stream); + break; + + case 'y': + fputs_filtered ("%y", stream); + break; } - else - { - fprintf (stream, "%s %s,%s,%s", - name, rs1, reg_names[insn.arith.rs2], rd); - } - break; - } - if (op < 20) - { - /* read/write state registers. */ - char *sr = state_reg_name[op & 7]; - if (sr == 0) - fprintf (stream, "0x%08x (unimplemented state register insn", - insn.intval); - else - fprintf (stream, "%s %s,%s", op & 16 ? "wr" : "rd", sr, rd); - break; } - if (op < 22) - { - /* floating point insns. */ - int opcode = insn.arith.opf; + } - fprint_fpop (stream, insn, op & 3, opcode); - break; - } - if (op < 24) - { - /* coprocessor insns. */ - char *rs2 = reg_names[insn.arith.rs2]; - int opcode = insn.arith.opf; + /* If we are adding or or'ing something to rs1, then + check to see whether the previous instruction was + a sethi to the same register as in the sethi. + If so, attempt to print the result of the add or + or (in this context add and or do the same thing) + and its symbolic value. */ + if (imm_added_to_rs1) + { + union sparc_insn prev_insn; + int errcode; - fprintf (stream, "cpop%d rs1=%s,rs2=%s,op=0x%x,rd=%s", - op & 1, rs1, rs2, opcode, rd); - break; - } + errcode = read_memory (memaddr - 4, + &prev_insn, sizeof (prev_insn)); - switch (op) - { - char *rndop_ptr; - - case 24: - fprint_addr1 (stream, "jumpl", insn); - break; - case 25: - fprint_addr1 (stream, "rett", insn); - break; - case 26: + if (errcode == 0) { - char rndop_buf[32]; - sprintf (rndop_buf, "t%s", icc_name[insn.branch.cond]); - fprint_addr1 (stream, rndop_buf, insn); + /* If it is a delayed branch, we need to look at the + instruction before the delayed branch. This handles + sequences such as + + sethi %o1, %hi(_foo), %o1 + call _printf + or %o1, %lo(_foo), %o1 + */ + + if (is_delayed_branch (prev_insn)) + errcode = read_memory (memaddr - 8, + &prev_insn, sizeof (prev_insn)); } - break; - case 27: - fprint_addr1 (stream, "iflush", insn); - break; - - case 28: - rndop_ptr = "save"; - case 29: - if (op == 29) - rndop_ptr = "restore"; - - if (insn.arith.i) - { - fprintf (stream, "%s %s,0x%x,%s", - rndop_ptr, rs1, - ((int) (insn.arith_imm.simm << 19) >> 19), rd); - } - else - { - fprintf (stream, "%s %s,%s,%s", - rndop_ptr, rs1, reg_names[insn.arith.rs2], rd); - } - break; - case 30: - case 31: - fprintf (stream, "0x%08x (unimplemented op3 insn)", - insn.intval); - break; - } - break; - } - } - case 3: - /* load and store insns. */ - { - char *rd = reg_names[insn.arith.rd]; - char *rs1 = reg_names[insn.arith.rs1]; - int op = insn.arith.op3; - if ((op & 32) == 0) - { - /* Integer ops. */ - fprint_ldst (stream, insn, op); - break; - } - if ((op & 16) == 0) - { - /* Float ops. */ - op ^= 32; - if (op <= 7) - { - fprint_f_ldst (stream, insn, op); - } - else - fprintf (stream, "0x%08x (unimplemented float load/store insn)", - insn.intval); - } - else - { - /* Coprocessor ops. */ - op ^= (32+16); - if (op <= 7) - { - fprint_c_ldst (stream, insn, op); - } - else - fprintf (stream, "0x%08x (unimplemented coprocessor load/store insn)", - insn.intval); - } - break; - } + /* If there was a problem reading memory, then assume + the previous instruction was not sethi. */ + if (errcode == 0) + { + /* Is it sethi to the same register? */ + if ((prev_insn.code & 0xc1c00000) == 0x01000000 + && prev_insn.rd == insn.rs1) + { + fprintf_filtered (stream, "\t! "); + /* We cannot trust the compiler to sign-extend + when extracting the bitfield, hence the shifts. */ + print_address (((int) prev_insn.imm22 << 10) + | (insn.imm13 << 19) >> 19, stream); + } + } + } + + return sizeof (insn); + } } - return 4; + + fprintf_filtered ("%#8x", insn.code); + return sizeof (insn); } -/* It would be nice if this routine could print out a symbolic address - when appropriate. */ -static void -fprint_addr1 (stream, name, insn) - FILE *stream; - char *name; - union insn_fmt insn; -{ - char *rs1 = reg_names[insn.arith.rs1]; - char *rd = reg_names[insn.arith.rd]; - if (insn.arith.i) - { - fprintf (stream, "%s %s,0x%x,%s", - name, rs1, - (int) (insn.arith_imm.simm << 19) >> 19, - rd); - } - else - { - fprintf (stream, "%s %s,%s,%s", - name, rs1, reg_names[insn.arith.rs2], rd); - } -} +/* Compare opcodes A and B. */ -static void -fprint_mem (stream, insn) - FILE *stream; - union insn_fmt insn; +static int +compare_opcodes (a, b) + char *a, *b; { - char *reg_name = reg_names[insn.arith.rs1]; - if (insn.arith.i) - { - if (insn.arith_imm.simm == 0) - fprintf (stream, "[%s]", reg_name); - else if (insn.arith_imm.simm & 0x1000) - fprintf (stream, "[%s-0x%x]", reg_name, - - (insn.arith_imm.simm | 0xffffe000)); - else - fprintf (stream, "[%s+0x%x]", reg_name, insn.arith_imm.simm); - } - else + struct sparc_opcode *op0 = (struct sparc_opcode *) a; + struct sparc_opcode *op1 = (struct sparc_opcode *) b; + unsigned long int match0 = op0->match, match1 = op1->match; + unsigned long int lose0 = op0->lose, lose1 = op1->lose; + register unsigned int i; + + /* If a bit is set in both match and lose, there is something + wrong with the opcode table. */ + if (match0 & lose0) { - if (insn.arith.rs2 == 0) - fprintf (stream, "[%s]", reg_name); - else - fprintf (stream, "[%s,%s]", reg_names[insn.arith.rs2], reg_name); + fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8x, %#.8x\n", + op0->name, match0, lose0); + op0->lose &= ~op0->match; + lose0 = op0->lose; } -} - -static void -fprint_ldst (stream, insn, op) - FILE *stream; - union insn_fmt insn; - int op; -{ - char *name = ldst_i_name[op]; - char *rd = reg_names[insn.arith.rd]; - if (name) + if (match1 & lose1) { - if (name[0] == 's') - { - fprintf (stream, "%s %s,", name, rd); - fprint_mem (stream, insn); - } - else - { - fprintf (stream, "%s ", name); - fprint_mem (stream, insn); - fprintf (stream, ",%s", rd); - } + fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8x, %#.8x\n", + op1->name, match1, lose1); + op1->lose &= ~op1->match; + lose1 = op1->lose; } - else - fprintf (stream, "0x%08x (unimplemented load/store insn)", insn.intval); -} -static void -fprint_f_ldst (stream, insn, op) - FILE *stream; - union insn_fmt insn; - int op; -{ - char *name = ldst_f_name[op]; - if (name) + /* Because the bits that are variable in one opcode are constant in + another, it is important to order the opcodes in the right order. */ + for (i = 0; i < 32; ++i) { - char *rd = reg_names[insn.arith.rd + 32]; + unsigned long int x = 1 << i; + int x0 = (match0 & x) != 0; + int x1 = (match1 & x) != 0; - if (name[0] == 's') - { - fprintf (stream, "%s %s,", name, rd); - fprint_mem (stream, insn); - } - else - { - fprintf (stream, "%s ", name); - fprint_mem (stream, insn); - fprintf (stream, ",%s", rd); - } + if (x0 != x1) + return x1 - x0; } - else - fprintf (stream, "0x%08x (unimplemented float load/store insn)", insn.intval); -} -static void -fprint_c_ldst (stream, insn, op) - FILE *stream; - union insn_fmt insn; - int op; -{ - char *name = ldst_c_name[op]; - if (name) + for (i = 0; i < 32; ++i) { - if (name[0] == 's') - { - fprintf (stream, "%s %%cpreg(%d),", name, insn.arith.rs1); - fprint_mem (stream, insn); - } - else - { - fprintf (stream, "%s "); - fprint_mem (stream, insn); - fprintf (stream, ",%%cpreg(%d)", insn.arith.rd); - } - } - else - fprintf (stream, "0x%08x (unimplemented coprocessor load/store insn)", - insn.intval); -} + unsigned long int x = 1 << i; + int x0 = (lose0 & x) != 0; + int x1 = (lose1 & x) != 0; -static void -fprint_fpop (stream, insn, op, opcode) - FILE *stream; - union insn_fmt insn; - int op, opcode; -{ - char *name; - char *rs1, *rs2, *rd; - - switch (op) - { - case 0: - rs2 = reg_names[insn.arith.rs2 + 32]; - rd = reg_names[insn.arith.rd + 32]; - if ((opcode ^ 0x2f) <= 0x2f) - { - switch (opcode) - { - case 0x1: - name = "fmovs"; - break; - case 0x5: - name = "fnegs"; - break; - case 0x9: - name = "fabss"; - break; - case 0x29: - name = "fsqrts"; - break; - case 0x2a: - name = "fsqrtd"; - break; - case 0x2b: - name = "fsqrtx"; - break; - } - fprintf (stream, "%s %s,%s", name, rs2, rd); - return; - } - if ((opcode ^ 0x5f) <= 0x5f) - { - rs1 = reg_names[insn.arith.rs1 + 32]; - switch (opcode) - { - case 0x41: - name = "fadds"; - break; - case 0x42: - name = "faddd"; - break; - case 0x43: - name = "faddx"; - break; - case 0x45: - name = "fsubs"; - break; - case 0x46: - name = "fsubd"; - break; - case 0x47: - name = "fsubx"; - break; - case 0x49: - name = "fmuls"; - break; - case 0x4a: - name = "fmuld"; - break; - case 0x4b: - name = "fmulx"; - break; - case 0x4d: - name = "fdivs"; - break; - case 0x4e: - name = "fdivd"; - break; - case 0x4f: - name = "fdivx"; - break; - default: - goto unimplemented; - } - if ((opcode & 0x10) == 0) - fprintf (stream, "%s %s,%s,%s", name, rs1, rs2, rd); - else - fprintf (stream, "%s %s,%s", name, rs1, rs2); - return; - } - if ((opcode ^ 0xdf) <= 0xdf) - { - switch (opcode) - { - case 0xc4: - name = "fitos"; - break; - case 0xc8: - name = "fitod"; - break; - case 0xcc: - name = "fitox"; - break; - case 0xd1: - name = "fstoi"; - break; - case 0xd2: - name = "fdtoi"; - break; - case 0xd3: - name = "fxtoi"; - break; - case 0xc9: - name = "fstod"; - break; - case 0xcd: - name = "fstox"; - break; - case 0xc6: - name = "fdtos"; - break; - case 0xce: - name = "fdtox"; - break; - case 0xc7: - name = "fxtos"; - break; - case 0xcb: - name = "fxtod"; - break; - default: - goto unimplemented; - } - fprintf (stream, "%s %s,%s", name, rs2, rd); - return; - } - goto unimplemented; + if (x0 != x1) + return x1 - x0; + } - case 1: - rs1 = reg_names[insn.arith.rs1 + 32]; - rs2 = reg_names[insn.arith.rs2 + 32]; - if ((opcode ^ 0x57) <= 0x57) - { - switch (opcode) - { - case 0x51: - name = "fcmps"; - break; - case 0x52: - name = "fcmpd"; - break; - case 0x53: - name = "fcmpx"; - break; - case 0x55: - name = "fcmpes"; - break; - case 0x56: - name = "fcmped"; - break; - case 0x57: - name = "fcmpex"; - break; - default: - goto unimplemented; - } - fprintf (stream, "%s %s,%s", name, rs1, rs2); - return; - } - else goto unimplemented; + /* They are functionally equal. So as long as the opcode table is + valid, we can put whichever one first we want, on aesthetic grounds. */ + { + int length_diff = strlen (op0->args) - strlen (op1->args); + if (length_diff != 0) + /* Put the one with fewer arguments first. */ + return length_diff; + } + + /* Put 1+i before i+1. */ + { + char *p0 = (char *) index(op0->args, '+'); + char *p1 = (char *) index(op1->args, '+'); + + if (p0 && p1) + { + /* There is a plus in both operands. Note that a plus + sign cannot be the first character in args, + so the following [-1]'s are valid. */ + if (p0[-1] == 'i' && p1[1] == 'i') + /* op0 is i+1 and op1 is 1+i, so op1 goes first. */ + return 1; + if (p0[1] == 'i' && p1[-1] == 'i') + /* op0 is 1+i and op1 is i+1, so op0 goes first. */ + return -1; + } + } - case 2: - case 3: - goto unimplemented; - } - unimplemented: - fprintf (stream, "0x%08x (unimplemented fpop insn)", insn.intval); + /* They are, as far as we can tell, identical. + Since qsort may have rearranged the table partially, there is + no way to tell which one was first in the opcode table as + written, so just say there are equal. */ + return 0; } - diff --git a/gdb/stab.def b/gdb/stab.def index 8657e6b15d..b81cda4bdc 100644 --- a/gdb/stab.def +++ b/gdb/stab.def @@ -1,106 +1,19 @@ /* Table of DBX symbol codes for the GNU system. Copyright (C) 1988 Free Software Foundation, Inc. - NO WARRANTY - - BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY -NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT -WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, -RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS 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. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. -STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY -WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE -LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR -OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR -DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR -A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS -PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. - - GENERAL PUBLIC LICENSE TO COPY - - 1. You may copy and distribute verbatim copies of this source file -as you receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy a valid copyright notice "Copyright - (C) 1988 Free Software Foundation, Inc."; and include following the -copyright notice a verbatim copy of the above disclaimer of warranty -and of this License. You may charge a distribution fee for the -physical act of transferring a copy. - - 2. You may modify your copy or copies of this source file 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 or is a derivative of this - program or any part thereof, to be licensed at no charge to all - third parties on terms identical to those contained in this - License Agreement (except that you may choose to grant more extensive - warranty protection to some or all third parties, at your option). - - c) You may charge a distribution 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 unrelated program with this program (or its -derivative) on a volume of a storage or distribution medium does not bring -the other program under the scope of these terms. - - 3. You may copy and distribute this program or any portion of it in -compiled, executable or object code form under the terms of Paragraphs -1 and 2 above provided that you do 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 - shipping charge) 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.) - -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. - - 4. You may not copy, sublicense, distribute or transfer this program -except as expressly provided under this License Agreement. Any attempt -otherwise to copy, sublicense, distribute or transfer this program is void and -your rights to use the program under this License agreement shall be -automatically terminated. However, parties who have received computer -software programs from you with this License Agreement will not have -their licenses terminated so long as such parties remain in full compliance. - - 5. If you wish to incorporate parts of this program into other free -programs whose distribution conditions are different, write to the Free -Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet -worked out a simple rule that can be stated here, but we will often permit -this. We will be guided by the two goals of preserving the free status of -all derivatives our free software and of promoting the sharing and reuse of -software. - - -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! */ + 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. */ @@ -135,7 +48,8 @@ __define_stab (N_SSYM, 0x60, "SSYM") (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. */ +/* 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. */ diff --git a/gdb/stack.c b/gdb/stack.c index 8a78b09673..981348ad52 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -1,22 +1,21 @@ /* Print and select stack frames for GDB, the GNU debugger. Copyright (C) 1986, 1987, 1989 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! -*/ +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 @@ -24,8 +23,6 @@ anyone else from sharing it farther. Help stamp out software hoarding! #include "param.h" #include "symtab.h" #include "frame.h" -#include "inferior.h" -#include "gdbcore.h" /* Thie "selected" stack frame is used by default for local and arg access. @@ -39,9 +36,6 @@ FRAME selected_frame; int selected_frame_level; -/* Error message when selected_frame is zero when it's needed */ -char no_sel_frame[] = "There is no current stack frame."; - /* Nonzero means print the full filename and linenumber when a frame is printed, and do so in a format programs can parse. */ @@ -51,7 +45,7 @@ static void select_calling_frame (); void print_frame_info (); -/* Print a stack frame briefly. FRAME should be the frame address +/* 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. @@ -61,10 +55,6 @@ void print_frame_info (); If SOURCE is 1, print the source line as well. If SOURCE is -1, print ONLY the source line. */ -/* FIXME, the argument "frame" is always "selected_frame". This is why - we can say "No selected frame" if it == 0. Probably shouldn't be an - argument anymore... */ - static void print_stack_frame (frame, level, source) FRAME frame; @@ -73,13 +63,15 @@ print_stack_frame (frame, level, source) { struct frame_info *fi; - if (frame == 0) - error (no_sel_frame); 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; @@ -91,11 +83,60 @@ print_frame_info (fi, level, source, args) 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); + + printf_filtered ("%s (...) (...)\n", fname); + + return; + } sal = find_pc_line (fi->pc, fi->next_frame); func = find_pc_function (fi->pc); if (func) - funname = SYMBOL_NAME (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); @@ -103,25 +144,27 @@ print_frame_info (fi, level, source, args) funname = misc_function_vector[misc_index].name; } - if (source >= 0 || !sal.symtab) + if (frame_changed || source >= 0 || !sal.symtab) { if (level >= 0) - printf ("#%-2d ", level); + printf_filtered ("#%-2d ", level); + else if (frame_changed) + printf ("#%-2d ", 0); if (fi->pc != sal.pc || !sal.symtab) - printf ("0x%x in ", fi->pc); - printf ("%s (", funname ? funname : "??"); + printf_filtered ("0x%x in ", fi->pc); + printf_filtered ("%s (", funname ? funname : "??"); if (args) { FRAME_NUM_ARGS (numargs, fi); print_frame_args (func, fi, numargs, stdout); } - printf (")"); + printf_filtered (")"); if (sal.symtab) - printf (" (%s line %d)", sal.symtab->filename, sal.line); - printf ("\n"); + printf_filtered (" (%s line %d)", sal.symtab->filename, sal.line); + printf_filtered ("\n"); } - if (source != 0 && sal.symtab) + if ((frame_changed || source != 0) && sal.symtab) { int done = 0; int mid_statement = source < 0 && fi->pc != sal.pc; @@ -130,11 +173,12 @@ print_frame_info (fi, level, source, args) if (!done) { if (mid_statement) - printf ("0x%x\t", fi->pc); + 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); @@ -159,7 +203,7 @@ print_selected_frame () print_stack_frame (selected_frame, selected_frame_level, 0); } -void flush_cached_frames (); /* FIXME, never called! */ +void flush_cached_frames (); #ifdef FRAME_SPECIFICATION_DYADIC extern FRAME setup_arbitrary_frame (); @@ -209,8 +253,6 @@ parse_frame_specification (frame_exp) switch (numargs) { case 0: - if (selected_frame == 0) - error (no_sel_frame); return selected_frame; /* NOTREACHED */ case 1: @@ -276,7 +318,12 @@ frame_info (addr_exp) char *funname = 0; int numargs; + 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); @@ -326,9 +373,12 @@ frame_info (addr_exp) FRAME_NUM_ARGS (numargs, fi); 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]) + if (fsr.regs[i] && i != SP_REGNUM) { if (count % 4 != 0) printf (", "); @@ -389,9 +439,6 @@ backtrace_command (count_exp) register FRAME trailing; register int trailing_level; - if (have_inferior_p () == 0 && corefile == 0) - error ("There is no running program or core file."); - /* 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 @@ -424,11 +471,7 @@ backtrace_command (count_exp) } } else -#if 0 - count = backtrace_limit; -#else count = -1; -#endif for (i = 0, frame = trailing; frame && count--; @@ -441,12 +484,13 @@ backtrace_command (count_exp) /* If we've stopped before the end, mention that. */ if (frame) - printf ("(More stack frames follow...)\n"); + printf_filtered ("(More stack frames follow...)\n"); } -/* Print the local variables of a block B active in FRAME. */ +/* Print the local variables of a block B active in FRAME. + Return 1 if any variables were printed; 0 otherwise. */ -static void +static int print_block_frame_locals (b, frame, stream) struct block *b; register FRAME frame; @@ -455,6 +499,7 @@ print_block_frame_locals (b, frame, stream) int nsyms; register int i; register struct symbol *sym; + register int values_printed = 0; nsyms = BLOCK_NSYMS (b); @@ -465,12 +510,15 @@ print_block_frame_locals (b, frame, stream) || SYMBOL_CLASS (sym) == LOC_REGISTER || SYMBOL_CLASS (sym) == LOC_STATIC) { - fprintf (stream, "%s = ", SYMBOL_NAME (sym)); + values_printed = 1; + fputs_filtered (SYMBOL_NAME (sym), stream); + fputs_filtered (" = ", stream); print_variable_value (sym, frame, stream); - fprintf (stream, "\n"); + fprintf_filtered (stream, "\n"); fflush (stream); } } + return values_printed; } /* Print on STREAM all the local variables in frame FRAME, @@ -486,14 +534,20 @@ print_frame_local_vars (frame, stream) register FRAME frame; register FILE *stream; { - register struct block *block; + register struct block *block = get_frame_block (frame); + register int values_printed = 0; - block = get_frame_block (frame); if (block == 0) - return 0; + { + fprintf_filtered (stream, "No symbol table info available.\n"); + fflush (stream); + return 0; + } + while (block != 0) { - print_block_frame_locals (block, frame, stream); + 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. */ @@ -501,14 +555,22 @@ print_frame_local_vars (frame, stream) break; block = BLOCK_SUPERBLOCK (block); } + + if (!values_printed) + { + fprintf_filtered (stream, "No locals.\n"); + fflush (stream); + } + return 1; } static void locals_info () { - if (selected_frame == 0) - error(no_sel_frame); + if (!have_inferior_p () && !have_core_file_p ()) + error ("No inferior or core file."); + print_frame_local_vars (selected_frame, stdout); } @@ -517,15 +579,19 @@ print_frame_arg_vars (frame, stream) register FRAME frame; register FILE *stream; { - struct symbol *func; + 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; - func = get_frame_function (frame); if (func == 0) - return 0; + { + fprintf_filtered (stream, "No symbol table info available.\n"); + fflush (stream); + return 0; + } b = SYMBOL_BLOCK_VALUE (func); nsyms = BLOCK_NSYMS (b); @@ -533,23 +599,33 @@ print_frame_arg_vars (frame, stream) for (i = 0; i < nsyms; i++) { sym = BLOCK_SYM (b, i); - if (SYMBOL_CLASS (sym) == LOC_ARG || SYMBOL_CLASS (sym) == LOC_REGPARM) + if (SYMBOL_CLASS (sym) == LOC_ARG + || SYMBOL_CLASS (sym) == LOC_REF_ARG + || SYMBOL_CLASS (sym) == LOC_REGPARM) { - fprintf (stream, "%s = ", SYMBOL_NAME (sym)); + values_printed = 1; + fputs_filtered (SYMBOL_NAME (sym), stream); + fputs_filtered (" = ", stream); print_variable_value (sym, frame, stream); - fprintf (stream, "\n"); + fprintf_filtered (stream, "\n"); fflush (stream); } } + if (!values_printed) + { + fprintf_filtered (stream, "No arguments.\n"); + fflush (stream); + } + return 1; } static void args_info () { - if (selected_frame == 0) - error(no_sel_frame); + if (!have_inferior_p () && !have_core_file_p ()) + error ("No inferior or core file."); print_frame_arg_vars (selected_frame, stdout); } @@ -563,6 +639,9 @@ select_frame (frame, 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. */ @@ -607,8 +686,6 @@ find_relative_frame (frame, level_offset_ptr) register FRAME prev; register FRAME frame1, frame2; - if (frame == 0) - error (no_sel_frame); /* Going up is simple: just do get_prev_frame enough times or until initial frame is reached. */ while (*level_offset_ptr > 0) @@ -661,6 +738,9 @@ frame_command (level_exp, 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); @@ -671,6 +751,7 @@ frame_command (level_exp, from_tty) if (!frame1) level = 0; + frame_changed = level; select_frame (frame, level); if (!from_tty) @@ -692,12 +773,16 @@ up_command (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 @@ -719,6 +804,7 @@ down_command (count_exp) select_frame (frame, selected_frame_level + count - count1); print_stack_frame (selected_frame, selected_frame_level, 1); + frame_changed--; } static void @@ -727,6 +813,7 @@ return_command (retval_exp, from_tty) int from_tty; { struct symbol *thisfun = get_frame_function (selected_frame); + FRAME_ADDR selected_frame_addr = FRAME_FP (selected_frame); /* If interactive, require confirmation. */ @@ -742,9 +829,12 @@ return_command (retval_exp, from_tty) error ("Not confirmed."); } - /* Do the real work. Pop until the specified frame is current. */ + /* 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 != get_current_frame ()) + while (selected_frame_addr != FRAME_FP (get_current_frame())) POP_FRAME; /* Then pop that frame. */ diff --git a/gdb/standalone.c b/gdb/standalone.c index eb456ff6fb..5646fb64ff 100644 --- a/gdb/standalone.c +++ b/gdb/standalone.c @@ -1,22 +1,21 @@ /* Interface to bare machine for GDB running as kernel debugger. - Copyright (C) 1986 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! -*/ + 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 #include diff --git a/gdb/stuff.c b/gdb/stuff.c index 0f0a503252..7a2173bea0 100644 --- a/gdb/stuff.c +++ b/gdb/stuff.c @@ -1,22 +1,21 @@ /* Program to stuff files into a specially prepared space in kdb. - Copyright (C) 1986 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! -*/ + 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. */ /* Written 13-Mar-86 by David Bridgham. */ diff --git a/gdb/sun3-dep.c b/gdb/sun3-dep.c index 9bab09592f..0a99e6a5e8 100644 --- a/gdb/sun3-dep.c +++ b/gdb/sun3-dep.c @@ -1,23 +1,22 @@ /* Machine-dependent code which would otherwise be in inflow.c and core.c, for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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" @@ -131,9 +130,9 @@ void fetch_inferior_registers () { struct regs inferior_registers; -#ifndef sun2 +#ifdef FP0_REGNUM struct fp_status inferior_fp_registers; -#endif sun2 +#endif extern char registers[]; if (remote_debugging) @@ -141,22 +140,22 @@ fetch_inferior_registers () else { ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers); -#ifndef sun2 +#ifdef FP0_REGNUM ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers); -#endif sun2 +#endif bcopy (&inferior_registers, registers, 16 * 4); -#ifndef sun2 +#ifdef FP0_REGNUM bcopy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)], sizeof inferior_fp_registers.fps_regs); -#endif sun2 +#endif *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps; *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc; -#ifndef sun2 +#ifdef FP0_REGNUM bcopy (&inferior_fp_registers.fps_control, ®isters[REGISTER_BYTE (FPC_REGNUM)], sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs); -#endif sun2 +#endif } } @@ -296,11 +295,6 @@ write_inferior_memory (memaddr, myaddr, len) /* Machine-dependent code which would otherwise be in core.c */ /* Work with core dump and executable files, for GDB. */ -/* Recognize COFF format systems because a.out.h defines AOUTHDR. */ -#ifdef AOUTHDR -#define COFF_FORMAT -#endif - #ifndef N_TXTADDR #define N_TXTADDR(hdr) 0 #endif /* no N_TXTADDR */ @@ -309,6 +303,15 @@ write_inferior_memory (memaddr, myaddr, len) #define N_DATADDR(hdr) hdr.a_text #endif /* no N_DATADDR */ +/* Non-zero if this is an object (.o) file, rather than an executable. + Distinguishing between the two is rarely necessary (and seems like + a hack, but there is no other way to get the text and data + addresses--N_TXTADDR should probably take care of + this, but it doesn't). */ +/* This definition will not work + if someone decides to make ld preserve relocation info. */ +#define IS_OBJECT_FILE(hdr) (hdr.a_trsize != 0) + /* Make COFF and non-COFF names for things a little more compatible to reduce conditionals later. */ @@ -317,8 +320,10 @@ write_inferior_memory (memaddr, myaddr, len) #endif #ifndef COFF_FORMAT +#ifndef AOUTHDR #define AOUTHDR struct exec #endif +#endif extern char *sys_siglist[]; @@ -421,6 +426,9 @@ core_file_command (filename, from_tty) 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); @@ -449,6 +457,7 @@ core_file_command (filename, from_tty) bcopy (&corestr.c_regs, registers, 16 * 4); *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps; *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc; +#ifdef FP0_REGNUM #ifdef FPU bcopy (corestr.c_fpu.f_fpstatus.fps_regs, ®isters[REGISTER_BYTE (FP0_REGNUM)], @@ -463,6 +472,7 @@ core_file_command (filename, from_tty) bcopy (&corestr.c_fpstatus.fps_control, ®isters[REGISTER_BYTE (FPC_REGNUM)], sizeof corestr.c_fpstatus - sizeof corestr.c_fpstatus.fps_regs); +#endif #endif bcopy (&corestr.c_aouthdr, &core_aouthdr, sizeof (struct exec)); @@ -516,6 +526,9 @@ exec_file_command (filename, from_tty) if (filename) { + filename = tilde_expand (filename); + make_cleanup (free, filename); + execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, &execfile); if (execchan < 0) @@ -559,8 +572,10 @@ exec_file_command (filename, from_tty) if (val < 0) perror_with_name (filename); - text_start = N_TXTADDR (exec_aouthdr); - exec_data_start = N_DATADDR (exec_aouthdr); + text_start = + IS_OBJECT_FILE (exec_aouthdr) ? 0 : N_TXTADDR (exec_aouthdr); + exec_data_start = IS_OBJECT_FILE (exec_aouthdr) + ? exec_aouthdr.a_text : N_DATADDR (exec_aouthdr); text_offset = N_TXTOFF (exec_aouthdr); exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text; diff --git a/gdb/symmetry-dep.c b/gdb/symmetry-dep.c new file mode 100644 index 0000000000..92fd89afa3 --- /dev/null +++ b/gdb/symmetry-dep.c @@ -0,0 +1,1285 @@ +/* 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. */ + +/* many 387-specific items of use taken from i386-dep.c */ + +#include "defs.h" +#include "param.h" +#include "frame.h" +#include "inferior.h" +#include "symtab.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static long i386_get_frame_setup (); +static i386_follow_jump (); + +/* XPT_DEBUG doesn't work yet under Dynix 3.0.12, but UNDEBUG does... */ +#define PTRACE_ATTACH XPT_DEBUG +#define PTRACE_DETACH XPT_UNDEBUG + +#include +#define TERMINAL struct sgttyb + +extern int errno; + +/* Nonzero if we are debugging an attached outside process + rather than an inferior. */ + +static int attach_flag; + +/* 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"); + } +} + +#ifdef ATTACH_DETACH + +/* Start debugging the process whose number is PID. */ + +attach (pid) + int pid; +{ + errno = 0; + ptrace (PTRACE_ATTACH, pid, 0, 0); + if (errno) + perror_with_name ("ptrace"); + attach_flag = 1; + return pid; +} + +/* Stop debugging the process whose number is PID + and continue it with signal number SIGNAL. + SIGNAL = 0 means just continue it. */ + +void +detach (signal) + int signal; +{ + errno = 0; + ptrace (PTRACE_DETACH, inferior_pid, 1, signal); + if (errno) + perror_with_name ("ptrace"); + attach_flag = 0; +} +#endif /* ATTACH_DETACH */ + + +store_inferior_registers(regno) +int regno; +{ + struct pt_regset regs; + int reg_tmp, i; + extern char registers[]; + + if (-1 == regno) + { + regs.pr_eax = *(int *)®isters[REGISTER_BYTE(0)]; + regs.pr_ebx = *(int *)®isters[REGISTER_BYTE(5)]; + regs.pr_ecx = *(int *)®isters[REGISTER_BYTE(2)]; + regs.pr_edx = *(int *)®isters[REGISTER_BYTE(1)]; + regs.pr_esi = *(int *)®isters[REGISTER_BYTE(6)]; + regs.pr_edi = *(int *)®isters[REGISTER_BYTE(7)]; + regs.pr_esp = *(int *)®isters[REGISTER_BYTE(14)]; + regs.pr_ebp = *(int *)®isters[REGISTER_BYTE(15)]; + regs.pr_eip = *(int *)®isters[REGISTER_BYTE(16)]; + regs.pr_flags = *(int *)®isters[REGISTER_BYTE(17)]; + for (i = 0; i < 31; i++) { + regs.pr_fpa.fpa_regs[i] = + *(int *)®isters[REGISTER_BYTE(FP1_REGNUM+i)]; + } + } + else + { + reg_tmp = *(int *)®isters[REGISTER_BYTE(regno)]; + ptrace(XPT_RREGS, inferior_pid, ®s, 0); + switch (regno) + { + case 0: + regs.pr_eax = *(int *)®isters[REGISTER_BYTE(0)]; + break; + case 5: + regs.pr_ebx = *(int *)®isters[REGISTER_BYTE(5)]; + break; + case 2: + regs.pr_ecx = *(int *)®isters[REGISTER_BYTE(2)]; + break; + case 1: + regs.pr_edx = *(int *)®isters[REGISTER_BYTE(1)]; + break; + case 6: + regs.pr_esi = *(int *)®isters[REGISTER_BYTE(6)]; + break; + case 7: + regs.pr_edi = *(int *)®isters[REGISTER_BYTE(7)]; + break; + case 15: + regs.pr_ebp = *(int *)®isters[REGISTER_BYTE(15)]; + break; + case 14: + regs.pr_esp = *(int *)®isters[REGISTER_BYTE(14)]; + break; + case 16: + regs.pr_eip = *(int *)®isters[REGISTER_BYTE(16)]; + break; + case 17: + regs.pr_flags = *(int *)®isters[REGISTER_BYTE(17)]; + break; + } + } + ptrace(XPT_WREGS, inferior_pid, ®s, 0); +} + +void +fetch_inferior_registers() +{ + int i; + struct pt_regset regs; + extern char registers[]; + + ptrace(XPT_RREGS, inferior_pid, ®s, 0); + *(int *)®isters[REGISTER_BYTE(0)] = regs.pr_eax; + *(int *)®isters[REGISTER_BYTE(5)] = regs.pr_ebx; + *(int *)®isters[REGISTER_BYTE(2)] = regs.pr_ecx; + *(int *)®isters[REGISTER_BYTE(1)] = regs.pr_edx; + *(int *)®isters[REGISTER_BYTE(6)] = regs.pr_esi; + *(int *)®isters[REGISTER_BYTE(7)] = regs.pr_edi; + *(int *)®isters[REGISTER_BYTE(15)] = regs.pr_ebp; + *(int *)®isters[REGISTER_BYTE(14)] = regs.pr_esp; + *(int *)®isters[REGISTER_BYTE(16)] = regs.pr_eip; + *(int *)®isters[REGISTER_BYTE(17)] = regs.pr_flags; + for (i = 0; i < FPA_NREGS; i++) { + *(int *)®isters[REGISTER_BYTE(FP1_REGNUM+i)] = regs.pr_fpa.fpa_regs[i]; + } + bcopy(regs.pr_fpu.fpu_stack[0], ®isters[REGISTER_BYTE(3)], 10); + bcopy(regs.pr_fpu.fpu_stack[1], ®isters[REGISTER_BYTE(4)], 10); + bcopy(regs.pr_fpu.fpu_stack[2], ®isters[REGISTER_BYTE(8)], 10); + bcopy(regs.pr_fpu.fpu_stack[3], ®isters[REGISTER_BYTE(9)], 10); + bcopy(regs.pr_fpu.fpu_stack[4], ®isters[REGISTER_BYTE(10)], 10); + bcopy(regs.pr_fpu.fpu_stack[5], ®isters[REGISTER_BYTE(11)], 10); + bcopy(regs.pr_fpu.fpu_stack[6], ®isters[REGISTER_BYTE(12)], 10); + bcopy(regs.pr_fpu.fpu_stack[7], ®isters[REGISTER_BYTE(13)], 10); +} + + +/* Copy LEN bytes from inferior's memory starting at MEMADDR + to debugger memory starting at MYADDR. */ + +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)); + + /* Read all the longwords */ + for (i = 0; i < count; i++, addr += sizeof (int)) { + errno = 0; + if (remote_debugging) + buffer[i] = remote_fetch_word (addr); + else + 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) + buffer[0] = remote_fetch_word (addr); + else + buffer[0] = ptrace (1, inferior_pid, addr, 0); + + if (count > 1) + { + if (remote_debugging) + buffer[count - 1] + = remote_fetch_word (addr + (count - 1) * sizeof (int)); + else + 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; + if (remote_debugging) + remote_store_word (addr, buffer[i]); + else + ptrace (4, inferior_pid, addr, buffer[i]); + if (errno) + return errno; + } + + return 0; +} + + +/* Recognize COFF format systems because a.out.h defines AOUTHDR. */ +#ifdef AOUTHDR +#define COFF_FORMAT +#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 */ + +/* 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 +#define AOUTHDR struct exec +#endif + +extern char *sys_siglist[]; + +/* Hook for `exec_file_command' command to call. */ + +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. */ + +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 (); +unsigned int register_addr (); + +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; + int reg_offset; + + val = myread (corechan, &u, sizeof u); + if (val < 0) + perror_with_name (filename); + data_start = exec_data_start; + + data_end = data_start + NBPG * (u.u_dsize - u.u_tsize); + stack_start = stack_end - NBPG * u.u_ssize; + data_offset = NBPG * UPAGES; + stack_offset = ctob(UPAGES + u.u_dsize - u.u_tsize); + reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR; +printf("u.u_tsize= %#x, u.u_dsize= %#x, u.u_ssize= %#x, stack_off= %#x\n", + u.u_tsize, u.u_dsize, u.u_ssize, stack_offset); + + core_aouthdr.a_magic = 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) + perror_with_name (filename); + + val = myread (corechan, buf, sizeof buf); + if (val < 0) + perror_with_name (filename); + 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())); +/* set_current_frame (read_register (FP_REGNUM));*/ + 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) < 0) + error ("\"%s\": can't read text section header", execfile); + + if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections) < 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; + + val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR)); + + if (val < 0) + perror_with_name (filename); + + text_start = N_ADDRADJ(exec_aouthdr); + exec_data_start = round(exec_aouthdr.a_text, NBPG*CLSIZE); + text_offset = N_TXTOFF (exec_aouthdr); + exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text; + text_end = exec_aouthdr.a_text; + exec_data_end = exec_data_start + exec_aouthdr.a_data; + data_start = exec_data_start; + data_end = data_start + exec_aouthdr.a_data; + exec_data_offset = N_TXTOFF(exec_aouthdr); + fstat (execchan, &st_exec); + 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); +} + +/* rounds 'one' up to divide evenly by 'two' */ + +int +round(one,two) +register int one, two; + +{ + register int temp; + temp = (one/two)*two; + if (one != temp) { + temp += two; + } + return temp; +} + + +static CORE_ADDR codestream_next_addr; +static CORE_ADDR codestream_addr; +static unsigned char codestream_buf[sizeof (int)]; +static int codestream_off; +static int codestream_cnt; + +#define codestream_tell() (codestream_addr + codestream_off) +#define codestream_peek() (codestream_cnt == 0 ? \ + codestream_fill(1): codestream_buf[codestream_off]) +#define codestream_get() (codestream_cnt-- == 0 ? \ + codestream_fill(0) : codestream_buf[codestream_off++]) + + +static unsigned char +codestream_fill (peek_flag) +{ + codestream_addr = codestream_next_addr; + codestream_next_addr += sizeof (int); + codestream_off = 0; + codestream_cnt = sizeof (int); + read_memory (codestream_addr, + (unsigned char *)codestream_buf, + sizeof (int)); + + if (peek_flag) + return (codestream_peek()); + else + return (codestream_get()); +} + +static void +codestream_seek (place) +{ + codestream_next_addr = place & -sizeof (int); + codestream_cnt = 0; + codestream_fill (1); + while (codestream_tell() != place) + codestream_get (); +} + +static void +codestream_read (buf, count) + unsigned char *buf; +{ + unsigned char *p; + int i; + p = buf; + for (i = 0; i < count; i++) + *p++ = codestream_get (); +} + +/* + * Following macro translates i386 opcode register numbers to Symmetry + * register numbers. This is used by FRAME_FIND_SAVED_REGS. + * + * %eax %ecx %edx %ebx %esp %ebp %esi %edi + * i386 0 1 2 3 4 5 6 7 + * Symmetry 0 2 1 5 14 15 6 7 + * + */ +#define I386_REGNO_TO_SYMMETRY(n) \ +((n)==0?0 :(n)==1?2 :(n)==2?1 :(n)==3?5 :(n)==4?14 :(n)==5?15 :(n)) + +/* from i386-dep.c */ +i386_frame_find_saved_regs (fip, fsrp) + struct frame_info *fip; + struct frame_saved_regs *fsrp; +{ + unsigned long locals; + unsigned char *p; + unsigned char op; + CORE_ADDR dummy_bottom; + CORE_ADDR adr; + int i; + + bzero (fsrp, sizeof *fsrp); + + /* if frame is the end of a dummy, compute where the + * beginning would be + */ + dummy_bottom = fip->frame - 4 - NUM_REGS*4 - CALL_DUMMY_LENGTH; + + /* check if the PC is in the stack, in a dummy frame */ + if (dummy_bottom <= fip->pc && fip->pc <= fip->frame) + { + /* all regs were saved by push_call_dummy () */ + adr = fip->frame - 4; + for (i = 0; i < NUM_REGS; i++) + { + fsrp->regs[i] = adr; + adr -= 4; + } + return; + } + + locals = i386_get_frame_setup (get_pc_function_start (fip->pc)); + + if (locals >= 0) + { + adr = fip->frame - 4 - locals; + for (i = 0; i < 8; i++) + { + op = codestream_get (); + if (op < 0x50 || op > 0x57) + break; + fsrp->regs[I386_REGNO_TO_SYMMETRY(op - 0x50)] = adr; + adr -= 4; + } + } + + fsrp->regs[PC_REGNUM] = fip->frame + 4; + fsrp->regs[FP_REGNUM] = fip->frame; +} + +/* from i386-dep.c */ +static +print_387_control_word (control) +unsigned short control; +{ + printf ("control 0x%04x: ", control); + printf ("compute to "); + switch ((control >> 8) & 3) + { + case 0: printf ("24 bits; "); break; + case 1: printf ("(bad); "); break; + case 2: printf ("53 bits; "); break; + case 3: printf ("64 bits; "); break; + } + printf ("round "); + switch ((control >> 10) & 3) + { + case 0: printf ("NEAREST; "); break; + case 1: printf ("DOWN; "); break; + case 2: printf ("UP; "); break; + case 3: printf ("CHOP; "); break; + } + if (control & 0x3f) + { + printf ("mask:"); + if (control & 0x0001) printf (" INVALID"); + if (control & 0x0002) printf (" DENORM"); + if (control & 0x0004) printf (" DIVZ"); + if (control & 0x0008) printf (" OVERF"); + if (control & 0x0010) printf (" UNDERF"); + if (control & 0x0020) printf (" LOS"); + printf (";"); + } + printf ("\n"); + if (control & 0xe080) printf ("warning: reserved bits on 0x%x\n", + control & 0xe080); +} + +static +print_387_status_word (status) + unsigned short status; +{ + printf ("status %#04x: ", status); + if (status & 0xff) { + printf ("exceptions:"); /* exception names match */ + if (status & 0x0001) printf (" FLTINV"); + if (status & 0x0002) printf (" FLTDEN"); + if (status & 0x0004) printf (" FLTDIV"); + if (status & 0x0008) printf (" FLTOVF"); + if (status & 0x0010) printf (" FLTUND"); + if (status & 0x0020) printf (" FLTPRE"); + if (status & 0x0040) printf (" FLTSTK"); + printf ("; "); + } + printf ("flags: %d%d%d%d; ", + (status & 0x4000) != 0, + (status & 0x0400) != 0, + (status & 0x0200) != 0, + (status & 0x0100) != 0); + + printf ("top %d\n", (status >> 11) & 7); +} + +static +print_fpu_status(ep) +struct pt_regset ep; + +{ + int i; + int bothstatus; + int top; + int fpreg; + unsigned char *p; + + printf("80387:"); + if (ep.pr_fpu.fpu_ip == 0) { + printf(" not in use.\n"); + return; + } else { + printf("\n"); + } + if (ep.pr_fpu.fpu_status != 0) { + print_387_status_word (ep.pr_fpu.fpu_status); + } + print_387_control_word (ep.pr_fpu.fpu_control); + printf ("last exception: "); + printf ("opcode 0x%x; ", ep.pr_fpu.fpu_rsvd4); + printf ("pc 0x%x:0x%x; ", ep.pr_fpu.fpu_cs, ep.pr_fpu.fpu_ip); + printf ("operand 0x%x:0x%x\n", ep.pr_fpu.fpu_data_offset, ep.pr_fpu.fpu_op_sel); + + top = (ep.pr_fpu.fpu_status >> 11) & 7; + + printf ("regno tag msb lsb value\n"); + for (fpreg = 7; fpreg >= 0; fpreg--) + { + double val; + + printf ("%s %d: ", fpreg == top ? "=>" : " ", fpreg); + + switch ((ep.pr_fpu.fpu_tag >> (fpreg * 2)) & 3) + { + case 0: printf ("valid "); break; + case 1: printf ("zero "); break; + case 2: printf ("trap "); break; + case 3: printf ("empty "); break; + } + for (i = 9; i >= 0; i--) + printf ("%02x", ep.pr_fpu.fpu_stack[fpreg][i]); + + i387_to_double (ep.pr_fpu.fpu_stack[fpreg], (char *)&val); + printf (" %g\n", val); + } + if (ep.pr_fpu.fpu_rsvd1) + printf ("warning: rsvd1 is 0x%x\n", ep.pr_fpu.fpu_rsvd1); + if (ep.pr_fpu.fpu_rsvd2) + printf ("warning: rsvd2 is 0x%x\n", ep.pr_fpu.fpu_rsvd2); + if (ep.pr_fpu.fpu_rsvd3) + printf ("warning: rsvd3 is 0x%x\n", ep.pr_fpu.fpu_rsvd3); + if (ep.pr_fpu.fpu_rsvd5) + printf ("warning: rsvd5 is 0x%x\n", ep.pr_fpu.fpu_rsvd5); +} + + +print_1167_control_word(pcr) +unsigned int pcr; + +{ + int pcr_tmp; + + pcr_tmp = pcr & FPA_PCR_MODE; + printf("\tMODE= %#x; RND= %#x ", pcr_tmp, pcr_tmp & 12); + switch (pcr_tmp & 12) { + case 0: + printf("RN (Nearest Value)"); + break; + case 1: + printf("RZ (Zero)"); + break; + case 2: + printf("RP (Positive Infinity)"); + break; + case 3: + printf("RM (Negative Infinity)"); + break; + } + printf("; IRND= %d ", pcr_tmp & 2); + if (0 == pcr_tmp & 2) { + printf("(same as RND)\n"); + } else { + printf("(toward zero)\n"); + } + pcr_tmp = pcr & FPA_PCR_EM; + printf("\tEM= %#x", pcr_tmp); + if (pcr_tmp & FPA_PCR_EM_DM) printf(" DM"); + if (pcr_tmp & FPA_PCR_EM_UOM) printf(" UOM"); + if (pcr_tmp & FPA_PCR_EM_PM) printf(" PM"); + if (pcr_tmp & FPA_PCR_EM_UM) printf(" UM"); + if (pcr_tmp & FPA_PCR_EM_OM) printf(" OM"); + if (pcr_tmp & FPA_PCR_EM_ZM) printf(" ZM"); + if (pcr_tmp & FPA_PCR_EM_IM) printf(" IM"); + printf("\n"); + pcr_tmp = FPA_PCR_CC; + printf("\tCC= %#x", pcr_tmp); + if (pcr_tmp & FPA_PCR_20MHZ) printf(" 20MHZ"); + if (pcr_tmp & FPA_PCR_CC_Z) printf(" Z"); + if (pcr_tmp & FPA_PCR_CC_C2) printf(" C2"); + if (pcr_tmp & FPA_PCR_CC_C1) printf(" C1"); + switch (pcr_tmp) { + case FPA_PCR_CC_Z: + printf(" (Equal)"); + break; + case FPA_PCR_CC_C1: + printf(" (Less than)"); + break; + case 0: + printf(" (Greater than)"); + break; + case FPA_PCR_CC_Z | FPA_PCR_CC_C1 | FPA_PCR_CC_C2: + printf(" (Unordered)"); + break; + default: + printf(" (Undefined)"); + break; + } + printf("\n"); + pcr_tmp = pcr & FPA_PCR_AE; + printf("\tAE= %#x", pcr_tmp); + if (pcr_tmp & FPA_PCR_AE_DE) printf(" DE"); + if (pcr_tmp & FPA_PCR_AE_UOE) printf(" UOE"); + if (pcr_tmp & FPA_PCR_AE_PE) printf(" PE"); + if (pcr_tmp & FPA_PCR_AE_UE) printf(" UE"); + if (pcr_tmp & FPA_PCR_AE_OE) printf(" OE"); + if (pcr_tmp & FPA_PCR_AE_ZE) printf(" ZE"); + if (pcr_tmp & FPA_PCR_AE_EE) printf(" EE"); + if (pcr_tmp & FPA_PCR_AE_IE) printf(" IE"); + printf("\n"); +} + +print_1167_regs(regs) +long regs[FPA_NREGS]; + +{ + int i; + + union { + double d; + long l[2]; + } xd; + union { + float f; + long l; + } xf; + + + for (i = 0; i < FPA_NREGS; i++) { + xf.l = regs[i]; + printf("%%fp%d: raw= %#x, single= %f", i+1, regs[i], xf.f); + if (!(i & 1)) { + printf("\n"); + } else { + xd.l[1] = regs[i]; + xd.l[0] = regs[i+1]; + printf(", double= %f\n", xd.d); + } + } +} + +print_fpa_status(ep) +struct pt_regset ep; + +{ + + printf("WTL 1167:"); + if (ep.pr_fpa.fpa_pcr !=0) { + printf("\n"); + print_1167_control_word(ep.pr_fpa.fpa_pcr); + print_1167_regs(ep.pr_fpa.fpa_regs); + } else { + printf(" not in use.\n"); + } +} + +i386_float_info () + +{ + char ubuf[UPAGES*NBPG]; + struct pt_regset regset; + extern int corechan; + + if (have_inferior_p()) { + call_ptrace(XPT_RREGS, inferior_pid, ®set, 0); + } else { + if (lseek (corechan, 0, 0) < 0) { + perror ("seek on core file"); + } + if (myread (corechan, ubuf, UPAGES*NBPG) < 0) { + perror ("read on core file"); + } + /* only interested in the floating point registers */ + regset.pr_fpu = ((struct user *) ubuf)->u_fpusave; + regset.pr_fpa = ((struct user *) ubuf)->u_fpasave; + } + print_fpu_status(regset); + print_fpa_status(regset); +} + +i387_to_double (from, to) + char *from; + char *to; +{ + long *lp; + /* push extended mode on 387 stack, then pop in double mode + * + * first, set exception masks so no error is generated - + * number will be rounded to inf or 0, if necessary + */ + asm ("pushl %eax"); /* grab a stack slot */ + asm ("fstcw (%esp)"); /* get 387 control word */ + asm ("movl (%esp),%eax"); /* save old value */ + asm ("orl $0x3f,%eax"); /* mask all exceptions */ + asm ("pushl %eax"); + asm ("fldcw (%esp)"); /* load new value into 387 */ + + asm ("movl 8(%ebp),%eax"); + asm ("fldt (%eax)"); /* push extended number on 387 stack */ + asm ("fwait"); + asm ("movl 12(%ebp),%eax"); + asm ("fstpl (%eax)"); /* pop double */ + asm ("fwait"); + + asm ("popl %eax"); /* flush modified control word */ + asm ("fnclex"); /* clear exceptions */ + asm ("fldcw (%esp)"); /* restore original control word */ + asm ("popl %eax"); /* flush saved copy */ +} + +double_to_i387 (from, to) + char *from; + char *to; +{ + /* push double mode on 387 stack, then pop in extended mode + * no errors are possible because every 64-bit pattern + * can be converted to an extended + */ + asm ("movl 8(%ebp),%eax"); + asm ("fldl (%eax)"); + asm ("fwait"); + asm ("movl 12(%ebp),%eax"); + asm ("fstpt (%eax)"); + asm ("fwait"); +} + +static long +i386_get_frame_setup (pc) +{ + unsigned char op; + + codestream_seek (pc); + + i386_follow_jump (); + + op = codestream_get (); + + if (op == 0x58) /* popl %eax */ + { + /* + * this function must start with + * + * popl %eax 0x58 + * xchgl %eax, (%esp) 0x87 0x04 0x24 + * or xchgl %eax, 0(%esp) 0x87 0x44 0x24 0x00 + * + * (the system 5 compiler puts out the second xchg + * inst, and the assembler doesn't try to optimize it, + * so the 'sib' form gets generated) + * + * this sequence is used to get the address of the return + * buffer for a function that returns a structure + */ + int pos; + unsigned char buf[4]; + static unsigned char proto1[3] = { 0x87,0x04,0x24 }; + static unsigned char proto2[4] = { 0x87,0x44,0x24,0x00 }; + pos = codestream_tell (); + codestream_read (buf, 4); + if (bcmp (buf, proto1, 3) == 0) + pos += 3; + else if (bcmp (buf, proto2, 4) == 0) + pos += 4; + + codestream_seek (pos); + op = codestream_get (); /* update next opcode */ + } + + if (op == 0x55) /* pushl %esp */ + { + if (codestream_get () != 0x8b) /* movl %esp, %ebp (2bytes) */ + return (-1); + if (codestream_get () != 0xec) + return (-1); + /* + * check for stack adjustment + * + * subl $XXX, %esp + * + * note: you can't subtract a 16 bit immediate + * from a 32 bit reg, so we don't have to worry + * about a data16 prefix + */ + op = codestream_peek (); + if (op == 0x83) /* subl with 8 bit immed */ + { + codestream_get (); + if (codestream_get () != 0xec) + return (-1); + /* subl with signed byte immediate + * (though it wouldn't make sense to be negative) + */ + return (codestream_get()); + } + else if (op == 0x81) /* subl with 32 bit immed */ + { + int locals; + if (codestream_get () != 0xec) + return (-1); + /* subl with 32 bit immediate */ + codestream_read ((unsigned char *)&locals, 4); + return (locals); + } + else + { + return (0); + } + } + else if (op == 0xc8) + { + /* enter instruction: arg is 16 unsigned immed */ + unsigned short slocals; + codestream_read ((unsigned char *)&slocals, 2); + codestream_get (); /* flush final byte of enter instruction */ + return (slocals); + } + return (-1); +} + +/* next instruction is a jump, move to target */ +static +i386_follow_jump () +{ + int long_delta; + short short_delta; + char byte_delta; + int data16; + int pos; + + pos = codestream_tell (); + + data16 = 0; + if (codestream_peek () == 0x66) + { + codestream_get (); + data16 = 1; + } + + switch (codestream_get ()) + { + case 0xe9: + /* relative jump: if data16 == 0, disp32, else disp16 */ + if (data16) + { + codestream_read ((unsigned char *)&short_delta, 2); + pos += short_delta + 3; /* include size of jmp inst */ + } + else + { + codestream_read ((unsigned char *)&long_delta, 4); + pos += long_delta + 5; + } + break; + case 0xeb: + /* relative jump, disp8 (ignore data16) */ + codestream_read ((unsigned char *)&byte_delta, 1); + pos += byte_delta + 2; + break; + } + codestream_seek (pos + data16); +} + +/* return pc of first real instruction */ +/* from i386-dep.c */ + +i386_skip_prologue (pc) +{ + unsigned char op; + int i; + + if (i386_get_frame_setup (pc) < 0) + return (pc); + + /* found valid frame setup - codestream now points to + * start of push instructions for saving registers + */ + + /* skip over register saves */ + for (i = 0; i < 8; i++) + { + op = codestream_peek (); + /* break if not pushl inst */ + if (op < 0x50 || op > 0x57) + break; + codestream_get (); + } + + i386_follow_jump (); + + return (codestream_tell ()); +} + +symmetry_extract_return_value(type, regbuf, valbuf) + struct type *type; + char *regbuf; + char *valbuf; +{ + union { + double d; + int l[2]; + } xd; + int i; + float f; + + if (TYPE_CODE_FLT == TYPE_CODE(type)) { + for (i = 0; i < misc_function_count; i++) { + if (!strcmp(misc_function_vector[i].name, "1167_flt")) + break; + } + if (i < misc_function_count) { + /* found "1167_flt" means 1167, %fp2-%fp3 */ + /* float & double; 19= %fp2, 20= %fp3 */ + /* no single precision on 1167 */ + xd.l[1] = *((int *)®buf[REGISTER_BYTE(19)]); + xd.l[0] = *((int *)®buf[REGISTER_BYTE(20)]); + switch (TYPE_LENGTH(type)) { + case 4: + f = (float) xd.d; + bcopy(&f, valbuf, TYPE_LENGTH(type)); + break; + case 8: + bcopy(&xd.d, valbuf, TYPE_LENGTH(type)); + break; + default: + error("Unknown floating point size"); + break; + } + } else { + /* 387 %st(0), gcc uses this */ + i387_to_double(((int *)®buf[REGISTER_BYTE(3)]), + &xd.d); + switch (TYPE_LENGTH(type)) { + case 4: /* float */ + f = (float) xd.d; + bcopy(&f, valbuf, 4); + break; + case 8: /* double */ + bcopy(&xd.d, valbuf, 8); + break; + default: + error("Unknown floating point size"); + break; + } + } + } else { + bcopy (regbuf, valbuf, TYPE_LENGTH (type)); + } +} diff --git a/gdb/symmisc.c b/gdb/symmisc.c index 313f65dafb..600bb28a4b 100644 --- a/gdb/symmisc.c +++ b/gdb/symmisc.c @@ -1,22 +1,21 @@ /* Do various things to symbol tables (other than lookup)), for GDB. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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" @@ -377,7 +376,7 @@ read_symsegs (desc, name) } static int block_depth (); -static void print_spaces (); +void print_spaces (); static void print_symbol (); void @@ -397,6 +396,10 @@ print_symtabs (filename) 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); @@ -518,6 +521,10 @@ print_symbol (symbol, depth, outfile) 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; diff --git a/gdb/symseg.h b/gdb/symseg.h index a142e925d2..468580e05d 100644 --- a/gdb/symseg.h +++ b/gdb/symseg.h @@ -1,23 +1,22 @@ /* GDB symbol table format definitions. - Copyright (C) 1986 Free Software Foundation, Inc. + Copyright (C) 1986, 1989 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@mcc.com) -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. +This file is part of GDB. -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. +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. -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! -*/ +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 @@ -121,17 +120,31 @@ enum type_code /* 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 - -/* Other flag bits are used with GDB. */ - +/* 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 @@ -146,7 +159,7 @@ struct 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 type, describes the type of the value. + 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; @@ -157,6 +170,8 @@ struct type 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 @@ -182,8 +197,6 @@ struct type 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". - For range types, there are two "fields", that record constant values - (inclusive) for the minimum and maximum. Using a pointer to a separate array of fields allows all types to have the same size, which is useful @@ -225,7 +238,7 @@ struct type /* 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. */ + has been renamed to make it distinct. */ struct fn_fieldlist { /* The overloaded name. */ @@ -239,7 +252,7 @@ struct type /* The overloaded name */ char *name; #endif - /* The type of the argument */ + /* The return value of the method */ struct type *type; /* The argument list */ struct type **args; @@ -383,6 +396,8 @@ enum address_class 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 @@ -428,13 +443,23 @@ struct partial_symbol enum namespace namespace; /* Address class (for info_symbols) */ enum address_class class; + /* Value (only used for static functions currently). Done this + way so that we can use the struct symbol macros. */ + union + { + long value; + } + value; }; /* * Vectors of all partial symbols read in from file; actually declared * and used in dbxread.c. */ -extern struct partial_symbol *global_psymbols, *static_psymbols; +extern struct psymbol_allocation_list { + struct partial_symbol *list, *next; + int size; +} global_psymbols, static_psymbols; /* Source-file information. diff --git a/gdb/symtab.c b/gdb/symtab.c index 5b36c71f1f..a8108d8546 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -1,22 +1,21 @@ /* Symbol table lookup for the GNU debugger, GDB. - Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1988, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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" @@ -26,6 +25,7 @@ anyone else from sharing it farther. Help stamp out software hoarding! #include #include +char *index (); /* Allocate an obstack to hold objects that should be freed when we load a new symbol table. @@ -78,42 +78,88 @@ struct partial_symtab *lookup_partial_symtab (); struct symtab *psymtab_to_symtab (); static struct partial_symbol *lookup_partial_symbol (); -/* Lookup the symbol table of a source file named NAME. If there - isn't any symtab for it, lookup the psymtab and read in the - symbtab. */ +/* Check for a symtab of a specific name; first in symtabs, then in + psymtabs. *If* there is no '/' in the name, a match after a '/' + in the symtab filename will also work. */ -struct symtab * -lookup_symtab (name) +static struct symtab * +lookup_symtab_1 (name) char *name; { register struct symtab *s; register struct partial_symtab *ps; - register char *copy; + register char *slash = index (name, '/'); + register int len = strlen (name); for (s = symtab_list; s; s = s->next) if (!strcmp (name, s->filename)) return s; + for (ps = partial_symtab_list; ps; ps = ps->next) + if (!strcmp (name, ps->filename)) + { + if (ps->readin) + fatal ("Internal: readin pst found when no symtab found."); + s = psymtab_to_symtab (ps); + return s; + } + + if (!slash) + { + for (s = symtab_list; s; s = s->next) + { + int l = strlen (s->filename); + + if (s->filename[l - len -1] == '/' + && !strcmp (s->filename + l - len, name)) + return s; + } + + for (ps = partial_symtab_list; ps; ps = ps->next) + { + int l = strlen (ps->filename); + + if (ps->filename[l - len - 1] == '/' + && !strcmp (ps->filename + l - len, name)) + { + if (ps->readin) + fatal ("Internal: readin pst found when no symtab found."); + s = psymtab_to_symtab (ps); + return s; + } + } + } + return 0; +} + +/* Lookup the symbol table of a source file named NAME. Try a couple + of variations if the first lookup doesn't work. */ + +struct symtab * +lookup_symtab (name) + char *name; +{ + register struct symtab *s; + register char *copy; + + s = lookup_symtab_1 (name); + if (s) return s; + /* If name not found as specified, see if adding ".c" helps. */ copy = (char *) alloca (strlen (name) + 3); strcpy (copy, name); strcat (copy, ".c"); - for (s = symtab_list; s; s = s->next) - if (!strcmp (copy, s->filename)) - return s; - - ps = lookup_partial_symtab (name); - if (ps) - { - s = psymtab_to_symtab (ps); - return s; - } + s = lookup_symtab_1 (copy); + if (s) return s; + /* We didn't find anything; die. */ return 0; } -/* Lookup the partial symbol table of a source file named NAME. */ +/* Lookup the partial symbol table of a source file named NAME. This + only returns true on an exact match (ie. this semantics are + different from lookup_symtab. */ struct partial_symtab * lookup_partial_symtab (name) @@ -126,15 +172,6 @@ char *name; if (!strcmp (name, s->filename)) return s; - /* If name not found as specified, see if adding ".c" helps. */ - - copy = (char *) alloca (strlen (name) + 3); - strcpy (copy, name); - strcat (copy, ".c"); - for (s = partial_symtab_list; s; s = s->next) - if (!strcmp (copy, s->filename)) - return s; - return 0; } @@ -241,6 +278,41 @@ lookup_enum (name, block) return SYMBOL_TYPE (sym); } +/* Given a type TYPE, lookup the type of the component of type named + NAME. */ + +struct type * +lookup_struct_elt_type (type, name) + struct type *type; + char *name; +{ + struct type *t; + int i; + char *errmsg; + + if (TYPE_CODE (type) != TYPE_CODE_STRUCT + && TYPE_CODE (type) != TYPE_CODE_UNION) + { + terminal_ours (); + fflush (stdout); + fprintf (stderr, "Type "); + type_print (type, "", stderr, -1); + fprintf (stderr, " is not a structure or union type.\n"); + return_to_top_level (); + } + + for (i = TYPE_NFIELDS (type) - 1; i >= 0; i--) + if (!strcmp (TYPE_FIELD_NAME (type, i), name)) + return TYPE_FIELD_TYPE (type, i); + + terminal_ours (); + fflush (stdout); + fprintf (stderr, "Type "); + type_print (type, "", stderr, -1); + fprintf (stderr, " has no component named %s\n", name); + return_to_top_level (); +} + /* Given a type TYPE, return a type of pointers to that type. May need to construct such a type if this is the first use. @@ -361,6 +433,73 @@ lookup_member_type (type, domain) return mtype; } +struct type * +lookup_method_type (type, domain, args) + struct type *type, *domain, **args; +{ + register struct type *mtype = TYPE_MAIN_VARIANT (type); + struct type *main_type; + + main_type = mtype; + while (mtype) + { + if (TYPE_DOMAIN_TYPE (mtype) == domain) + { + struct type **t1 = args; + struct type **t2 = TYPE_ARG_TYPES (mtype); + if (t2) + { + int i; + for (i = 0; t1[i] != 0 && t1[i]->code != TYPE_CODE_VOID; i++) + if (t1[i] != t2[i]) + break; + if (t1[i] == t2[i]) + return mtype; + } + } + mtype = TYPE_NEXT_VARIANT (mtype); + } + + /* This is the first time anyone wanted this member type. */ + if (TYPE_FLAGS (type) & TYPE_FLAG_PERM) + mtype = (struct type *) xmalloc (sizeof (struct type)); + else + mtype = (struct type *) obstack_alloc (symbol_obstack, + sizeof (struct type)); + + bzero (mtype, sizeof (struct type)); + if (main_type == 0) + main_type = mtype; + else + { + TYPE_NEXT_VARIANT (mtype) = TYPE_NEXT_VARIANT (main_type); + TYPE_NEXT_VARIANT (main_type) = mtype; + } + TYPE_MAIN_VARIANT (mtype) = main_type; + TYPE_TARGET_TYPE (mtype) = type; + TYPE_DOMAIN_TYPE (mtype) = domain; + TYPE_ARG_TYPES (mtype) = args; + /* New type is permanent if type pointed to is permanent. */ + if (TYPE_FLAGS (type) & TYPE_FLAG_PERM) + TYPE_FLAGS (mtype) |= TYPE_FLAG_PERM; + + /* In practice, this is never used. */ + TYPE_LENGTH (mtype) = 1; + TYPE_CODE (mtype) = TYPE_CODE_METHOD; + +#if 0 + /* Now splice in the new member pointer type. */ + if (main_type) + { + /* This type was not "smashed". */ + TYPE_CHAIN (mtype) = TYPE_CHAIN (main_type); + TYPE_CHAIN (main_type) = mtype; + } +#endif + + return mtype; +} + /* Given a type TYPE, return a type which has offset OFFSET, via_virtual VIA_VIRTUAL, and via_public VIA_PUBLIC. May need to construct such a type if none exists. */ @@ -375,7 +514,7 @@ lookup_basetype_type (type, offset, via_virtual, via_public) if (offset != 0) { - printf ("type offset non-zero in lookup_basetype_type"); + printf ("Internal error: type offset non-zero in lookup_basetype_type"); offset = 0; } @@ -451,6 +590,38 @@ lookup_function_type (type) TYPE_NFIELDS (ptype) = 0; return ptype; } + +/* Create an array type. Elements will be of type TYPE, and there will + be NUM of them. + + Eventually this should be extended to take two more arguments which + specify the bounds of the array and the type of the index. + It should also be changed to be a "lookup" function, with the + appropriate data structures added to the type field. + Then read array type should call here. */ + +struct type * +create_array_type (element_type, number) + struct type *element_type; + int number; +{ + struct type *result_type = (struct type *) + obstack_alloc (symbol_obstack, sizeof (struct type)); + + bzero (result_type, sizeof (struct type)); + + TYPE_CODE (result_type) = TYPE_CODE_ARRAY; + TYPE_TARGET_TYPE (result_type) = element_type; + TYPE_LENGTH (result_type) = number * TYPE_LENGTH (element_type); + TYPE_NFIELDS (result_type) = 1; + TYPE_FIELDS (result_type) = + (struct field *) obstack_alloc (symbol_obstack, sizeof (struct field)); + TYPE_FIELD_TYPE (result_type, 0) = builtin_type_int; + TYPE_VPTR_FIELDNO (result_type) = -1; + + return result_type; +} + /* Smash TYPE to be a type of pointers to TO_TYPE. If TO_TYPE is not permanent and has no pointer-type yet, @@ -460,6 +631,8 @@ void smash_to_pointer_type (type, to_type) struct type *type, *to_type; { + int type_permanent = (TYPE_FLAGS (type) & TYPE_FLAG_PERM); + bzero (type, sizeof (struct type)); TYPE_TARGET_TYPE (type) = to_type; /* We assume the machine has only one representation for pointers! */ @@ -468,8 +641,12 @@ smash_to_pointer_type (type, to_type) TYPE_MAIN_VARIANT (type) = type; + if (type_permanent) + TYPE_FLAGS (type) |= TYPE_FLAG_PERM; + if (TYPE_POINTER_TYPE (to_type) == 0 - && !(TYPE_FLAGS (type) & TYPE_FLAG_PERM)) + && (!(TYPE_FLAGS (to_type) & TYPE_FLAG_PERM) + || type_permanent)) { TYPE_POINTER_TYPE (to_type) = type; } @@ -492,6 +669,24 @@ smash_to_member_type (type, domain, to_type) TYPE_MAIN_VARIANT (type) = lookup_member_type (domain, to_type); } +/* Smash TYPE to be a type of method of DOMAIN with type TO_TYPE. */ + +void +smash_to_method_type (type, domain, to_type, args) + struct type *type, *domain, *to_type, **args; +{ + bzero (type, sizeof (struct type)); + TYPE_TARGET_TYPE (type) = to_type; + TYPE_DOMAIN_TYPE (type) = domain; + TYPE_ARG_TYPES (type) = args; + + /* In practice, this is never needed. */ + TYPE_LENGTH (type) = 1; + TYPE_CODE (type) = TYPE_CODE_METHOD; + + TYPE_MAIN_VARIANT (type) = lookup_method_type (domain, to_type, args); +} + /* Smash TYPE to be a type of reference to TO_TYPE. If TO_TYPE is not permanent and has no pointer-type yet, record TYPE as its pointer-type. */ @@ -500,6 +695,8 @@ void smash_to_reference_type (type, to_type) struct type *type, *to_type; { + int type_permanent = (TYPE_FLAGS (type) & TYPE_FLAG_PERM); + bzero (type, sizeof (struct type)); TYPE_TARGET_TYPE (type) = to_type; /* We assume the machine has only one representation for pointers! */ @@ -508,8 +705,12 @@ smash_to_reference_type (type, to_type) TYPE_MAIN_VARIANT (type) = type; + if (type_permanent) + TYPE_FLAGS (type) |= TYPE_FLAG_PERM; + if (TYPE_REFERENCE_TYPE (to_type) == 0 - && !(TYPE_FLAGS (type) & TYPE_FLAG_PERM)) + && (!(TYPE_FLAGS (to_type) & TYPE_FLAG_PERM) + || type_permanent)) { TYPE_REFERENCE_TYPE (to_type) = type; } @@ -523,18 +724,75 @@ void smash_to_function_type (type, to_type) struct type *type, *to_type; { + int type_permanent = (TYPE_FLAGS (type) & TYPE_FLAG_PERM); + bzero (type, sizeof (struct type)); TYPE_TARGET_TYPE (type) = to_type; TYPE_LENGTH (type) = 1; TYPE_CODE (type) = TYPE_CODE_FUNC; TYPE_NFIELDS (type) = 0; + if (type_permanent) + TYPE_FLAGS (type) |= TYPE_FLAG_PERM; + if (TYPE_FUNCTION_TYPE (to_type) == 0 - && !(TYPE_FLAGS (type) & TYPE_FLAG_PERM)) + && (!(TYPE_FLAGS (to_type) & TYPE_FLAG_PERM) + || type_permanent)) { TYPE_FUNCTION_TYPE (to_type) = type; } } + +/* Find which partial symtab on the partial_symtab_list contains + PC. Return 0 if none. */ + +struct partial_symtab * +find_pc_psymtab (pc) + register CORE_ADDR pc; +{ + register struct partial_symtab *ps; + + for (ps = partial_symtab_list; ps; ps = ps->next) + if (pc >= ps->textlow && pc < ps->texthigh) + return ps; + + return 0; +} + +/* Find which partial symbol within a psymtab contains PC. Return 0 + if none. Check all psymtabs if PSYMTAB is 0. */ +struct partial_symbol * +find_pc_psymbol (psymtab, pc) + struct partial_symtab *psymtab; + CORE_ADDR pc; +{ + struct partial_symbol *best, *p; + int best_pc; + + if (!psymtab) + psymtab = find_pc_psymtab (pc); + if (!psymtab) + return 0; + + best_pc = psymtab->textlow - 1; + + for (p = static_psymbols.list + psymtab->statics_offset; + (p - (static_psymbols.list + psymtab->statics_offset) + < psymtab->n_static_syms); + p++) + if (SYMBOL_NAMESPACE (p) == VAR_NAMESPACE + && SYMBOL_CLASS (p) == LOC_BLOCK + && pc >= SYMBOL_VALUE (p) + && SYMBOL_VALUE (p) > best_pc) + { + best_pc = SYMBOL_VALUE (p); + best = p; + } + if (best_pc == psymtab->textlow - 1) + return 0; + return best; +} + static struct symbol *lookup_block_symbol (); @@ -602,8 +860,43 @@ lookup_symbol (name, block, namespace, is_a_field_of_this) } } + /* Check for the possibility of the symbol being a global function + that is stored on the misc function vector. Eventually, all + global symbols might be resolved in this way. */ + + if (namespace == VAR_NAMESPACE) + { + int index = lookup_misc_func (name); + + if (index != -1) + { + ps = find_pc_psymtab (misc_function_vector[index].address); + if (ps && !ps->readin) + { + s = psymtab_to_symtab (ps); + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, 0); + sym = lookup_block_symbol (block, name, namespace); + /* sym == 0 if symbol was found in the psymtab but not + in the symtab. + Return 0 to use the misc_function definition of "foo_". + + This happens for Fortran "foo_" symbols, + which are "foo" in the symtab. + + This can also happen if "asm" is used to make a + regular symbol but not a debugging symbol, e.g. + asm(".globl _main"); + asm("_main:"); + */ + + return sym; + } + } + } + for (ps = partial_symtab_list; ps; ps = ps->next) - if (lookup_partial_symbol (ps, name, 1, namespace)) + if (!ps->readin && lookup_partial_symbol (ps, name, 1, namespace)) { s = psymtab_to_symtab(ps); bv = BLOCKVECTOR (s); @@ -631,7 +924,7 @@ lookup_symbol (name, block, namespace, is_a_field_of_this) } for (ps = partial_symtab_list; ps; ps = ps->next) - if (lookup_partial_symbol (ps, name, 0, namespace)) + if (!ps->readin && lookup_partial_symbol (ps, name, 0, namespace)) { s = psymtab_to_symtab(ps); bv = BLOCKVECTOR (s); @@ -659,8 +952,8 @@ lookup_partial_symbol (pst, name, global, namespace) int length = (global ? pst->n_global_syms : pst->n_static_syms); start = (global ? - global_psymbols + pst->globals_offset : - static_psymbols + pst->statics_offset ); + global_psymbols.list + pst->globals_offset : + static_psymbols.list + pst->statics_offset ); if (!length) return (struct partial_symbol *) 0; @@ -790,8 +1083,9 @@ lookup_block_symbol (block, name, namespace) && !strcmp (SYMBOL_NAME (sym), name) && SYMBOL_NAMESPACE (sym) == namespace) { - if (SYMBOL_CLASS (sym) == LOC_ARG || - SYMBOL_CLASS (sym) == LOC_REGPARM) + if (SYMBOL_CLASS (sym) == LOC_ARG + || SYMBOL_CLASS (sym) == LOC_REF_ARG + || SYMBOL_CLASS (sym) == LOC_REGPARM) parameter_sym = sym; else return sym; @@ -816,7 +1110,7 @@ block_function (bl) /* Subroutine of find_pc_line */ -static struct symtab * +struct symtab * find_pc_symtab (pc) register CORE_ADDR pc; { @@ -837,12 +1131,14 @@ find_pc_symtab (pc) } if (!s) - for (ps = partial_symtab_list; ps; ps = ps->next) - if (pc >= ps->textlow && pc < ps->texthigh) - { - s = psymtab_to_symtab (ps); - break; - } + { + ps = find_pc_psymtab (pc); + if (ps && ps->readin) + fatal ("Internal error: pc in read in psymtab, but not in symtab."); + + if (ps) + s = psymtab_to_symtab (ps); + } return s; } @@ -1176,7 +1472,8 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line) { (*argptr)++; pc = parse_and_eval_address_1 (argptr); - values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line)); + values.sals = (struct symtab_and_line *) + malloc (sizeof (struct symtab_and_line)); values.nelts = 1; values.sals[0] = find_pc_line (pc, 0); values.sals[0].pc = pc; @@ -1250,29 +1547,51 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line) else while (t) { class_name = TYPE_NAME (t); - while (*class_name++ != ' '); - - sym_class = lookup_symbol (class_name, 0, STRUCT_NAMESPACE, 0); - for (method_counter = TYPE_NFN_FIELDS (SYMBOL_TYPE (sym_class)) - 1; - method_counter >= 0; - --method_counter) + /* Ignore this class if it doesn't have a name. + This prevents core dumps, but is just a workaround + because we might not find the function in + certain cases, such as + struct D {virtual int f();} + struct C : D {virtual int g();} + (in this case g++ 1.35.1- does not put out a name + for D as such, it defines type 19 (for example) in + the same stab as C, and then does a + .stabs "D:T19" and a .stabs "D:t19". + Thus + "break C::f" should not be looking for field f in + the class named D, + but just for the field f in the baseclasses of C + (no matter what their names). + + However, I don't know how to replace the code below + that depends on knowing the name of D. */ + if (class_name) { - int field_counter; - struct fn_field *f = - TYPE_FN_FIELDLIST1 (SYMBOL_TYPE (sym_class), method_counter); - - method_name = TYPE_FN_FIELDLIST_NAME (SYMBOL_TYPE (sym_class), method_counter); - if (!strcmp (copy, method_name)) - for (field_counter = TYPE_FN_FIELDLIST_LENGTH (SYMBOL_TYPE (sym_class), method_counter) - 1; - field_counter >= 0; - --field_counter) - { - phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter); - physnames[i1] = (char*) alloca (strlen (phys_name) + 1); - strcpy (physnames[i1], phys_name); - sym_arr[i1] = lookup_symbol (phys_name, SYMBOL_BLOCK_VALUE (sym_class), VAR_NAMESPACE, 0); - if (sym_arr[i1]) i1++; - } + while (*class_name++ != ' '); + + sym_class = lookup_symbol (class_name, 0, STRUCT_NAMESPACE, 0); + for (method_counter = TYPE_NFN_FIELDS (SYMBOL_TYPE (sym_class)) - 1; + method_counter >= 0; + --method_counter) + { + int field_counter; + struct fn_field *f = + TYPE_FN_FIELDLIST1 (SYMBOL_TYPE (sym_class), method_counter); + + method_name = TYPE_FN_FIELDLIST_NAME (SYMBOL_TYPE (sym_class), method_counter); + if (!strcmp (copy, method_name)) + /* Find all the fields with that name. */ + for (field_counter = TYPE_FN_FIELDLIST_LENGTH (SYMBOL_TYPE (sym_class), method_counter) - 1; + field_counter >= 0; + --field_counter) + { + phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter); + physnames[i1] = (char*) alloca (strlen (phys_name) + 1); + strcpy (physnames[i1], phys_name); + sym_arr[i1] = lookup_symbol (phys_name, SYMBOL_BLOCK_VALUE (sym_class), VAR_NAMESPACE, 0); + if (sym_arr[i1]) i1++; + } + } } if (TYPE_N_BASECLASSES (t)) t = TYPE_BASECLASS(t, 1); @@ -1282,6 +1601,7 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line) if (i1 == 1) { + /* There is exactly one field with that name. */ sym = sym_arr[0]; if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK) @@ -1303,6 +1623,8 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line) } if (i1 > 0) { + /* There is more than one field with that name + (overloaded). Ask the user which one to use. */ return decode_line_2 (argptr, sym_arr, physnames, i1, funfirstline); } @@ -1361,7 +1683,7 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line) { if (symtab_list == 0 && partial_symtab_list == 0) error ("No symbol table is loaded. Use the \"symbol-file\" command."); - select_source_symtab (symtab_list); + select_source_symtab (0); default_symtab = current_source_symtab; default_line = current_source_line; } @@ -1424,7 +1746,7 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line) if (funfirstline) SKIP_PROLOGUE (pc); value = find_pc_line (pc, 0); -#ifdef convex +#ifdef PROLOGUE_FIRSTLINE_OVERLAP /* Convex: no need to suppress code on first line, if any */ value.pc = pc; #else @@ -1485,7 +1807,7 @@ decode_line_2 (argptr, sym_arr, physnames, nelts, funfirstline) char *getenv(); struct symtabs_and_lines values, return_values; register CORE_ADDR pc; - char *args, *arg1, *gdb_read_line (); + char *args, *arg1, *command_line_input (); int i; char *prompt; @@ -1518,7 +1840,7 @@ decode_line_2 (argptr, sym_arr, physnames, nelts, funfirstline) printf("%s ",prompt); fflush(stdout); - args = gdb_read_line (0, 0); + args = command_line_input (0, 0); if (args == 0) error_no_arg ("one or more choice numbers"); @@ -1584,10 +1906,8 @@ lookup_misc_func (name) } /* - * Slave routine for sources_info + * Slave routine for sources_info. Force line breaks at ,'s. */ -static int rows_output; - static void output_source_filename (name, next) char *name; @@ -1597,26 +1917,19 @@ int next; if (column != 0 && column + strlen (name) >= 70) { - printf ("\n"); + printf_filtered ("\n"); column = 0; - if (++rows_output >= 21) - { - printf ("--Type Return to print more--"); - fflush (stdout); - gdb_read_line (0, 0); - rows_output = 0; - } } else if (column != 0) { - printf (" "); + printf_filtered (" "); column++; } - printf ("%s", name); + printf_filtered ("%s", name); column += strlen (name); if (next) { - printf (","); + printf_filtered (","); column++; } @@ -1636,17 +1949,18 @@ sources_info () return; } - printf ("Source files for which symbols have been read in:\n\n"); - rows_output = 2; + printf_filtered ("Source files for which symbols have been read in:\n\n"); + for (s = symtab_list; s; s = s->next) output_source_filename (s->filename, s->next); - printf ("\n\n"); + printf_filtered ("\n\n"); - printf ("Source files for which symbols will be read in on demand:\n\n"); - rows_output += 2; + printf_filtered ("Source files for which symbols will be read in on demand:\n\n"); + for (ps = partial_symtab_list; ps; ps = ps->next) - output_source_filename (ps->filename, ps->next); - printf ("\n"); + if (!ps->readin) + output_source_filename (ps->filename, ps->next); + printf_filtered ("\n"); } /* List all symbols (if REGEXP is 0) or all symbols matching REGEXP. @@ -1654,14 +1968,6 @@ sources_info () If CLASS is 1, list only functions. If CLASS is 2, list only type names. */ -#define MORE \ -{ print_count++; \ - if (print_count >= 21) \ - { printf ("--Type Return to print more--"); \ - print_count = 0; \ - fflush (stdout); \ - gdb_read_line (0, 0); } } - static void sort_block_syms (); static void @@ -1687,12 +1993,6 @@ list_symbols (regexp, class) if (val = (char *) re_comp (regexp)) error ("Invalid regexp: %s", val); - printf (regexp - ? "All %ss matching regular expression \"%s\":\n" - : "All defined %ss:\n", - classnames[class], - regexp); - /* Search through the partial_symtab_list *first* for all symbols matching the regexp. That way we don't have to reproduce all of the machinery below. */ @@ -1701,20 +2001,22 @@ list_symbols (regexp, class) struct partial_symbol *bound, *gbound, *sbound; int keep_going = 1; - gbound = global_psymbols + ps->globals_offset + ps->n_global_syms; - sbound = static_psymbols + ps->statics_offset + ps->n_static_syms; + if (ps->readin) continue; + + gbound = global_psymbols.list + ps->globals_offset + ps->n_global_syms; + sbound = static_psymbols.list + ps->statics_offset + ps->n_static_syms; bound = gbound; /* Go through all of the symbols stored in a partial symtab in one loop. */ - psym = global_psymbols + ps->globals_offset; + psym = global_psymbols.list + ps->globals_offset; while (keep_going) { if (psym >= bound) { if (bound == gbound && ps->n_static_syms != 0) { - psym = static_psymbols + ps->statics_offset; + psym = static_psymbols.list + ps->statics_offset; bound = sbound; } else @@ -1741,6 +2043,30 @@ list_symbols (regexp, class) } } + /* Printout here so as to get after the "Reading in symbols" + messages which will be generated above. */ + printf_filtered (regexp + ? "All %ss matching regular expression \"%s\":\n" + : "All defined %ss:\n", + classnames[class], + regexp); + + /* Here, *if* the class is correct (function only, right now), we + should search through the misc function vector for symbols that + match and call find_pc_psymtab on them. If find_pc_psymtab returns + 0, don't worry about it (already read in or no debugging info). */ + + if (class == 1) + { + for (i = 0; i < misc_function_count; i++) + if (regexp == 0 || re_exec (misc_function_vector[i].name)) + { + ps = find_pc_psymtab (misc_function_vector[i].address); + if (ps && !ps->readin) + psymtab_to_symtab (ps); + } + } + for (s = symtab_list; s; s = s->next) { found_in_file = 0; @@ -1770,29 +2096,15 @@ list_symbols (regexp, class) { if (!found_in_file) { - printf ("\nFile %s:\n", s->filename); + printf_filtered ("\nFile %s:\n", s->filename); print_count += 2; } found_in_file = 1; -#if 0 - MORE; -#else - { - print_count++; - if (print_count >= 21) - { - printf ("--Type Return to print more--"); - print_count = 0; - fflush (stdout); - gdb_read_line (0, 0); - } - } -#endif if (class != 2 && i == 1) - printf ("static "); + printf_filtered ("static "); if (class == 2 && SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE) - printf ("typedef "); + printf_filtered ("typedef "); if (class < 3) { @@ -1800,7 +2112,15 @@ list_symbols (regexp, class) (SYMBOL_CLASS (sym) == LOC_TYPEDEF ? "" : SYMBOL_NAME (sym)), stdout, 0); - printf (";\n"); + + if (class == 2 + && SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE + && (TYPE_NAME ((SYMBOL_TYPE (sym))) == 0 + || 0 != strcmp (TYPE_NAME ((SYMBOL_TYPE (sym))), + SYMBOL_NAME (sym)))) + printf_filtered (" %s", SYMBOL_NAME (sym)); + + printf_filtered (";\n"); } else { @@ -1812,12 +2132,6 @@ list_symbols (regexp, class) type_print_method_args (TYPE_FN_FIELD_ARGS (t, i), buf, name, stdout); # endif } - if (class == 2 - && SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE - && (TYPE_NAME ((SYMBOL_TYPE (sym))) == 0 - || 0 != strcmp (TYPE_NAME ((SYMBOL_TYPE (sym))), - SYMBOL_NAME (sym)))) - printf (" %s", SYMBOL_NAME (sym)); } } } @@ -1915,6 +2229,155 @@ contained_in (a, b) return a->startaddr >= b->startaddr && a->endaddr <= b->endaddr; } + +/* Helper routine for make_symbol_completion_list. */ + +int return_val_size, return_val_index; +char **return_val; + +void +completion_list_add_symbol (symname) + char *symname; +{ + if (return_val_index + 3 > return_val_size) + return_val = + (char **)xrealloc (return_val, + (return_val_size *= 2) * sizeof (char *)); + + return_val[return_val_index] = + (char *)xmalloc (1 + strlen (symname)); + + strcpy (return_val[return_val_index], symname); + + return_val[++return_val_index] = (char *)NULL; +} + +/* Return a NULL terminated array of all symbols (regardless of class) which + begin by matching TEXT. If the answer is no symbols, then the return value + is an array which contains only a NULL pointer. + + Problem: All of the symbols have to be copied because readline + frees them. I'm not going to worry about this; hopefully there + won't be that many. */ + +char ** +make_symbol_completion_list (text) + char *text; +{ + register struct symtab *s; + register struct partial_symtab *ps; + register struct blockvector *bv; + struct blockvector *prev_bv = 0; + register struct block *b, *surrounding_static_block; + extern struct block *get_selected_block (); + register int i, j; + register struct symbol *sym; + struct partial_symbol *psym; + + int text_len = strlen (text); + return_val_size = 100; + return_val_index = 0; + return_val = + (char **)xmalloc ((1 + return_val_size) *sizeof (char *)); + return_val[0] = (char *)NULL; + + /* Look through the partial symtabs for all symbols which begin + by matching TEXT. Add each one that you find to the list. */ + + for (ps = partial_symtab_list; ps; ps = ps->next) + { + /* If the psymtab's been read in we'll get it when we search + through the blockvector. */ + if (ps->readin) continue; + + for (psym = global_psymbols.list + ps->globals_offset; + psym < (global_psymbols.list + ps->globals_offset + + ps->n_global_syms); + psym++) + { + QUIT; /* If interrupted, then quit. */ + if ((strncmp (SYMBOL_NAME (psym), text, text_len) == 0)) + completion_list_add_symbol (SYMBOL_NAME (psym)); + } + + for (psym = static_psymbols.list + ps->statics_offset; + psym < (static_psymbols.list + ps->statics_offset + + ps->n_static_syms); + psym++) + { + QUIT; + if ((strncmp (SYMBOL_NAME (psym), text, text_len) == 0)) + completion_list_add_symbol (SYMBOL_NAME (psym)); + } + } + + /* At this point scan through the misc function vector and add each + symbol you find to the list. Eventually we want to ignore + anything that isn't a text symbol (everything else will be + handled by the psymtab code above). */ + + for (i = 0; i < misc_function_count; i++) + if (!strncmp (text, misc_function_vector[i].name, text_len)) + completion_list_add_symbol (misc_function_vector[i].name); + + /* Search upwards from currently selected frame (so that we can + complete on local vars. */ + for (b = get_selected_block (); b; b = BLOCK_SUPERBLOCK (b)) + { + if (!BLOCK_SUPERBLOCK (b)) + surrounding_static_block = b; /* For elmin of dups */ + + /* Also catch fields of types defined in this places which + match our text string. Only complete on types visible + from current context. */ + for (i = 0; i < BLOCK_NSYMS (b); i++) + { + register struct symbol *sym = BLOCK_SYM (b, i); + + if (!strncmp (SYMBOL_NAME (sym), text, text_len)) + completion_list_add_symbol (SYMBOL_NAME (sym)); + + if (SYMBOL_CLASS (sym) == LOC_TYPEDEF) + { + struct type *t = SYMBOL_TYPE (sym); + enum type_code c = TYPE_CODE (t); + + if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT) + for (j = 0; j < TYPE_NFIELDS (t); j++) + if (TYPE_FIELD_NAME (t, j) && + !strncmp (TYPE_FIELD_NAME (t, j), text, text_len)) + completion_list_add_symbol (TYPE_FIELD_NAME (t, j)); + } + } + } + + /* Go through the symtabs and check the externs and statics for + symbols which match. */ + + for (s = symtab_list; s; s = s->next) + { + struct block *b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 0); + + for (i = 0; i < BLOCK_NSYMS (b); i++) + if (!strncmp (SYMBOL_NAME (BLOCK_SYM (b, i)), text, text_len)) + completion_list_add_symbol (SYMBOL_NAME (BLOCK_SYM (b, i))); + } + + for (s = symtab_list; s; s = s->next) + { + struct block *b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 1); + + /* Don't do this block twice. */ + if (b == surrounding_static_block) continue; + + for (i = 0; i < BLOCK_NSYMS (b); i++) + if (!strncmp (SYMBOL_NAME (BLOCK_SYM (b, i)), text, text_len)) + completion_list_add_symbol (SYMBOL_NAME (BLOCK_SYM (b, i))); + } + + return (return_val); +} + void _initialize_symtab () { @@ -1935,7 +2398,7 @@ are listed."); obstack_init (symbol_obstack); obstack_init (psymbol_obstack); - builtin_type_void = init_type (TYPE_CODE_VOID, 0, 0, "void"); + builtin_type_void = init_type (TYPE_CODE_VOID, 1, 0, "void"); builtin_type_float = init_type (TYPE_CODE_FLT, sizeof (float), 0, "float"); builtin_type_double = init_type (TYPE_CODE_FLT, sizeof (double), 0, "double"); diff --git a/gdb/symtab.h b/gdb/symtab.h index ef03c20ecd..e56206082a 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -1,22 +1,21 @@ /* Symbol table definitions for GDB. - Copyright (C) 1986 Free Software Foundation, Inc. + Copyright (C) 1986, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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 @@ -41,15 +40,20 @@ extern void free (); /* 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. The type is - used when sorting so that find_pc_misc_function will pick a global name - over a local name for the same address. */ + 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; - unsigned char type; + unsigned char type; /* Really enum misc_function_type. */ }; /* Address and length of the vector recording all misc function names/addresses. */ @@ -200,11 +204,6 @@ int current_source_line; #define SYMBOL_BLOCK_VALUE(symbol) (symbol)->value.block #define SYMBOL_TYPE(symbol) (symbol)->type -/* 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 - /* 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))) @@ -231,6 +230,7 @@ int current_source_line; #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) @@ -263,12 +263,13 @@ int current_source_line; #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) (thistype)[n] +#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 +#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 @@ -287,11 +288,17 @@ 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. */ @@ -311,9 +318,29 @@ 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 diff --git a/gdb/tags b/gdb/tags deleted file mode 100644 index 2b001d2d2f..0000000000 --- a/gdb/tags +++ /dev/null @@ -1,799 +0,0 @@ -ALL_BREAKPOINTS breakpoint.c /^#define ALL_BREAKPOINTS(b) for (b = breakpoint_ch/ -ASSERT malloc.c /^#define ASSERT(p) if (!(p)) botch("p"); else$/ -CHAIN malloc.c /^#define CHAIN(a) \\$/ -CORE_RELOCATE symmisc.c /^#define CORE_RELOCATE(slot) \\$/ -IGNORE_SYMBOL dbxread.c /^#define IGNORE_SYMBOL(type) (type == N_NSYMS)$/ -INFERIOR_AR0 hp9k320-dep.c /^#define INFERIOR_AR0(u) \\$/ -MAX_OF_TYPE dbxread.c /^#define MAX_OF_TYPE(t) ((1 << (sizeof (t) - 1)) - / -MIN_OF_TYPE dbxread.c /^#define MIN_OF_TYPE(t) (-(1 << (sizeof (t) - 1)))$/ -Mmain main.c /^main (argc, argv, envp)$/ -Mregex regex.c /^main (argc, argv)$/ -Mstuff stuff.c /^main (argc, argv)$/ -NEXTBYTE m68k-pinsn.c /^#define NEXTBYTE(p) (p += 2, ((char *)p)[-1])$/ -NEXTDOUBLE m68k-pinsn.c /^#define NEXTDOUBLE(p) \\$/ -NEXTEXTEND m68k-pinsn.c /^#define NEXTEXTEND(p) \\$/ -NEXTLONG m68k-pinsn.c /^#define NEXTLONG(p) \\$/ -NEXTPACKED m68k-pinsn.c /^#define NEXTPACKED(p) \\$/ -NEXTSINGLE m68k-pinsn.c /^#define NEXTSINGLE(p) \\$/ -NEXTWORD m68k-pinsn.c /^#define NEXTWORD(p) \\$/ -N_DATADDR convex-dep.c /^#define N_DATADDR(hdr) hdr.a_text$/ -N_MAGIC core.c /^#define N_MAGIC(exec) ((exec).magic)$/ -N_SET_MAGIC default-dep.c /^#define N_SET_MAGIC(exec, val) ((exec).a_magic = (/ -N_TXTADDR convex-dep.c /^#define N_TXTADDR(hdr) 0$/ -OP_C i386-pinsn.c /^OP_C (dummy)$/ -OP_D i386-pinsn.c /^OP_D (dummy)$/ -OP_DIR i386-pinsn.c /^OP_DIR (size)$/ -OP_DSSI i386-pinsn.c /^OP_DSSI (dummy)$/ -OP_E i386-pinsn.c /^OP_E (bytemode)$/ -OP_ESDI i386-pinsn.c /^OP_ESDI (dummy)$/ -OP_G i386-pinsn.c /^OP_G (bytemode)$/ -OP_I i386-pinsn.c /^OP_I (bytemode)$/ -OP_J i386-pinsn.c /^OP_J (bytemode)$/ -OP_OFF i386-pinsn.c /^OP_OFF (bytemode)$/ -OP_ONE i386-pinsn.c /^OP_ONE (dummy)$/ -OP_REG i386-pinsn.c /^OP_REG (code)$/ -OP_SEG i386-pinsn.c /^OP_SEG (dummy)$/ -OP_ST i386-pinsn.c /^OP_ST (ignore)$/ -OP_STi i386-pinsn.c /^OP_STi (ignore)$/ -OP_T i386-pinsn.c /^OP_T (dummy)$/ -OP_indirE i386-pinsn.c /^OP_indirE (bytemode)$/ -OP_rm i386-pinsn.c /^OP_rm (bytemode)$/ -OP_sI i386-pinsn.c /^OP_sI (bytemode)$/ -PATFETCH regex.c /^#define PATFETCH(c) \\$/ -PATFETCH_RAW regex.c /^#define PATFETCH_RAW(c) \\$/ -PATPUSH regex.c /^#define PATPUSH(ch) (*b++ = (char) (ch))$/ -POINTER obstack.c /^POINTER (obstack_base) (obstack)$/ -READ_FILE_HEADERS dbxread.c /^#define READ_FILE_HEADERS(DESC, NAME) \\$/ -READ_STRING_TABLE_SIZE dbxread.c /^#define READ_STRING_TABLE_SIZE(INTO) \\$/ -RELOCATE symmisc.c /^#define RELOCATE(slot) (slot ? (* (char **) &slot / -SET_ELEMENT_P dbxread.c /^#define SET_ELEMENT_P(x) ((x)>=N_SETA&&(x)<=(N_SET/ -SIGN_EXTEND_CHAR regex.c /^#define SIGN_EXTEND_CHAR(x) (x)$/ -SYNTAX regex.c /^#define SYNTAX(c) re_syntax_table[c]$/ -TEXT_RELOCATE symmisc.c /^#define TEXT_RELOCATE(slot) ((slot) += text_reloc/ -TYPE_OF_SET_ELEMENT dbxread.c /^#define TYPE_OF_SET_ELEMENT(x) ((x)-N_SETA+N_ABS)$/ -UNRELOCATE symmisc.c /^#define UNRELOCATE(slot) (slot ? (* (char **) &slo/ -_exit standalone.c /^_exit ()$/ -_flsbuf standalone.c /^_flsbuf ()$/ -_initialize_blockframe blockframe.c /^_initialize_blockframe ()$/ -_initialize_breakpoint breakpoint.c /^_initialize_breakpoint ()$/ -_initialize_coff coffread.c /^_initialize_coff ()$/ -_initialize_command command.c /^_initialize_command ()$/ -_initialize_core core.c /^_initialize_core()$/ -_initialize_dbxread dbxread.c /^_initialize_dbxread ()$/ -_initialize_infcmd infcmd.c /^_initialize_infcmd ()$/ -_initialize_inflow inflow.c /^_initialize_inflow ()$/ -_initialize_infrun infrun.c /^_initialize_infrun ()$/ -_initialize_printcmd printcmd.c /^_initialize_printcmd ()$/ -_initialize_source source.c /^_initialize_source ()$/ -_initialize_stack stack.c /^_initialize_stack ()$/ -_initialize_standalone standalone.c /^_initialize_standalone ()$/ -_initialize_symmisc symmisc.c /^_initialize_symmisc ()$/ -_initialize_symtab symtab.c /^_initialize_symtab ()$/ -_initialize_valprint valprint.c /^_initialize_valprint ()$/ -_initialize_values values.c /^_initialize_values ()$/ -_initialize_xgdb xgdb.c /^_initialize_xgdb ()$/ -_obstack_allocated_p obstack.c /^_obstack_allocated_p (h, obj)$/ -_obstack_begin obstack.c /^_obstack_begin (h, size, alignment, chunkfun, free/ -_obstack_free obstack.c /^_obstack_free (h, obj)$/ -_obstack_newchunk obstack.c /^_obstack_newchunk (h, length)$/ -access standalone.c /^access ()$/ -access_value_history values.c /^access_value_history (num)$/ -add_abbrev_cmd command.c /^add_abbrev_cmd (name, class, fun, doc, list)$/ -add_abbrev_prefix_cmd command.c /^add_abbrev_prefix_cmd (name, class, fun, doc, pref/ -add_alias_cmd command.c /^add_alias_cmd (name, oldname, class, abbrev_flag, / -add_bincl_to_list dbxread.c /^add_bincl_to_list (pst, name, instance)$/ -add_cmd command.c /^add_cmd (name, class, fun, doc, list)$/ -add_com main.c /^add_com (name, class, fun, doc)$/ -add_com_alias main.c /^add_com_alias (name, oldname, class, abbrev_flag)$/ -add_file_command dbxread.c /^add_file_command (arg_string)$/ -add_info main.c /^add_info (name, fun, doc)$/ -add_info_alias main.c /^add_info_alias (name, oldname, abbrev_flag)$/ -add_new_header_file dbxread.c /^add_new_header_file (name, instance)$/ -add_old_header_file dbxread.c /^add_old_header_file (name, instance)$/ -add_prefix_cmd command.c /^add_prefix_cmd (name, class, fun, doc, prefixlist,/ -add_symbol_to_list coffread.c /^add_symbol_to_list (symbol, listhead)$/ -add_this_object_header_file dbxread.c /^add_this_object_header_file (i)$/ -addbutton xgdb.c /^addbutton (parent, name, function, closure)$/ -address_info printcmd.c /^address_info (exp)$/ -allocate_repeat_value values.c /^allocate_repeat_value (type, count)$/ -allocate_value values.c /^allocate_value (type)$/ -ambiguous_line_spec source.c /^ambiguous_line_spec (sals)$/ -append_prefix i386-pinsn.c /^append_prefix ()$/ -args_info stack.c /^args_info ()$/ -attach dep.c /^attach (pid)$/ -attach_command infcmd.c /^attach_command (args, from_tty)$/ -attach_program infrun.c /^attach_program (pid)$/ -backtrace_command stack.c /^backtrace_command (count_exp)$/ -backtrace_limit_info stack.c /^backtrace_limit_info (arg, from_tty)$/ -bcmp regex.c /^#define bcmp(s1,s2,n) memcmp((s1),(s2),(n))$/ -bcmp_translate regex.c /^bcmp_translate (s1, s2, len, translate)$/ -bcopy regex.c /^#define bcopy(s,d,n) memcpy((d),(s),(n))$/ -binop_user_defined_p valarith.c /^binop_user_defined_p (op, arg1, arg2)$/ -bit_extract ns32k-pinsn.c /^bit_extract (buffer, offset, count)$/ -block_depth symmisc.c /^block_depth (block)$/ -block_for_pc blockframe.c /^block_for_pc (pc)$/ -block_function symtab.c /^block_function (bl)$/ -block_innermost_frame blockframe.c /^block_innermost_frame (block)$/ -break_command breakpoint.c /^break_command (arg, from_tty)$/ -break_command_1 breakpoint.c /^break_command_1 (arg, tempflag, from_tty)$/ -breakpoint_1 breakpoint.c /^breakpoint_1 (bnum)$/ -breakpoint_auto_delete breakpoint.c /^breakpoint_auto_delete (bnum)$/ -breakpoint_button xgdb.c /^breakpoint_button(w, runflag, call_data)$/ -breakpoint_cond_eval breakpoint.c /^breakpoint_cond_eval (exp)$/ -breakpoint_here_p breakpoint.c /^breakpoint_here_p (pc)$/ -breakpoint_stop_status breakpoint.c /^breakpoint_stop_status (pc, frame_address)$/ -breakpoints_info breakpoint.c /^breakpoints_info (bnum_exp)$/ -bzero regex.c /^#define bzero(s,n) memset((s),0,(n))$/ -call_function valops.c /^call_function (function, nargs, args)$/ -call_ptrace convex-dep.c /^call_ptrace (request, pid, arg3, arg4)$/ -catch_errors main.c /^catch_errors (func, arg, errstring)$/ -cd_command main.c /^cd_command (dir, from_tty)$/ -chdir standalone.c /^chdir ()$/ -check_duplicates breakpoint.c /^check_duplicates (address)$/ -check_field valops.c /^check_field (arg1, name)$/ -ckprefix i386-pinsn.c /^ckprefix ()$/ -clear_breakpoint_commands breakpoint.c /^clear_breakpoint_commands ()$/ -clear_breakpoints breakpoint.c /^clear_breakpoints ()$/ -clear_command breakpoint.c /^clear_command (arg, from_tty)$/ -clear_displays printcmd.c /^clear_displays ()$/ -clear_internalvars values.c /^clear_internalvars ()$/ -clear_momentary_breakpoints breakpoint.c /^clear_momentary_breakpoints ()$/ -clear_proceed_status infrun.c /^clear_proceed_status ()$/ -clear_value_history values.c /^clear_value_history ()$/ -close standalone.c /^close (desc)$/ -close_exec_file core.c /^close_exec_file ()$/ -codestream_fill i386-dep.c /^codestream_fill (peek_flag)$/ -codestream_get i386-dep.c /^#define codestream_get() (codestream_cnt-- == 0 ? / -codestream_peek i386-dep.c /^#define codestream_peek() (codestream_cnt == 0 ? \\/ -codestream_read i386-dep.c /^codestream_read (buf, count)$/ -codestream_seek i386-dep.c /^codestream_seek (place)$/ -codestream_tell i386-dep.c /^#define codestream_tell() (codestream_addr + codes/ -coff_alloc_type coffread.c /^coff_alloc_type (index)$/ -coff_lookup_type coffread.c /^coff_lookup_type (index)$/ -command_loop main.c /^command_loop ()$/ -commands_command breakpoint.c /^commands_command (arg)$/ -compare_misc_functions coffread.c /^compare_misc_functions (fn1, fn2)$/ -compare_psymbols dbxread.c /^compare_psymbols (s1, s2)$/ -compare_symbols coffread.c /^compare_symbols (s1, s2)$/ -complete_symtab coffread.c /^complete_symtab (name, start_addr, size)$/ -concat utils.c /^concat (s1, s2, s3)$/ -condense_addl_misc_bunches dbxread.c /^condense_addl_misc_bunches ()$/ -condense_misc_bunches coffread.c /^condense_misc_bunches ()$/ -condition_command breakpoint.c /^condition_command (arg, from_tty)$/ -cont_command infcmd.c /^cont_command (proc_count_exp, from_tty)$/ -contained_in symtab.c /^contained_in (a, b)$/ -convenience_info values.c /^convenience_info ()$/ -convert_from_68881 m68k-pinsn.c /^convert_from_68881 (from, to)$/ -convert_to_68881 m68k-pinsn.c /^convert_to_68881 (from, to)$/ -copy_name expread.tab.c /^copy_name (token)$/ -copying_info main.c /^copying_info ()$/ -core_file_command convex-dep.c /^core_file_command (filename, from_tty)$/ -create_buttons xgdb.c /^create_buttons (parent)$/ -create_inferior inflow.c /^create_inferior (allargs, env)$/ -create_label xgdb.c /^create_label (name, label)$/ -create_new_frame blockframe.c /^create_new_frame (addr, pc)$/ -create_text_widget xgdb.c /^create_text_widget (parent, filename)$/ -dbit_extract ns32k-pinsn.c /^dbit_extract (buffer, offset, count)$/ -dbx_alloc_type dbxread.c /^dbx_alloc_type (typenums)$/ -dbx_lookup_type dbxread.c /^dbx_lookup_type (typenums)$/ -dcache_alloc remote.c /^dcache_alloc ()$/ -dcache_fetch remote.c /^dcache_fetch (addr)$/ -dcache_flush remote.c /^dcache_flush ()$/ -dcache_hit remote.c /^dcache_hit (addr)$/ -dcache_init remote.c /^dcache_init ()$/ -dcache_poke remote.c /^dcache_poke (addr, data)$/ -dcache_value remote.c /^dcache_value (db, addr)$/ -decode_base_type coffread.c /^decode_base_type (cs, c_type, aux)$/ -decode_format printcmd.c /^decode_format (string_ptr, oformat, osize)$/ -decode_function_type coffread.c /^decode_function_type (cs, c_type, aux)$/ -decode_line_1 symtab.c /^decode_line_1 (argptr, funfirstline, default_symta/ -decode_line_2 symtab.c /^decode_line_2 (argptr, sym_arr, physnames, nelts, / -decode_line_spec symtab.c /^decode_line_spec (string, funfirstline)$/ -decode_line_spec_1 breakpoint.c /^decode_line_spec_1 (string, funfirstline)$/ -decode_type coffread.c /^decode_type (cs, c_type, aux)$/ -define_command main.c /^define_command (comname, from_tty)$/ -define_symbol dbxread.c /^define_symbol (value, string, desc)$/ -delete_breakpoint breakpoint.c /^delete_breakpoint (bpt)$/ -delete_cmd command.c /^delete_cmd (name, list)$/ -delete_command breakpoint.c /^delete_command (arg, from_tty)$/ -delete_current_display printcmd.c /^delete_current_display ()$/ -delete_display printcmd.c /^delete_display (num)$/ -describe_other_breakpoints breakpoint.c /^describe_other_breakpoints (pc)$/ -destructor_name_p valops.c /^destructor_name_p (name, type)$/ -detach dep.c /^detach (signal)$/ -detach_command infcmd.c /^detach_command (args, from_tty)$/ -directories_info source.c /^directories_info ()$/ -directory_command source.c /^directory_command (dirname, from_tty)$/ -disable_breakpoint breakpoint.c /^disable_breakpoint (bpt)$/ -disable_command breakpoint.c /^disable_command (args)$/ -disable_display printcmd.c /^disable_display (args)$/ -discard_cleanups utils.c /^discard_cleanups (old_chain)$/ -discard_misc_bunches coffread.c /^discard_misc_bunches ()$/ -disconnect main.c /^disconnect ()$/ -display_command printcmd.c /^display_command (exp, from_tty)$/ -display_info printcmd.c /^display_info ()$/ -do_breakpoint_commands breakpoint.c /^do_breakpoint_commands ()$/ -do_cleanups utils.c /^do_cleanups (old_chain)$/ -do_command xgdb.c /^do_command(w, command, call_data)$/ -do_displays printcmd.c /^do_displays ()$/ -do_examine printcmd.c /^do_examine (fmt, addr)$/ -do_nothing main.c /^do_nothing ()$/ -do_one_display printcmd.c /^do_one_display (d)$/ -do_restore_insn dep.c /^do_restore_insn (pc)$/ -do_save_insn dep.c /^do_save_insn (size)$/ -document_command main.c /^document_command (comname, from_tty)$/ -dofloat i386-pinsn.c /^dofloat ()$/ -dont_repeat main.c /^dont_repeat ()$/ -double_to_i387 i386-dep.c /^double_to_i387 (from, to)$/ -down_command stack.c /^down_command (count_exp)$/ -dump_me_command main.c /^dump_me_command ()$/ -echo_command main.c /^echo_command (text)$/ -enable_breakpoint breakpoint.c /^enable_breakpoint (bpt)$/ -enable_command breakpoint.c /^enable_command (args)$/ -enable_delete_breakpoint breakpoint.c /^enable_delete_breakpoint (bpt)$/ -enable_delete_command breakpoint.c /^enable_delete_command (args)$/ -enable_display printcmd.c /^enable_display (args)$/ -enable_once_breakpoint breakpoint.c /^enable_once_breakpoint (bpt)$/ -enable_once_command breakpoint.c /^enable_once_command (args)$/ -end_arglist expread.tab.c /^end_arglist ()$/ -end_psymtab dbxread.c /^end_psymtab (pst, include_list, num_includes, capp/ -end_symtab coffread.c /^end_symtab ()$/ -enter_linenos coffread.c /^enter_linenos (file_offset, first_line, last_line)/ -environ_vector environ.c /^environ_vector (e)$/ -environment_info infcmd.c /^environment_info (var)$/ -err stuff.c /^err (msg, a1, a2, a3)$/ -error regex.c /^error (string)$/ -error_no_arg main.c /^error_no_arg (why)$/ -evaluate_expression eval.c /^evaluate_expression (exp)$/ -evaluate_subexp eval.c /^evaluate_subexp (expect_type, exp, pos, noside)$/ -evaluate_subexp_for_address eval.c /^evaluate_subexp_for_address (exp, pos, noside)$/ -evaluate_subexp_for_sizeof eval.c /^evaluate_subexp_for_sizeof (exp, pos)$/ -evaluate_subexp_with_coercion eval.c /^evaluate_subexp_with_coercion (exp, pos, noside)$/ -evaluate_type eval.c /^evaluate_type (exp)$/ -exec_file_command convex-dep.c /^exec_file_command (filename, from_tty)$/ -execle standalone.c /^execle ()$/ -execute_command main.c /^execute_command (p, from_tty)$/ -exit standalone.c /^exit ()$/ -explicit_breakpoint_button xgdb.c /^explicit_breakpoint_button ()$/ -explicit_lookup_type dbxread.c /^explicit_lookup_type (real_filenum, index)$/ -fatal utils.c /^fatal (string, arg)$/ -fault standalone.c /^fault ()$/ -fbit_extract ns32k-pinsn.c /^fbit_extract (buffer, offset, count)$/ -fclose standalone.c /^fclose (desc)$/ -fdopen standalone.c /^fdopen (desc)$/ -fetch_arg m68k-pinsn.c /^fetch_arg (buffer, code, bits)$/ -fetch_inferior_register hp9k320-dep.c /^fetch_inferior_register (regno, regaddr)$/ -fetch_inferior_registers convex-dep.c /^fetch_inferior_registers ()$/ -fflush standalone.c /^fflush (ign)$/ -fgetc standalone.c /^fgetc (desc)$/ -files_info core.c /^files_info ()$/ -fill_in_vptr_fieldno coffread.c /^fill_in_vptr_fieldno (type)$/ -fill_symbuf dbxread.c /^fill_symbuf ()$/ -find_corresponding_bincl_psymtab dbxread.c /^find_corresponding_bincl_psymtab (name, instance)$/ -find_line_common symtab.c /^find_line_common (l, lineno, exact_match)$/ -find_line_pc symtab.c /^find_line_pc (symtab, line)$/ -find_line_pc_range symtab.c /^find_line_pc_range (symtab, thisline, startptr, en/ -find_pc_function blockframe.c /^find_pc_function (pc)$/ -find_pc_line symtab.c /^find_pc_line (pc, notcurrent)$/ -find_pc_line_pc_range symtab.c /^find_pc_line_pc_range (pc, startptr, endptr)$/ -find_pc_misc_function blockframe.c /^find_pc_misc_function (pc)$/ -find_pc_symtab symtab.c /^find_pc_symtab (pc)$/ -find_relative_frame stack.c /^find_relative_frame (frame, level_offset_ptr)$/ -find_saved_register findvar.c /^find_saved_register (frame, regnum)$/ -find_source_lines source.c /^find_source_lines (s, desc)$/ -find_symbol stuff.c /^find_symbol (sym_name, symbol_table, length, strin/ -findarg gld-pinsn.c /^findarg(frame)$/ -findframe gld-pinsn.c /^findframe(thisframe)$/ -finish_block coffread.c /^finish_block (symbol, listhead, old_blocks, start,/ -finish_command infcmd.c /^finish_command (arg, from_tty)$/ -flip_bytes ns32k-pinsn.c /^flip_bytes (ptr, count)$/ -float_info infcmd.c /^float_info (addr_exp)$/ -flush_cached_frames blockframe.c /^flush_cached_frames ()$/ -fopen standalone.c /^fopen (filename, modes)$/ -forward_search_command source.c /^forward_search_command (regex, from_tty)$/ -fprint_addr1 pinsn.c /^fprint_addr1 (stream, name, insn)$/ -fprint_c_ldst pinsn.c /^fprint_c_ldst (stream, insn, op)$/ -fprint_f_ldst pinsn.c /^fprint_f_ldst (stream, insn, op)$/ -fprint_fpop pinsn.c /^fprint_fpop (stream, insn, op, opcode)$/ -fprint_ldst pinsn.c /^fprint_ldst (stream, insn, op)$/ -fprint_mem pinsn.c /^fprint_mem (stream, insn)$/ -fprintf standalone.c /^fprintf (ign, a1, a2, a3, a4, a5, a6, a7, a8, a9)$/ -fputc standalone.c /^fputc (c, ign)$/ -frame_command stack.c /^frame_command (level_exp, from_tty)$/ -frame_info stack.c /^frame_info (addr_exp)$/ -frame_saved_pc dep.c /^frame_saved_pc (frame)$/ -framechain gld-pinsn.c /^framechain(frame)$/ -fread standalone.c /^fread (bufp, numelts, eltsize, stream)$/ -free malloc.c /^free (mem)$/ -free_all_psymtabs symmisc.c /^free_all_psymtabs()$/ -free_all_symtabs symmisc.c /^free_all_symtabs ()$/ -free_all_values values.c /^free_all_values ()$/ -free_bincl_list dbxread.c /^free_bincl_list ()$/ -free_command_lines main.c /^free_command_lines (lptr)$/ -free_current_contents utils.c /^free_current_contents (location)$/ -free_display printcmd.c /^free_display (d)$/ -free_environ environ.c /^free_environ (e)$/ -free_funcalls expread.tab.c /^free_funcalls ()$/ -free_header_files dbxread.c /^free_header_files ()$/ -free_stringtab coffread.c /^free_stringtab ()$/ -free_symtab symmisc.c /^free_symtab (s)$/ -free_symtab_block symmisc.c /^free_symtab_block (b)$/ -fromhex remote.c /^fromhex (a)$/ -fstat standalone.c /^fstat (desc, statbuf)$/ -functions_info symtab.c /^functions_info (regexp)$/ -fwrite standalone.c /^fwrite (buf, numelts, size, stream)$/ -garbage xgdb.c /^garbage (c)$/ -gdb_read_line main.c /^gdb_read_line (prompt, repeat)$/ -get16 i386-pinsn.c /^get16 ()$/ -get32 i386-pinsn.c /^get32 ()$/ -get_breakpoint_commands breakpoint.c /^get_breakpoint_commands ()$/ -get_current_block blockframe.c /^get_current_block ()$/ -get_current_frame blockframe.c /^get_current_frame ()$/ -get_displacement ns32k-pinsn.c /^get_displacement (buffer, aoffsetp)$/ -get_exec_file core.c /^get_exec_file (err)$/ -get_filename_and_charpos source.c /^get_filename_and_charpos (s, line, fullname)$/ -get_frame_block blockframe.c /^get_frame_block (frame)$/ -get_frame_function blockframe.c /^get_frame_function (frame)$/ -get_frame_info blockframe.c /^get_frame_info (frame)$/ -get_frame_pc blockframe.c /^get_frame_pc (frame)$/ -get_frame_saved_regs blockframe.c /^get_frame_saved_regs (frame_info_addr, saved_regs_/ -get_in_environ environ.c /^get_in_environ (e, var)$/ -get_lim_data malloc.c /^get_lim_data ()$/ -get_offset stuff.c /^get_offset (file, sym_name)$/ -get_pc_function_start blockframe.c /^get_pc_function_start (pc)$/ -get_prev_frame blockframe.c /^get_prev_frame (frame)$/ -get_prev_frame_info blockframe.c /^get_prev_frame_info (next_frame)$/ -get_selected_block stack.c /^get_selected_block ()$/ -get_sym_file coffread.c /^get_sym_file ()$/ -getfilename coffread.c /^getfilename (aux_entry)$/ -getpid standalone.c /^getpid ()$/ -getpkt remote.c /^getpkt (buf)$/ -getpool malloc.c /^getpool ()$/ -getrlimit standalone.c /^getrlimit (addr)$/ -getsymname coffread.c /^getsymname (symbol_entry)$/ -getwd standalone.c /^getwd (buf)$/ -handle_command infrun.c /^handle_command (args, from_tty)$/ -hash_symsegs dbxread.c /^hash_symsegs ()$/ -hashname coffread.c /^hashname (name)$/ -have_core_file_p core.c /^have_core_file_p ()$/ -have_inferior_p infcmd.c /^have_inferior_p ()$/ -help_cmd command.c /^help_cmd (command, stream)$/ -help_cmd_list command.c /^help_cmd_list (list, class, prefix, recurse, strea/ -help_command main.c /^help_command (command, from_tty)$/ -help_list command.c /^help_list (list, cmdtype, class, stream)$/ -history_info values.c /^history_info (num_exp)$/ -i386_float_info i386-dep.c /^i386_float_info ()$/ -i386_follow_jump i386-dep.c /^i386_follow_jump ()$/ -i386_frame_find_saved_regs i386-dep.c /^i386_frame_find_saved_regs (fip, fsrp)$/ -i386_get_frame_setup i386-dep.c /^i386_get_frame_setup (pc)$/ -i386_pop_frame i386-dep.c /^i386_pop_frame ()$/ -i386_push_dummy_frame i386-dep.c /^i386_push_dummy_frame ()$/ -i386_register_u_addr i386-dep.c /^i386_register_u_addr (blockend, regnum)$/ -i386_skip_prologue i386-dep.c /^i386_skip_prologue (pc)$/ -i386dis i386-pinsn.c /^i386dis (pc, inbuf, outbuf)$/ -i387_to_double i386-dep.c /^i387_to_double (from, to)$/ -identify_source_line source.c /^identify_source_line (s, line, mid_statement)$/ -ignore_command breakpoint.c /^ignore_command (args, from_tty)$/ -index utils.c /^index (s, c)$/ -inferior_died inflow.c /^inferior_died ()$/ -info_command main.c /^info_command ()$/ -init_bincl_list dbxread.c /^init_bincl_list (number)$/ -init_environ environ.c /^init_environ (e)$/ -init_header_files dbxread.c /^init_header_files ()$/ -init_lineno coffread.c /^init_lineno (chan, offset, count)$/ -init_misc_functions coffread.c /^init_misc_functions ()$/ -init_psymbol_list dbxread.c /^init_psymbol_list (total_symbols)$/ -init_source_path source.c /^init_source_path ()$/ -init_stringtab coffread.c /^init_stringtab (chan, offset)$/ -init_syntax_once regex.c /^init_syntax_once ()$/ -init_type symtab.c /^init_type (code, length, uns, name)$/ -initialize_all_files init.c /^void initialize_all_files () {$/ -initialize_cmd_lists main.c /^initialize_cmd_lists ()$/ -initialize_main main.c /^initialize_main ()$/ -input_from_terminal_p main.c /^input_from_terminal_p ()$/ -insert_breakpoints breakpoint.c /^insert_breakpoints ()$/ -insert_jump regex.c /^insert_jump (op, from, to, current_end)$/ -insert_step_breakpoint infrun.c /^insert_step_breakpoint ()$/ -insque utils.c /^insque (item, after)$/ -int obstack.c /^int (obstack_object_size) (obstack)$/ -internalvar_name values.c /^internalvar_name (var)$/ -ioctl standalone.c /^ioctl (desc, code, arg)$/ -is_nan valprint.c /^is_nan (arg)$/ -isabranch dep.c /^isabranch (addr, target)$/ -jump_command infcmd.c /^jump_command (arg, from_tty)$/ -kill standalone.c /^kill ()$/ -kill_command inflow.c /^kill_command ()$/ -kill_inferior convex-dep.c /^kill_inferior ()$/ -kill_inferior_fast convex-dep.c /^kill_inferior_fast ()$/ -length_of_subexp expread.tab.c /^length_of_subexp (expr, endpos)$/ -line_info source.c /^line_info (arg, from_tty)$/ -list_command source.c /^list_command (arg, from_tty)$/ -list_symbols symtab.c /^list_symbols (regexp, class)$/ -locals_info stack.c /^locals_info ()$/ -locate_var_value findvar.c /^locate_var_value (var, frame)$/ -lookup_basetype_type symtab.c /^lookup_basetype_type (type, offset, via_virtual, v/ -lookup_block_symbol symtab.c /^lookup_block_symbol (block, name, namespace)$/ -lookup_cmd command.c /^lookup_cmd (line, list, cmdtype, allow_unknown)$/ -lookup_enum symtab.c /^lookup_enum (name, block)$/ -lookup_function_type symtab.c /^lookup_function_type (type)$/ -lookup_internalvar values.c /^lookup_internalvar (name)$/ -lookup_member_type symtab.c /^lookup_member_type (type, domain)$/ -lookup_misc_func symtab.c /^lookup_misc_func (name)$/ -lookup_partial_symbol symtab.c /^lookup_partial_symbol (pst, name, global, namespac/ -lookup_partial_symtab symtab.c /^lookup_partial_symtab (name)$/ -lookup_pointer_type symtab.c /^lookup_pointer_type (type)$/ -lookup_reference_type symtab.c /^lookup_reference_type (type)$/ -lookup_struct symtab.c /^lookup_struct (name, block)$/ -lookup_symbol symtab.c /^lookup_symbol (name, block, namespace, is_a_field_/ -lookup_symtab symtab.c /^lookup_symtab (name)$/ -lookup_typename symtab.c /^lookup_typename (name, block, noerr)$/ -lookup_union symtab.c /^lookup_union (name, block)$/ -lookup_unsigned_typename symtab.c /^lookup_unsigned_typename (name)$/ -lseek standalone.c /^lseek (desc, pos)$/ -make_blockvector coffread.c /^make_blockvector ()$/ -make_cleanup utils.c /^make_cleanup (function, arg)$/ -make_environ environ.c /^make_environ ()$/ -malloc malloc.c /^malloc (n) \/* get a block *\/$/ -malloc_init malloc.c /^malloc_init (start, warnfun)$/ -malloc_mem_free malloc.c /^malloc_mem_free ()$/ -malloc_mem_used malloc.c /^malloc_mem_used ()$/ -malloc_stats malloc.c /^malloc_stats (size)$/ -malloc_usable_size malloc.c /^malloc_usable_size (mem)$/ -malloc_warning standalone.c /^malloc_warning (str)$/ -map_breakpoint_numbers breakpoint.c /^map_breakpoint_numbers (args, function)$/ -mark_breakpoints_out breakpoint.c /^mark_breakpoints_out ()$/ -max environ.c /^#define max(a, b) ((a) > (b) ? (a) : (b))$/ -memalign malloc.c /^memalign (alignment, size)$/ -methods_info symtab.c /^methods_info (regexp)$/ -min environ.c /^#define min(a, b) ((a) < (b) ? (a) : (b))$/ -modify_field values.c /^modify_field (addr, fieldval, bitpos, bitsize)$/ -morecore malloc.c /^morecore (nu) \/* ask system for more memory *\/$/ -myread core.c /^myread (desc, addr, len)$/ -new_object_header_files dbxread.c /^new_object_header_files ()$/ -new_tty inflow.c /^new_tty (ttyname)$/ -next_command infcmd.c /^next_command (count_string)$/ -next_symbol_text dbxread.c /^next_symbol_text ()$/ -nexti_command infcmd.c /^nexti_command (count_string)$/ -normal_stop infrun.c /^normal_stop ()$/ -ns32k_get_enter_addr ns32k-pinsn.c /^ns32k_get_enter_addr (pc)$/ -ns32k_localcount ns32k-pinsn.c /^ns32k_localcount (enter_pc)$/ -oappend i386-pinsn.c /^oappend (s)$/ -obconcat dbxread.c /^obconcat (s1, s2, s3)$/ -obsavestring dbxread.c /^obsavestring (ptr, size)$/ -obstack_free obstack.c /^obstack_free (h, obj)$/ -open standalone.c /^open (filename, modes)$/ -openp source.c /^openp (path, try_cwd_first, string, mode, prot, fi/ -output_command printcmd.c /^output_command (exp)$/ -output_source_filename symtab.c /^output_source_filename (name, next)$/ -parse_and_eval eval.c /^parse_and_eval (exp)$/ -parse_and_eval_address eval.c /^parse_and_eval_address (exp)$/ -parse_and_eval_address_1 eval.c /^parse_and_eval_address_1 (expptr)$/ -parse_c_1 expread.tab.c /^parse_c_1 (stringptr, block, comma)$/ -parse_c_expression expread.tab.c /^parse_c_expression (string)$/ -parse_escape utils.c /^parse_escape (string_ptr)$/ -parse_frame_specification stack.c /^parse_frame_specification (frame_exp)$/ -parse_number expread.tab.c /^parse_number (olen)$/ -parse_to_comma_and_eval eval.c /^parse_to_comma_and_eval (expp)$/ -patch_opaque_types coffread.c /^patch_opaque_types ()$/ -patch_type coffread.c /^patch_type (type, real_type)$/ -perror_with_name utils.c /^perror_with_name (string)$/ -pop_subfile dbxread.c /^pop_subfile ()$/ -prefixify_expression expread.tab.c /^prefixify_expression (expr)$/ -prefixify_subexp expread.tab.c /^prefixify_subexp (inexpr, outexpr, inend, outbeg)$/ -print_387_control_word i386-dep.c /^print_387_control_word (control)$/ -print_387_status i386-dep.c /^print_387_status (status, ep)$/ -print_387_status_word i386-dep.c /^print_387_status_word (status)$/ -print_address printcmd.c /^print_address (addr, stream)$/ -print_base m68k-pinsn.c /^print_base (regno, disp, stream)$/ -print_block_frame_locals stack.c /^print_block_frame_locals (b, frame, stream)$/ -print_buf regex.c /^print_buf (bufp)$/ -print_button xgdb.c /^print_button(w, starflag, call_data)$/ -print_command printcmd.c /^print_command (exp)$/ -print_expression expprint.c /^print_expression (exp, stream)$/ -print_formatted printcmd.c /^print_formatted (val, format, size)$/ -print_frame_arg_vars stack.c /^print_frame_arg_vars (frame, stream)$/ -print_frame_args printcmd.c /^print_frame_args (func, fi, num, stream)$/ -print_frame_info stack.c /^print_frame_info (fi, level, source, args)$/ -print_frame_local_vars stack.c /^print_frame_local_vars (frame, stream)$/ -print_frame_nameless_args printcmd.c /^print_frame_nameless_args (argsaddr, start, end, s/ -print_gdb_version main.c /^print_gdb_version ()$/ -print_indexed m68k-pinsn.c /^print_indexed (basereg, p, addr, stream)$/ -print_insn gld-pinsn.c /^print_insn (memaddr, stream)$/ -print_insn_arg m68k-pinsn.c /^print_insn_arg (d, buffer, p, addr, stream)$/ -print_prompt main.c /^print_prompt ()$/ -print_scalar_formatted printcmd.c /^print_scalar_formatted (valaddr, type, format, siz/ -print_sel_frame stack.c /^print_sel_frame (just_source)$/ -print_selected_frame stack.c /^print_selected_frame ()$/ -print_source_lines source.c /^print_source_lines (s, line, stopline, noerror)$/ -print_spaces utils.c /^print_spaces (n, file)$/ -print_stack_frame stack.c /^print_stack_frame (frame, level, source)$/ -print_subexp expprint.c /^print_subexp (exp, pos, stream, prec)$/ -print_symbol symmisc.c /^print_symbol (symbol, depth, outfile)$/ -print_symtabs symmisc.c /^print_symtabs (filename)$/ -print_sys_errmsg utils.c /^print_sys_errmsg (string, errcode)$/ -print_variable_value printcmd.c /^print_variable_value (var, frame, stream)$/ -printchar regex.c /^printchar (c)$/ -printf standalone.c /^printf (a1, a2, a3, a4, a5, a6, a7, a8, a9)$/ -printf_command printcmd.c /^printf_command (arg)$/ -proceed infrun.c /^proceed (addr, signal, step)$/ -process_coff_symbol coffread.c /^process_coff_symbol (cs, aux)$/ -process_one_symbol dbxread.c /^process_one_symbol (type, desc, value, name)$/ -process_symbol_for_psymtab dbxread.c /^process_symbol_for_psymtab (name)$/ -program_info infcmd.c /^program_info ()$/ -psymtab_to_symtab coffread.c /^psymtab_to_symtab ()$/ -ptrace standalone.c /^ptrace ()$/ -ptype_command printcmd.c /^ptype_command (typename)$/ -push_bytes valops.c /^push_bytes (sp, buffer, len)$/ -push_subfile dbxread.c /^push_subfile ()$/ -push_word valops.c /^push_word (sp, buffer)$/ -putop i386-pinsn.c /^putop (template)$/ -putpkt remote.c /^putpkt (buf)$/ -pwd_command main.c /^pwd_command (arg, from_tty)$/ -query utils.c /^query (ctlstr, arg1, arg2)$/ -quit utils.c /^quit ()$/ -quit_command main.c /^quit_command ()$/ -re_comp regex.c /^re_comp (s)$/ -re_compile_fastmap regex.c /^re_compile_fastmap (bufp)$/ -re_compile_pattern regex.c /^re_compile_pattern (pattern, size, bufp)$/ -re_exec regex.c /^re_exec (s)$/ -re_match regex.c /^re_match (pbufp, string, size, pos, regs)$/ -re_match_2 regex.c /^re_match_2 (pbufp, string1, size1, string2, size2,/ -re_search regex.c /^re_search (pbufp, string, size, startpos, range, r/ -re_search_2 regex.c /^re_search_2 (pbufp, string1, size1, string2, size2/ -re_set_syntax regex.c /^re_set_syntax (syntax)$/ -read_addl_syms dbxread.c /^read_addl_syms (desc, stringtab, nlistlen, text_ad/ -read_aout_hdr coffread.c /^read_aout_hdr (chan, aout_hdr, size)$/ -read_args dbxread.c /^read_args (pp, end)$/ -read_array_type dbxread.c /^read_array_type (pp, type)$/ -read_coff_symtab coffread.c /^read_coff_symtab (desc, nsyms)$/ -read_command_lines main.c /^read_command_lines ()$/ -read_dbx_symtab dbxread.c /^read_dbx_symtab (desc, stringtab, nlistlen, inclin/ -read_enum_type coffread.c /^read_enum_type (index, length, lastsym)$/ -read_file_hdr coffread.c /^read_file_hdr (chan, file_hdr)$/ -read_inferior_memory convex-dep.c /^read_inferior_memory (memaddr, myaddr, len)$/ -read_inferior_register standalone.c /^read_inferior_register ()$/ -read_memory core.c /^read_memory (memaddr, myaddr, len)$/ -read_memory_integer infcmd.c /^read_memory_integer (memaddr, len)$/ -read_number dbxread.c /^read_number (pp, end)$/ -read_ofile_symtab dbxread.c /^read_ofile_symtab (desc, stringtab, sym_offset,$/ -read_one_sym coffread.c /^read_one_sym (cs, sym, aux)$/ -read_pc infcmd.c /^read_pc ()$/ -read_range_type dbxread.c /^read_range_type (pp, typenums)$/ -read_register findvar.c /^read_register (regno)$/ -read_register_bytes findvar.c /^read_register_bytes (regbyte, myaddr, len)$/ -read_relative_register_raw_bytes findvar.c /^read_relative_register_raw_bytes (regnum, myaddr)$/ -read_section_hdr coffread.c /^read_section_hdr (chan, section_name, section_hdr,/ -read_struct_type coffread.c /^read_struct_type (index, length, lastsym)$/ -read_symsegs symmisc.c /^read_symsegs (desc, name)$/ -read_type dbxread.c /^read_type (pp)$/ -read_type_number dbxread.c /^read_type_number (pp, typenums)$/ -read_var_value findvar.c /^read_var_value (var, frame)$/ -readchar remote.c /^readchar ()$/ -realloc malloc.c /^realloc (mem, n)$/ -really_free_pendings dbxread.c /^really_free_pendings ()$/ -record_latest_value values.c /^record_latest_value (val)$/ -record_line coffread.c /^record_line (line, pc)$/ -record_misc_function coffread.c /^record_misc_function (name, address)$/ -record_selected_frame stack.c /^record_selected_frame (frameaddrp, levelp)$/ -redisplay_button xgdb.c /^redisplay_button()$/ -register_addr core.c /^register_addr (regno, blockend)$/ -registers_info infcmd.c /^registers_info (addr_exp)$/ -release_value values.c /^release_value (val)$/ -relocate_block symmisc.c /^relocate_block (bp)$/ -relocate_blockvector symmisc.c /^relocate_blockvector (blp)$/ -relocate_source symmisc.c /^relocate_source (sp)$/ -relocate_sourcevector symmisc.c /^relocate_sourcevector (svp)$/ -relocate_symbol symmisc.c /^relocate_symbol (sp)$/ -relocate_symtab symmisc.c /^relocate_symtab (root)$/ -relocate_type symmisc.c /^relocate_type (tp)$/ -relocate_typevector symmisc.c /^relocate_typevector (tv)$/ -remote_fetch_registers remote.c /^remote_fetch_registers (regs)$/ -remote_fetch_word remote.c /^remote_fetch_word (addr)$/ -remote_open remote.c /^remote_open (name, from_tty)$/ -remote_read_bytes remote.c /^remote_read_bytes (memaddr, myaddr, len)$/ -remote_resume remote.c /^remote_resume (step, signal)$/ -remote_send remote.c /^remote_send (buf)$/ -remote_store_registers remote.c /^remote_store_registers (regs)$/ -remote_store_word remote.c /^remote_store_word (addr, word)$/ -remote_wait remote.c /^remote_wait (status)$/ -remote_write_bytes remote.c /^remote_write_bytes (memaddr, myaddr, len)$/ -remove_breakpoints breakpoint.c /^remove_breakpoints ()$/ -remove_step_breakpoint infrun.c /^remove_step_breakpoint ()$/ -remque utils.c /^remque (item)$/ -reopen_exec_file core.c /^reopen_exec_file ()$/ -request_quit utils.c /^request_quit ()$/ -restore_cleanups utils.c /^restore_cleanups (chain)$/ -restore_gdb standalone.c /^restore_gdb ()$/ -restore_inferior_status infrun.c /^restore_inferior_status (inf_status)$/ -resume convex-dep.c /^resume (step, signal)$/ -return_command stack.c /^return_command (retval_exp, from_tty)$/ -return_to_top_level main.c /^return_to_top_level ()$/ -reverse_search_command source.c /^reverse_search_command (regex, from_tty)$/ -rindex utils.c /^rindex (s, c)$/ -run_command infcmd.c /^run_command (args, from_tty)$/ -run_stack_dummy infcmd.c /^run_stack_dummy (addr, buffer)$/ -save_cleanups utils.c /^save_cleanups ()$/ -save_frame_pointer standalone.c /^save_frame_pointer (val)$/ -save_inferior_status infrun.c /^save_inferior_status (inf_status, restore_stack_in/ -save_registers standalone.c /^save_registers (firstreg)$/ -savestring utils.c /^savestring (ptr, size)$/ -sbrk standalone.c /^sbrk (amount)$/ -scan_file_globals dbxread.c /^scan_file_globals (desc, stringtab, offset, numsym/ -select_frame stack.c /^select_frame (frame, level)$/ -select_source_symtab source.c /^select_source_symtab (s)$/ -set_args_command infcmd.c /^set_args_command (args)$/ -set_backtrace_limit_command stack.c /^set_backtrace_limit_command (count_exp, from_tty)$/ -set_breakpoint breakpoint.c /^set_breakpoint (s, line, tempflag)$/ -set_breakpoint_commands breakpoint.c /^set_breakpoint_commands (cmds)$/ -set_command printcmd.c /^set_command (exp)$/ -set_current_frame blockframe.c /^set_current_frame (frame)$/ -set_default_breakpoint breakpoint.c /^set_default_breakpoint (valid, addr, symtab, line)/ -set_environment_command infcmd.c /^set_environment_command (arg)$/ -set_ignore_count breakpoint.c /^set_ignore_count (bptnum, count, from_tty)$/ -set_in_environ environ.c /^set_in_environ (e, var, value)$/ -set_internalvar values.c /^set_internalvar (var, val)$/ -set_internalvar_component values.c /^set_internalvar_component (var, offset, bitpos, bi/ -set_maximum_command valprint.c /^set_maximum_command (arg)$/ -set_momentary_breakpoint breakpoint.c /^set_momentary_breakpoint (sal, frame)$/ -set_next_address printcmd.c /^set_next_address (addr)$/ -set_prompt_command main.c /^set_prompt_command (text)$/ -set_raw_breakpoint breakpoint.c /^set_raw_breakpoint (sal)$/ -set_return_value values.c /^set_return_value (val)$/ -setpgrp standalone.c /^setpgrp ()$/ -setup_arbitrary_frame dep.c /^setup_arbitrary_frame (frame, stack)$/ -shell_escape command.c /^shell_escape (arg, from_tty)$/ -sign_extend ns32k-pinsn.c /^sign_extend (value, bits)$/ -signal standalone.c /^int (* signal ()) ()$/ -signal_command infcmd.c /^signal_command (signum_exp, from_tty)$/ -signals_info infrun.c /^signals_info (signum_exp)$/ -sigsetmask standalone.c /^sigsetmask ()$/ -single_step dep.c /^single_step (signal)$/ -sizeof i386-dep.c /^static unsigned char codestream_buf[sizeof (int)];/ -skip_prologue dep.c /^skip_prologue (pc)$/ -smash_to_function_type symtab.c /^smash_to_function_type (type, to_type)$/ -smash_to_member_type symtab.c /^smash_to_member_type (type, domain, to_type)$/ -smash_to_pointer_type symtab.c /^smash_to_pointer_type (type, to_type)$/ -smash_to_reference_type symtab.c /^smash_to_reference_type (type, to_type)$/ -sort_block_syms symtab.c /^sort_block_syms (b)$/ -sort_syms coffread.c /^sort_syms ()$/ -sort_symtab_syms dbxread.c /^sort_symtab_syms (s)$/ -source_charpos_line source.c /^source_charpos_line (s, chr)$/ -source_cleanup main.c /^source_cleanup (stream)$/ -source_command main.c /^source_command (file)$/ -source_line_charpos source.c /^source_line_charpos (s, line)$/ -sources_info symtab.c /^sources_info ()$/ -specify_exec_file_hook core.c /^specify_exec_file_hook (hook)$/ -start kdb-start.c /^start ()$/ -start_arglist expread.tab.c /^start_arglist ()$/ -start_inferior infrun.c /^start_inferior ()$/ -start_of_data malloc.c /^#define start_of_data() &etext$/ -start_psymtab dbxread.c /^start_psymtab (filename, textlow, ldsymoff, global/ -start_remote infrun.c /^start_remote ()$/ -start_subfile dbxread.c /^start_subfile (name)$/ -start_symtab coffread.c /^start_symtab ()$/ -step_1 infcmd.c /^step_1 (skip_subroutines, single_inst, count_strin/ -step_command infcmd.c /^step_command (count_string)$/ -stepi_command infcmd.c /^stepi_command (count_string)$/ -stop_sig main.c /^stop_sig ()$/ -store_inferior_register hp9k320-dep.c /^store_inferior_register (regno, regaddr)$/ -store_inferior_register_1 hp9k320-dep.c /^store_inferior_register_1 (regno, regaddr, value)$/ -store_inferior_registers convex-dep.c /^store_inferior_registers (regno)$/ -store_jump regex.c /^store_jump (from, opcode, to)$/ -supply_register findvar.c /^supply_register (regno, val)$/ -symbol_file_command coffread.c /^symbol_file_command (name)$/ -sys_sbrk malloc.c /^sys_sbrk (incr)$/ -tbreak_command breakpoint.c /^tbreak_command (arg, from_tty)$/ -term_status_command inflow.c /^term_status_command ()$/ -terminal_inferior inflow.c /^terminal_inferior ()$/ -terminal_init_inferior inflow.c /^terminal_init_inferior ()$/ -terminal_ours inflow.c /^terminal_ours ()$/ -terminal_ours_1 inflow.c /^terminal_ours_1 (output_only)$/ -terminal_ours_for_output inflow.c /^terminal_ours_for_output ()$/ -tohex remote.c /^tohex (nib)$/ -try_writing_regs_command inflow.c /^try_writing_regs_command ()$/ -tty_command infcmd.c /^tty_command (file)$/ -type_print valprint.c /^type_print (type, varstring, stream, show)$/ -type_print_1 valprint.c /^type_print_1 (type, varstring, stream, show, level/ -type_print_base valprint.c /^type_print_base (type, stream, show, level)$/ -type_print_derivation_info valprint.c /^type_print_derivation_info (stream, type)$/ -type_print_method_args valprint.c /^type_print_method_args (args, prefix, varstring, s/ -type_print_varspec_prefix valprint.c /^type_print_varspec_prefix (type, stream, show, pas/ -type_print_varspec_suffix valprint.c /^type_print_varspec_suffix (type, stream, show, pas/ -typecmp valops.c /^int typecmp(t1, t2)$/ -types_info symtab.c /^types_info (regexp)$/ -ulimit standalone.c /^ulimit ()$/ -undisplay_command printcmd.c /^undisplay_command (args)$/ -unop_user_defined_p valarith.c /^int unop_user_defined_p (op, arg1)$/ -unpack_double values.c /^unpack_double (type, valaddr)$/ -unpack_field_as_long values.c /^unpack_field_as_long (type, valaddr, fieldno)$/ -unpack_long values.c /^unpack_long (type, valaddr)$/ -unrecord_misc_function coffread.c /^unrecord_misc_function ()$/ -unset_environment_command infcmd.c /^unset_environment_command (var)$/ -unset_in_environ environ.c /^unset_in_environ (e, var)$/ -until_break_command breakpoint.c /^until_break_command(arg, from_tty)$/ -until_command infcmd.c /^until_command (arg, from_tty)$/ -until_next_command infcmd.c /^until_next_command (arg, from_tty)$/ -up_command stack.c /^up_command (count_exp)$/ -using_struct_return values.c /^using_struct_return (function, funcaddr, value_typ/ -val_print valprint.c /^val_print (type, valaddr, address, stream, format,/ -validate_comname main.c /^validate_comname (comname)$/ -validate_files core.c /^validate_files ()$/ -validate_format printcmd.c /^validate_format (fmt, cmdname)$/ -valloc malloc.c /^valloc (size)$/ -value_add valarith.c /^value_add (arg1, arg2)$/ -value_addr valops.c /^value_addr (arg1)$/ -value_arg_coerce valops.c /^value_arg_coerce (arg)$/ -value_arg_push valops.c /^value_arg_push (sp, arg)$/ -value_as_double values.c /^value_as_double (val)$/ -value_as_long values.c /^value_as_long (val)$/ -value_assign valops.c /^value_assign (toval, fromval)$/ -value_at valops.c /^value_at (type, addr)$/ -value_being_returned values.c /^value_being_returned (valtype, retbuf, struct_retu/ -value_binop valarith.c /^value_binop (arg1, arg2, op)$/ -value_cast valops.c /^value_cast (type, arg2)$/ -value_coerce_array valops.c /^value_coerce_array (arg1)$/ -value_copy values.c /^value_copy (arg)$/ -value_equal valarith.c /^value_equal (arg1, arg2)$/ -value_field values.c /^value_field (arg1, fieldno)$/ -value_fn_field values.c /^value_fn_field (arg1, fieldno, subfieldno)$/ -value_from_double values.c /^value_from_double (type, num)$/ -value_from_long values.c /^value_from_long (type, num)$/ -value_from_register findvar.c /^value_from_register (type, regnum, frame)$/ -value_ind valops.c /^value_ind (arg1)$/ -value_less valarith.c /^value_less (arg1, arg2)$/ -value_lognot valarith.c /^value_lognot (arg1)$/ -value_neg valarith.c /^value_neg (arg1)$/ -value_of_internalvar values.c /^value_of_internalvar (var)$/ -value_of_register findvar.c /^value_of_register (regnum)$/ -value_of_this valops.c /^value_of_this (complain)$/ -value_of_variable valops.c /^value_of_variable (var)$/ -value_print valprint.c /^value_print (val, stream, format)$/ -value_push valops.c /^value_push (sp, arg)$/ -value_repeat valops.c /^value_repeat (arg1, count)$/ -value_static_field values.c /^value_static_field (type, fieldname, fieldno)$/ -value_string valops.c /^value_string (ptr, len)$/ -value_struct_elt valops.c /^value_struct_elt (arg1, args, name, err)$/ -value_struct_elt_for_address valops.c /^value_struct_elt_for_address (domain, intype, name/ -value_sub valarith.c /^value_sub (arg1, arg2)$/ -value_subscript valarith.c /^value_subscript (array, idx)$/ -value_virtual_fn_field values.c /^value_virtual_fn_field (arg1, f, j, type)$/ -value_x_binop valarith.c /^value_x_binop (arg1, arg2, op, otherop)$/ -value_x_unop valarith.c /^value_x_unop (arg1, op)$/ -value_zerop valarith.c /^value_zerop (arg1)$/ -variables_info symtab.c /^variables_info (regexp)$/ -version_info main.c /^version_info ()$/ -vfork standalone.c /^vfork ()$/ -vlimit standalone.c /^vlimit ()$/ -void obstack.c /^void (obstack_grow) (obstack, pointer, length)$/ -wait standalone.c /^wait (w)$/ -wait_for_inferior infrun.c /^wait_for_inferior ()$/ -warranty_info main.c /^warranty_info ()$/ -whatis_command printcmd.c /^whatis_command (exp)$/ -write_exp_elt expread.tab.c /^write_exp_elt (expelt)$/ -write_exp_elt_dblcst expread.tab.c /^write_exp_elt_dblcst (expelt)$/ -write_exp_elt_intern expread.tab.c /^write_exp_elt_intern (expelt)$/ -write_exp_elt_longcst expread.tab.c /^write_exp_elt_longcst (expelt)$/ -write_exp_elt_opcode expread.tab.c /^write_exp_elt_opcode (expelt)$/ -write_exp_elt_sym expread.tab.c /^write_exp_elt_sym (expelt)$/ -write_exp_elt_type expread.tab.c /^write_exp_elt_type (expelt)$/ -write_exp_string expread.tab.c /^write_exp_string (str)$/ -write_inferior_memory convex-dep.c /^write_inferior_memory (memaddr, myaddr, len)$/ -write_inferior_register standalone.c /^write_inferior_register ()$/ -write_memory core.c /^write_memory (memaddr, myaddr, len)$/ -write_pc infcmd.c /^write_pc (val)$/ -write_register findvar.c /^write_register (regno, val)$/ -write_register_bytes findvar.c /^write_register_bytes (regbyte, myaddr, len)$/ -writing_pc infrun.c /^writing_pc (val)$/ -x_command printcmd.c /^x_command (exp, from_tty)$/ -xfer_core_file core.c /^xfer_core_file (memaddr, myaddr, len)$/ -xgdb_create_window xgdb.c /^xgdb_create_window ()$/ -xgdb_dispatch xgdb.c /^xgdb_dispatch (fp)$/ -xgdb_display_exec_file xgdb.c /^xgdb_display_exec_file (filename)$/ -xgdb_display_source xgdb.c /^xgdb_display_source ()$/ -xgdb_window_hook xgdb.c /^xgdb_window_hook (infile, prompt)$/ -xmalloc utils.c /^xmalloc (size)$/ -xrealloc utils.c /^xrealloc (ptr, size)$/ -xxmalloc dbxread.c /^xxmalloc (n)$/ -yyerror expread.tab.c /^yyerror ()$/ -yylex expread.tab.c /^yylex ()$/ -yyparse expread.tab.c /^yyparse() {$/ diff --git a/gdb/umax-dep.c b/gdb/umax-dep.c index 09d6a34097..0f055f7511 100644 --- a/gdb/umax-dep.c +++ b/gdb/umax-dep.c @@ -1,22 +1,21 @@ /* Low level interface to ptrace, for GDB when running under Unix. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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" @@ -310,8 +309,10 @@ write_inferior_memory (memaddr, myaddr, len) #endif #ifndef COFF_FORMAT +#ifndef AOUTHDR #define AOUTHDR struct exec #endif +#endif extern char *sys_siglist[]; @@ -415,6 +416,9 @@ core_file_command (filename, from_tty) 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); @@ -508,6 +512,9 @@ exec_file_command (filename, from_tty) if (filename) { + filename = tilde_expand (filename); + make_cleanup (free, filename); + execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, &execfile); if (execchan < 0) diff --git a/gdb/utils.c b/gdb/utils.c index 2db7359466..8eb3c68e40 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -1,33 +1,39 @@ /* General utility routines for GDB, the GNU debugger. - Copyright (C) 1986 Free Software Foundation, Inc. + Copyright (C) 1986, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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 #include #include #include +#include #include "defs.h" #include "param.h" #ifdef HAVE_TERMIO #include #endif +/* If this definition isn't overridden by the header files, assume + that isatty and fileno exist on this system. */ +#ifndef ISATTY +#define ISATTY(FP) (isatty (fileno (FP))) +#endif + void error (); void fatal (); @@ -214,13 +220,11 @@ print_sys_errmsg (string, errcode) void quit () { - fflush (stdout); #ifdef HAVE_TERMIO ioctl (fileno (stdout), TCFLSH, 1); #else /* not HAVE_TERMIO */ ioctl (fileno (stdout), TIOCFLUSH, 0); #endif /* not HAVE_TERMIO */ - #ifdef TIOCGPGRP error ("Quit"); #else @@ -236,8 +240,8 @@ request_quit () quit_flag = 1; #ifdef USG - /* Restore the signal handler */ - signal(SIGINT, request_quit); + /* Restore the signal handler. */ + signal (SIGINT, request_quit); #endif if (immediate_quit) @@ -253,6 +257,7 @@ error (string, arg1, arg2, arg3) char *string; int arg1, arg2, arg3; { + terminal_ours (); /* Should be ok even if no inf. */ fflush (stdout); fprintf (stderr, string, arg1, arg2, arg3); fprintf (stderr, "\n"); @@ -274,6 +279,23 @@ fatal (string, arg) exit (1); } +/* Print an error message and exit, dumping core. + STRING is a printf-style control string, and ARG is a corresponding + argument. */ +void +fatal_dump_core (string, arg) + char *string; + int arg; +{ + fprintf (stderr, "gdb: "); + fprintf (stderr, string, arg); + fprintf (stderr, "\n"); + signal (SIGQUIT, SIG_DFL); + kill (getpid (), SIGQUIT); + /* We should never get here, but just in case... */ + exit (1); +} + /* Make a copy of the string at PTR with SIZE characters (and add a null character at the end in the copy). Uses malloc to get the space. Returns the address of the copy. */ @@ -436,30 +458,273 @@ printchar (ch, stream, quoter) { register int c = ch; if (c < 040 || c >= 0177) + switch (c) + { + case '\n': + fputs_filtered ("\\n", stream); + break; + case '\b': + fputs_filtered ("\\b", stream); + break; + case '\t': + fputs_filtered ("\\t", stream); + break; + case '\f': + fputs_filtered ("\\f", stream); + break; + case '\r': + fputs_filtered ("\\r", stream); + break; + case '\033': + fputs_filtered ("\\e", stream); + break; + case '\007': + fputs_filtered ("\\a", stream); + break; + default: + fprintf_filtered (stream, "\\%.3o", (unsigned int) c); + break; + } + else { - if (c == '\n') - fprintf (stream, "\\n"); - else if (c == '\b') - fprintf (stream, "\\b"); - else if (c == '\t') - fprintf (stream, "\\t"); - else if (c == '\f') - fprintf (stream, "\\f"); - else if (c == '\r') - fprintf (stream, "\\r"); - else if (c == 033) - fprintf (stream, "\\e"); - else if (c == '\a') - fprintf (stream, "\\a"); - else - fprintf (stream, "\\%03o", c); + if (c == '\\' || c == quoter) + fputs_filtered ("\\", stream); + fprintf_filtered (stream, "%c", c); } +} + +static int lines_per_page, lines_printed, chars_per_line, chars_printed; + +/* Set values of page and line size. */ +static void +set_screensize_command (arg, from_tty) + char *arg; + int from_tty; +{ + char *p = arg; + char *p1; + int tolinesize = lines_per_page; + int tocharsize = chars_per_line; + + if (p == 0) + error_no_arg ("set screensize"); + + while (*p >= '0' && *p <= '9') + p++; + + if (*p && *p != ' ' && *p != '\t') + error ("Non-integral argument given to \"set screensize\"."); + + tolinesize = atoi (arg); + + while (*p == ' ' || *p == '\t') + p++; + + if (*p) + { + p1 = p; + while (*p1 >= '0' && *p1 <= '9') + p1++; + + if (*p1) + error ("Non-integral second argument given to \"set screensize\"."); + + tocharsize = atoi (p); + } + + lines_per_page = tolinesize; + chars_per_line = tocharsize; +} + +static void +prompt_for_continue () +{ + immediate_quit++; + gdb_readline ("---Type to continue---", 0); + chars_printed = lines_printed = 0; + immediate_quit--; +} + +/* Reinitialize filter; ie. tell it to reset to original values. */ + +void +reinitialize_more_filter () +{ + lines_printed = 0; + chars_printed = 0; +} + +static void +screensize_info (arg, from_tty) + char *arg; + int from_tty; +{ + if (arg) + error ("\"info screensize\" does not take any arguments."); + + if (!lines_per_page) + printf ("Output more filtering is disabled.\n"); else { - if (c == '\\' || c == quoter) - fputc ('\\', stream); - fputc (c, stream); + printf ("Output more filtering is enabled with\n"); + printf ("%d lines per page and %d characters per line.\n", + lines_per_page, chars_per_line); + } +} + +/* Like fputs but pause after every screenful. + Unlike fputs, fputs_filtered does not return a value. + It is OK for LINEBUFFER to be NULL, in which case just don't print + anything. + + Note that a longjmp to top level may occur in this routine + (since prompt_for_continue may do so) so this routine should not be + called when cleanups are not in place. */ + +void +fputs_filtered (linebuffer, stream) + char *linebuffer; + FILE *stream; +{ + char *lineptr; + + if (linebuffer == 0) + return; + + /* Don't do any filtering if it is disabled. */ + if (stream != stdout || !ISATTY(stdout) || lines_per_page == 0) + { + fputs (linebuffer, stream); + return; + } + + /* Go through and output each character. Show line extension + when this is necessary; prompt user for new page when this is + necessary. */ + + lineptr = linebuffer; + while (*lineptr) + { + /* Possible new page. */ + if (lines_printed >= lines_per_page - 1) + prompt_for_continue (); + + while (*lineptr && *lineptr != '\n') + { + /* Print a single line. */ + if (*lineptr == '\t') + { + putc ('\t', stream); + /* Shifting right by 3 produces the number of tab stops + we have already passed, and then adding one and + shifting left 3 advances to the next tab stop. */ + chars_printed = ((chars_printed >> 3) + 1) << 3; + lineptr++; + } + else + { + putc (*lineptr, stream); + chars_printed++; + lineptr++; + } + + if (chars_printed >= chars_per_line) + { + chars_printed = 0; + lines_printed++; + /* Possible new page. */ + if (lines_printed >= lines_per_page - 1) + prompt_for_continue (); + } + } + + if (*lineptr == '\n') + { + lines_printed++; + putc ('\n', stream); + lineptr++; + chars_printed = 0; + } + } +} + +/* Print ARG1, ARG2, and ARG3 on stdout using format FORMAT. If this + information is going to put the amount written since the last call + to INIIALIZE_MORE_FILTER or the last page break over the page size, + print out a pause message and do a gdb_readline to get the users + permision to continue. + + Unlike fprintf, this function does not return a value. + + Note that this routine has a restriction that the length of the + final output line must be less than 255 characters *or* it must be + less than twice the size of the format string. This is a very + arbitrary restriction, but it is an internal restriction, so I'll + put it in. This means that the %s format specifier is almost + useless; unless the caller can GUARANTEE that the string is short + enough, fputs_filtered should be used instead. + + Note also that a longjmp to top level may occur in this routine + (since prompt_for_continue may do so) so this routine should not be + called when cleanups are not in place. */ + +void +fprintf_filtered (stream, format, arg1, arg2, arg3, arg4, arg5, arg6) + FILE *stream; + char *format; + int arg1, arg2, arg3, arg4, arg5, arg6; +{ + static char *linebuffer = (char *) 0; + static int line_size; + int format_length = strlen (format); + int numchars; + + /* Allocated linebuffer for the first time. */ + if (!linebuffer) + { + linebuffer = (char *) xmalloc (255); + line_size = 255; + } + + /* Reallocate buffer to a larger size if this is necessary. */ + if (format_length * 2 > line_size) + { + line_size = format_length * 2; + + /* You don't have to copy. */ + free (linebuffer); + linebuffer = (char *) xmalloc (line_size); } + + /* This won't blow up if the restrictions described above are + followed. */ + (void) sprintf (linebuffer, format, arg1, arg2, arg3); + + fputs_filtered (linebuffer, stream); +} + +void +printf_filtered (format, arg1, arg2, arg3, arg4, arg5, arg6) + char *format; + int arg1, arg2, arg3, arg4, arg5, arg6; +{ + fprintf_filtered (stdout, format, arg1, arg2, arg3, arg4, arg5, arg6); +} + +/* Print N spaces. */ +void +print_spaces_filtered (n, stream) + int n; + FILE *stream; +{ + register char *s = (char *) alloca (n + 1); + register char *t = s; + + while (n--) + *t++ = ' '; + *t = '\0'; + + fputs_filtered (s, stream); } @@ -504,6 +769,34 @@ rindex (s, c) return strrchr (s, c); } +#ifndef USG +char *sys_siglist[32] = { + "SIG0", + "SIGHUP", + "SIGINT", + "SIGQUIT", + "SIGILL", + "SIGTRAP", + "SIGIOT", + "SIGEMT", + "SIGFPE", + "SIGKILL", + "SIGBUS", + "SIGSEGV", + "SIGSYS", + "SIGPIPE", + "SIGALRM", + "SIGTERM", + "SIGUSR1", + "SIGUSR2", + "SIGCLD", + "SIGPWR", + "SIGWIND", + "SIGPHONE", + "SIGPOLL", +}; +#endif + /* Queue routines */ struct queue { @@ -528,21 +821,71 @@ struct queue *item; item->forw->back = item->back; item->back->forw = item->forw; } - - -/* - * There is too much variation in Sys V signal numbers and names, so - * we must initialize them at runtime. If C provided a way to initialize - * an array based on subscript and value, this would not be necessary. - */ +#endif /* USG */ + +#ifdef USG +/* There is too much variation in Sys V signal numbers and names, so + we must initialize them at runtime. */ static char undoc[] = "(undocumented)"; char *sys_siglist[NSIG]; +#endif /* USG */ + +extern struct cmd_list_element *setlist; -_initialize_utils() +void +_initialize_utils () { - int i; - + int i; + add_cmd ("screensize", class_support, set_screensize_command, + "Change gdb's notion of the size of the output screen.\n\ +The first argument is the number of lines on a page.\n\ +The second argument (optional) is the number of characters on a line.", + &setlist); + add_info ("screensize", screensize_info, + "Show gdb's current notion of the size of the output screen."); + + /* These defaults will be used if we are unable to get the correct + values from termcap. */ + lines_per_page = 24; + chars_per_line = 80; + /* Initialize the screen height and width from termcap. */ + { + int termtype = getenv ("TERM"); + + /* Positive means success, nonpositive means failure. */ + int status; + + /* 2048 is large enough for all known terminals, according to the + GNU termcap manual. */ + char term_buffer[2048]; + + if (termtype) + { + status = tgetent (term_buffer, termtype); + if (status > 0) + { + int val; + + val = tgetnum ("li"); + if (val >= 0) + lines_per_page = val; + else + /* The number of lines per page is not mentioned + in the terminal description. This probably means + that paging is not useful (e.g. emacs shell window), + so disable paging. */ + lines_per_page = 0; + + val = tgetnum ("co"); + if (val >= 0) + chars_per_line = val; + } + } + } + +#ifdef USG + /* Initialize signal names. */ for (i = 0; i < NSIG; i++) sys_siglist[i] = undoc; @@ -651,6 +994,5 @@ _initialize_utils() #ifdef SIGPOLL sys_siglist[SIGPOLL ] = "SIGPOLL"; #endif -} #endif /* USG */ - +} diff --git a/gdb/valarith.c b/gdb/valarith.c index 772e590699..ac3f0f4168 100644 --- a/gdb/valarith.c +++ b/gdb/valarith.c @@ -1,22 +1,21 @@ /* Perform arithmetic and other operations on values, for GDB. - Copyright (C) 1986 Free Software Foundation, Inc. + Copyright (C) 1986, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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" @@ -26,6 +25,7 @@ anyone else from sharing it farther. Help stamp out software hoarding! value value_x_binop (); +value value_subscripted_rvalue (); value value_add (arg1, arg2) @@ -105,7 +105,58 @@ value value_subscript (array, idx) value array, idx; { - return value_ind (value_add (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 @@ -159,7 +210,8 @@ value_x_binop (arg1, arg2, op, otherop) value * argvec; char *ptr; char tstr[13]; - + int static_memfuncp; + COERCE_ENUM (arg1); COERCE_ENUM (arg2); @@ -219,10 +271,17 @@ value_x_binop (arg1, arg2, op, otherop) default: error ("Invalid binary operation specified."); } - argvec[0] = value_struct_elt (arg1, argvec+1, tstr, "structure"); + argvec[0] = value_struct_elt (arg1, argvec+1, tstr, &static_memfuncp, "structure"); if (argvec[0]) - return call_function (argvec[0], 2, argvec + 1); - else error ("member function %s not found", tstr); + { + 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 @@ -239,7 +298,8 @@ value_x_unop (arg1, 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 @@ -267,10 +327,17 @@ value_x_unop (arg1, op) default: error ("Invalid binary operation specified."); } - argvec[0] = value_struct_elt (arg1, argvec+1, tstr, "structure"); + argvec[0] = value_struct_elt (arg1, argvec+1, tstr, static_memfuncp, "structure"); if (argvec[0]) - return call_function (argvec[0], 1, argvec + 1); - else error ("member function %s not found", tstr); + { + 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. @@ -329,75 +396,154 @@ value_binop (arg1, arg2, op) *(double *) VALUE_CONTENTS (val) = v; } else + /* Integral operations here. */ { - LONGEST v1, v2, v; - v1 = value_as_long (arg1); - v2 = value_as_long (arg2); - - switch (op) + /* 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 (arg1)) >= sizeof (unsigned LONGEST))) { - 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."); + 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; } - - val = allocate_value (BUILTIN_TYPE_LONGEST); - *(LONGEST *) VALUE_CONTENTS (val) = v; } return val; @@ -452,7 +598,7 @@ value_equal (arg1, arg2) 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 value_as_long (arg1) == value_as_long (arg2); + 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)))) @@ -493,7 +639,7 @@ value_less (arg1, arg2) 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 value_as_long (arg1) < value_as_long (arg2); + return (char *) value_as_long (arg1) < (char *) value_as_long (arg2); else error ("Invalid type combination in ordering comparison."); } diff --git a/gdb/valops.c b/gdb/valops.c index 06091c478d..c70219fa37 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -1,22 +1,22 @@ /* Perform non-arithmetic operations on values, for GDB. - Copyright (C) 1986, 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! -*/ + 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" @@ -66,6 +66,21 @@ value_cast (type, arg2) error ("Invalid cast."); } +/* Create a value of type TYPE that is zero, and return it. */ + +value +value_zero (type, lv) + struct type *type; + enum lval_type lv; +{ + register value val = allocate_value (type); + + bzero (VALUE_CONTENTS (val), TYPE_LENGTH (type)); + VALUE_LVAL (val) = lv; + + return val; +} + /* Return the value with a specified type located at specified address. */ value @@ -255,12 +270,20 @@ value_assign (toval, fromval) error ("Left side of = operation is not an lvalue."); } - /* Return a value just like TOVAL except with the contents of FROMVAL. */ + /* Return a value just like TOVAL except with the contents of FROMVAL + (except in the case of the type if TOVAL is an internalvar). */ + + if (VALUE_LVAL (toval) == lval_internalvar + || VALUE_LVAL (toval) == lval_internalvar_component) + { + type = VALUE_TYPE (fromval); + } val = allocate_value (type); bcopy (toval, val, VALUE_CONTENTS (val) - (char *) val); bcopy (VALUE_CONTENTS (fromval), VALUE_CONTENTS (val), TYPE_LENGTH (type)); - + VALUE_TYPE (val) = type; + return val; } @@ -293,7 +316,7 @@ value value_of_variable (var) struct symbol *var; { - return read_var_value (var, (CORE_ADDR) 0); + return read_var_value (var, (FRAME) 0); } /* Given a value which is an array, return a value which is @@ -371,7 +394,7 @@ value_ind (arg1) /* Allow * on an integer so we can cast it to whatever we want. */ if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT) - return value_at (builtin_type_long, + return value_at (BUILTIN_TYPE_LONGEST, (CORE_ADDR) value_as_long (arg1)); else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR) return value_at (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)), @@ -502,6 +525,9 @@ call_function (function, nargs, args) struct inferior_status inf_status; struct cleanup *old_chain; + if (!have_inferior_p ()) + error ("Cannot invoke functions if the inferior is not running."); + save_inferior_status (&inf_status, 1); old_chain = make_cleanup (restore_inferior_status, &inf_status); @@ -524,14 +550,9 @@ call_function (function, nargs, args) /* If it's a member function, just look at the function part of it. */ - if (code == TYPE_CODE_MEMBER) - { - ftype = TYPE_TARGET_TYPE (ftype); - code = TYPE_CODE (ftype); - } /* Determine address to call. */ - if (code == TYPE_CODE_FUNC) + if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD) { funaddr = VALUE_ADDRESS (function); value_type = TYPE_TARGET_TYPE (ftype); @@ -539,8 +560,8 @@ call_function (function, nargs, args) else if (code == TYPE_CODE_PTR) { funaddr = value_as_long (function); - if (TYPE_CODE (TYPE_TARGET_TYPE (ftype)) - == TYPE_CODE_FUNC) + if (TYPE_CODE (TYPE_TARGET_TYPE (ftype)) == TYPE_CODE_FUNC + || TYPE_CODE (TYPE_TARGET_TYPE (ftype)) == TYPE_CODE_METHOD) value_type = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (ftype)); else value_type = builtin_type_int; @@ -571,9 +592,10 @@ call_function (function, nargs, args) FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, value_type); } +#ifndef CANNOT_EXECUTE_STACK write_memory (start_sp, dummy1, sizeof dummy); -#ifdef convex +#else /* Convex Unix prohibits executing in the stack segment. */ /* Hope there is empty room at the top of the text segment. */ { @@ -584,10 +606,11 @@ call_function (function, nargs, args) if (read_memory_integer (start_sp, 1) != 0) error ("text segment full -- no place to put call"); checked = 1; + sp = old_sp; start_sp = text_end - sizeof dummy; write_memory (start_sp, dummy1, sizeof dummy); } -#else /* !convex */ +#endif /* CANNOT_EXECUTE_STACK */ #ifdef STACK_ALIGN /* If stack grows down, we must leave a hole at the top. */ { @@ -600,7 +623,7 @@ call_function (function, nargs, args) len += TYPE_LENGTH (value_type); for (i = nargs - 1; i >= 0; i--) - len += TYPE_LENGTH (VALUE_TYPE (args[i])); + len += TYPE_LENGTH (VALUE_TYPE (value_arg_coerce (args[i]))); #ifdef CALL_DUMMY_STACK_ADJUST len += CALL_DUMMY_STACK_ADJUST; #endif @@ -636,7 +659,6 @@ call_function (function, nargs, args) sp += CALL_DUMMY_STACK_ADJUST; #endif #endif /* CALL_DUMMY_STACK_ADJUST */ -#endif /* !convex */ /* Store the address at which the structure is supposed to be written. Note that this (and the code which reserved the space @@ -748,12 +770,17 @@ value_string (ptr, len) C++: ARGS is a list of argument types to aid in the selection of an appropriate method. Also, handle derived types. + STATIC_MEMFUNCP, if non-NULL, points to a caller-supplied location + where the truthvalue of whether the function that was resolved was + a static member function or not. + ERR is an error message to be printed in case the field is not found. */ value -value_struct_elt (arg1, args, name, err) +value_struct_elt (arg1, args, name, static_memfuncp, err) register value arg1, *args; char *name; + int *static_memfuncp; char *err; { register struct type *t; @@ -784,17 +811,22 @@ value_struct_elt (arg1, args, name, err) baseclass = t; + /* Assume it's not, unless we see that it is. */ + if (static_memfuncp) + *static_memfuncp =0; + if (!args) { - /* if there are no arguments ...do this... */ + /* if there are no arguments ...do this... */ - /* Try as a variable first, because if we succeed, there - is less work to be done. */ + /* Try as a variable first, because if we succeed, there + is less work to be done. */ while (t) { for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--) { - if (!strcmp (TYPE_FIELD_NAME (t, i), name)) + char *t_field_name = TYPE_FIELD_NAME (t, i); + if (t_field_name && !strcmp (t_field_name, name)) { found = 1; break; @@ -837,7 +869,7 @@ value_struct_elt (arg1, args, name, err) } if (found == 0) - error("there is no field named %s", name); + error ("there is no field named %s", name); return 0; } @@ -871,15 +903,15 @@ value_struct_elt (arg1, args, name, err) found = 1; for (j = TYPE_FN_FIELDLIST_LENGTH (t, i) - 1; j >= 0; --j) - { - if (!typecmp (TYPE_FN_FIELD_ARGS (f, j), args)) - { - if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) - return (value)value_virtual_fn_field (arg1, f, j, t); - else - return (value)value_fn_field (arg1, i, j); - } - } + if (!typecmp (TYPE_FN_FIELD_STATIC_P (f, j), + TYPE_FN_FIELD_ARGS (f, j), args)) + { + if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) + return (value)value_virtual_fn_field (arg1, f, j, t); + if (TYPE_FN_FIELD_STATIC_P (f, j) && static_memfuncp) + *static_memfuncp = 1; + return (value)value_fn_field (arg1, i, j); + } } } @@ -903,7 +935,8 @@ value_struct_elt (arg1, args, name, err) { for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--) { - if (!strcmp (TYPE_FIELD_NAME (t, i), name)) + char *t_field_name = TYPE_FIELD_NAME (t, i); + if (t_field_name && !strcmp (t_field_name, name)) { found = 1; break; @@ -991,7 +1024,8 @@ check_field (arg1, name) { for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--) { - if (!strcmp (TYPE_FIELD_NAME (t, i), name)) + char *t_field_name = TYPE_FIELD_NAME (t, i); + if (t_field_name && !strcmp (t_field_name, name)) { return 1; } @@ -1056,7 +1090,8 @@ value_struct_elt_for_address (domain, intype, name) { for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--) { - if (!strcmp (TYPE_FIELD_NAME (t, i), name)) + char *t_field_name = TYPE_FIELD_NAME (t, i); + if (t_field_name && !strcmp (t_field_name, name)) { if (TYPE_FIELD_PACKED (t, i)) error ("pointers to bitfield members not allowed"); @@ -1136,27 +1171,37 @@ value_struct_elt_for_address (domain, intype, name) } /* Compare two argument lists and return the position in which they differ, - or zero if equal. Note that we ignore the first argument, which is - the type of the instance variable. This is because we want to handle - derived classes. This is not entirely correct: we should actually - check to make sure that a requested operation is type secure, - shouldn't we? */ -int typecmp(t1, t2) + or zero if equal. + + STATICP is nonzero if the T1 argument list came from a + static member function. + + For non-static member functions, we ignore the first argument, + which is the type of the instance variable. This is because we want + to handle calls with objects from derived classes. This is not + entirely correct: we should actually check to make sure that a + requested operation is type secure, shouldn't we? */ + +int +typecmp (staticp, t1, t2) + int staticp; struct type *t1[]; value t2[]; { int i; + if (staticp && t1 == 0) + return t2[1] != 0; + if (t1 == 0) + return 1; if (t1[0]->code == TYPE_CODE_VOID) return 0; - if (!t1[1]) return 0; - for (i = 1; t1[i] && t1[i]->code != TYPE_CODE_VOID; i++) + if (t1[!staticp] == 0) return 0; + for (i = !staticp; t1[i] && t1[i]->code != TYPE_CODE_VOID; i++) { if (! t2[i] || t1[i]->code != t2[i]->type->code || t1[i]->target_type != t2[i]->type->target_type) - { - return i+1; - } + return i+1; } if (!t1[i]) return 0; return t2[i] ? i+1 : 0; diff --git a/gdb/valprint.c b/gdb/valprint.c index b55aa87496..8b01964861 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -1,22 +1,21 @@ /* Print values for GNU debugger gdb. - Copyright (C) 1986, 1988 Free Software Foundation, Inc. + Copyright (C) 1986, 1988, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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 #include "defs.h" @@ -38,6 +37,91 @@ static void type_print_method_args (); char **unsigned_type_table; char **signed_type_table; char **float_type_table; + + +/* Print repeat counts if there are more than this + many repetitions of an element in an array. */ +#define REPEAT_COUNT_THRESHOLD 10 + +/* Print the character string STRING, printing at most LENGTH characters. + Printing stops early if the number hits print_max; repeat counts + are printed as appropriate. */ + +void +print_string (stream, string, length) + FILE *stream; + char *string; + unsigned int length; +{ + register unsigned int i; + unsigned int things_printed = 0; + int in_quotes = 0; + int need_comma = 0; + + if (length == 0) + { + fputs_filtered ("\"\"", stdout); + return; + } + + for (i = 0; i < length && things_printed < print_max; ++i) + { + /* Position of the character we are examining + to see whether it is repeated. */ + unsigned int rep1; + /* Number of repititions we have detected so far. */ + unsigned int reps; + + QUIT; + + if (need_comma) + { + fputs_filtered (", ", stream); + need_comma = 0; + } + + rep1 = i + 1; + reps = 1; + while (rep1 < length && string[rep1] == string[i]) + { + ++rep1; + ++reps; + } + + if (reps > REPEAT_COUNT_THRESHOLD) + { + if (in_quotes) + { + fputs_filtered ("\", ", stream); + in_quotes = 0; + } + fputs_filtered ("'", stream); + printchar (string[i], stream, '\''); + fprintf_filtered (stream, "' ", reps); + i = rep1 - 1; + things_printed += REPEAT_COUNT_THRESHOLD; + need_comma = 1; + } + else + { + if (!in_quotes) + { + fputs_filtered ("\"", stream); + in_quotes = 1; + } + printchar (string[i], stream, '"'); + ++things_printed; + } + } + + /* Terminate the quotes if necessary. */ + if (in_quotes) + fputs_filtered ("\"", stream); + + /* Print ellipses if we stopped before printing LENGTH characters. */ + if (i < length) + fputs_filtered ("...", stream); +} /* Print the value VAL in C-ish syntax on stream STREAM. FORMAT is a format-letter, or 0 for print in natural format of data type. @@ -45,12 +129,13 @@ char **float_type_table; the number of string bytes printed. */ int -value_print (val, stream, format) +value_print (val, stream, format, pretty) value val; FILE *stream; char format; + enum val_prettyprint pretty; { - register int i, n, typelen; + register unsigned int i, n, typelen; /* A "repeated" value really contains several values in a row. They are made by the @ operator. @@ -60,35 +145,59 @@ value_print (val, stream, format) { n = VALUE_REPETITIONS (val); typelen = TYPE_LENGTH (VALUE_TYPE (val)); - fputc ('{', stream); + fprintf_filtered (stream, "{"); /* Print arrays of characters using string syntax. */ if (typelen == 1 && TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT && format == 0) - { - fputc ('"', stream); - for (i = 0; i < n && i < print_max; i++) - { - QUIT; - printchar (VALUE_CONTENTS (val)[i], stream, '"'); - } - if (i < n) - fprintf (stream, "..."); - fputc ('"', stream); - } + print_string (stream, VALUE_CONTENTS (val), n); else { - for (i = 0; i < n && i < print_max; i++) + unsigned int things_printed = 0; + + for (i = 0; i < n && things_printed < print_max; i++) { - if (i) - fprintf (stream, ", "); - val_print (VALUE_TYPE (val), VALUE_CONTENTS (val) + typelen * i, - VALUE_ADDRESS (val) + typelen * i, - stream, format, 1); + /* Position of the array element we are examining to see + whether it is repeated. */ + unsigned int rep1; + /* Number of repititions we have detected so far. */ + unsigned int reps; + + if (i != 0) + fprintf_filtered (stream, ", "); + + rep1 = i + 1; + reps = 1; + while (rep1 < n + && !bcmp (VALUE_CONTENTS (val) + typelen * i, + VALUE_CONTENTS (val) + typelen * rep1, typelen)) + { + ++reps; + ++rep1; + } + + if (reps > REPEAT_COUNT_THRESHOLD) + { + val_print (VALUE_TYPE (val), + VALUE_CONTENTS (val) + typelen * i, + VALUE_ADDRESS (val) + typelen * i, + stream, format, 1, 0, pretty); + fprintf (stream, " ", reps); + i = rep1 - 1; + things_printed += REPEAT_COUNT_THRESHOLD; + } + else + { + val_print (VALUE_TYPE (val), + VALUE_CONTENTS (val) + typelen * i, + VALUE_ADDRESS (val) + typelen * i, + stream, format, 1, 0, pretty); + things_printed++; + } } if (i < n) - fprintf (stream, "..."); + fprintf_filtered (stream, "..."); } - fputc ('}', stream); + fprintf_filtered (stream, "}"); return n * typelen; } else @@ -102,15 +211,28 @@ value_print (val, stream, format) if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_REF) { - fprintf (stream, "("); + fprintf_filtered (stream, "("); type_print (VALUE_TYPE (val), "", stream, -1); - fprintf (stream, ") "); + fprintf_filtered (stream, ") "); + + /* If this is a function pointer, try to print what + function it is pointing to by name. */ + if (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (val))) + == TYPE_CODE_FUNC) + { + print_address (((int *) VALUE_CONTENTS (val))[0], stream); + /* Return value is irrelevant except for string pointers. */ + return 0; + } } return val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), - VALUE_ADDRESS (val), stream, format, 1); + VALUE_ADDRESS (val), stream, format, 1, 0, pretty); } } +static int prettyprint; /* Controls prettyprinting of structures. */ +int unionprint; /* Controls printing of nested unions. */ + /* Print data of type TYPE located at VALADDR (within GDB), which came from the inferior at address ADDRESS, onto stdio stream STREAM according to FORMAT @@ -120,64 +242,107 @@ value_print (val, stream, format) sting characters printed. if DEREF_REF is nonzero, then dereference references, - otherwise just print them like pointers. */ + otherwise just print them like pointers. + + The PRETTY parameter controls prettyprinting. */ int -val_print (type, valaddr, address, stream, format, deref_ref) +val_print (type, valaddr, address, stream, format, + deref_ref, recurse, pretty) struct type *type; char *valaddr; CORE_ADDR address; FILE *stream; char format; int deref_ref; + int recurse; + enum val_prettyprint pretty; { - register int i; + register unsigned int i; int len, n_baseclasses; struct type *elttype; int eltlen; LONGEST val; unsigned char c; + if (pretty == Val_pretty_default) + { + pretty = prettyprint ? Val_prettyprint : Val_no_prettyprint; + } + QUIT; + if (TYPE_FLAGS (type) & TYPE_FLAG_STUB) + { + fprintf_filtered (stream, ""); + fflush (stream); + return 0; + } + switch (TYPE_CODE (type)) { case TYPE_CODE_ARRAY: - if (TYPE_LENGTH (type) >= 0) + if (TYPE_LENGTH (type) >= 0 + && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0) { elttype = TYPE_TARGET_TYPE (type); eltlen = TYPE_LENGTH (elttype); len = TYPE_LENGTH (type) / eltlen; - fprintf (stream, "{"); + fprintf_filtered (stream, "{"); /* For an array of chars, print with string syntax. */ if (eltlen == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT && format == 0) - { - fputc ('"', stream); - for (i = 0; i < len && i < print_max; i++) - { - QUIT; - printchar (valaddr[i], stream, '"'); - } - if (i < len) - fprintf (stream, "..."); - fputc ('"', stream); - } + print_string (stream, valaddr, len); else { - for (i = 0; i < len && i < print_max; i++) + unsigned int things_printed = 0; + + for (i = 0; i < len && things_printed < print_max; i++) { - if (i) fprintf (stream, ", "); - val_print (elttype, valaddr + i * eltlen, - 0, stream, format, deref_ref); + /* Position of the array element we are examining to see + whether it is repeated. */ + unsigned int rep1; + /* Number of repititions we have detected so far. */ + unsigned int reps; + + if (i > 0) + fprintf_filtered (stream, ", "); + + rep1 = i + 1; + reps = 1; + while (rep1 < len + && !bcmp (valaddr + i * eltlen, + valaddr + rep1 * eltlen, eltlen)) + { + ++reps; + ++rep1; + } + + if (reps > REPEAT_COUNT_THRESHOLD) + { + val_print (elttype, valaddr + i * eltlen, + 0, stream, format, deref_ref, + recurse + 1, pretty); + fprintf_filtered (stream, " ", reps); + i = rep1 - 1; + things_printed += REPEAT_COUNT_THRESHOLD; + } + else + { + val_print (elttype, valaddr + i * eltlen, + 0, stream, format, deref_ref, + recurse + 1, pretty); + things_printed++; + } } if (i < len) - fprintf (stream, "..."); + fprintf_filtered (stream, "..."); } - fprintf (stream, "}"); + fprintf_filtered (stream, "}"); break; } - /* Array of unspecified length: treat like pointer. */ + /* Array of unspecified length: treat like pointer to first elt. */ + valaddr = (char *) &address; case TYPE_CODE_PTR: if (format) @@ -185,7 +350,7 @@ val_print (type, valaddr, address, stream, format, deref_ref) print_scalar_formatted (valaddr, type, format, 0, stream); break; } - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER) + if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD) { struct type *domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)); struct type *target = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type)); @@ -194,112 +359,115 @@ val_print (type, valaddr, address, stream, format, deref_ref) char *kind = ""; val = unpack_long (builtin_type_int, valaddr); - if (TYPE_CODE (target) == TYPE_CODE_FUNC) + if (val < 128) { - if (val < 128) + len = TYPE_NFN_FIELDS (domain); + for (i = 0; i < len; i++) { - len = TYPE_NFN_FIELDS (domain); - for (i = 0; i < len; i++) - { - f = TYPE_FN_FIELDLIST1 (domain, i); - len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); + f = TYPE_FN_FIELDLIST1 (domain, i); + len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); - for (j = 0; j < len2; j++) - { - QUIT; - if (TYPE_FN_FIELD_VOFFSET (f, j) == val) - { - kind = "virtual"; - goto common; - } - } - } - } - else - { - struct symbol *sym = find_pc_function ((CORE_ADDR) val); - if (sym == 0) - error ("invalid pointer to member function"); - len = TYPE_NFN_FIELDS (domain); - for (i = 0; i < len; i++) + for (j = 0; j < len2; j++) { - f = TYPE_FN_FIELDLIST1 (domain, i); - len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); - - for (j = 0; j < len2; j++) + QUIT; + if (TYPE_FN_FIELD_VOFFSET (f, j) == val) { - QUIT; - if (!strcmp (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j))) - goto common; + kind = "virtual"; + goto common; } } } - common: - if (i < len) - { - fputc ('&', stream); - type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0); - fprintf (stream, kind); - if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' - && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$') - type_print_method_args - (TYPE_FN_FIELD_ARGS (f, j) + 1, "~", - TYPE_FN_FIELDLIST_NAME (domain, i), stream); - else - type_print_method_args - (TYPE_FN_FIELD_ARGS (f, j), "", - TYPE_FN_FIELDLIST_NAME (domain, i), stream); - break; - } } else { - /* VAL is a byte offset into the structure type DOMAIN. - Find the name of the field for that offset and - print it. */ - int extra = 0; - int bits = 0; - len = TYPE_NFIELDS (domain); - val <<= 3; /* @@ Make VAL into bit offset */ + struct symbol *sym = find_pc_function ((CORE_ADDR) val); + if (sym == 0) + error ("invalid pointer to member function"); + len = TYPE_NFN_FIELDS (domain); for (i = 0; i < len; i++) { - int bitpos = TYPE_FIELD_BITPOS (domain, i); - QUIT; - if (val == bitpos) - break; - if (val < bitpos && i > 0) + f = TYPE_FN_FIELDLIST1 (domain, i); + len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); + + for (j = 0; j < len2; j++) { - int ptrsize = (TYPE_LENGTH (builtin_type_char) * TYPE_LENGTH (target)); - /* Somehow pointing into a field. */ - i -= 1; - extra = (val - TYPE_FIELD_BITPOS (domain, i)); - if (extra & 0x3) - bits = 1; - else - extra >>= 3; - break; + QUIT; + if (!strcmp (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j))) + goto common; } } - if (i < len) + } + common: + if (i < len) + { + fprintf_filtered (stream, "&"); + type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0); + fprintf (stream, kind); + if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' + && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$') + type_print_method_args + (TYPE_FN_FIELD_ARGS (f, j) + 1, "~", + TYPE_FN_FIELDLIST_NAME (domain, i), 0, stream); + else + type_print_method_args + (TYPE_FN_FIELD_ARGS (f, j), "", + TYPE_FN_FIELDLIST_NAME (domain, i), 0, stream); + break; + } + fprintf_filtered (stream, "("); + type_print (type, "", stream, -1); + fprintf_filtered (stream, ") %d", (int) val >> 3); + } + else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER) + { + struct type *domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)); + struct type *target = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type)); + char *kind = ""; + + /* VAL is a byte offset into the structure type DOMAIN. + Find the name of the field for that offset and + print it. */ + int extra = 0; + int bits = 0; + len = TYPE_NFIELDS (domain); + /* @@ Make VAL into bit offset */ + val = unpack_long (builtin_type_int, valaddr) << 3; + for (i = 0; i < len; i++) + { + int bitpos = TYPE_FIELD_BITPOS (domain, i); + QUIT; + if (val == bitpos) + break; + if (val < bitpos && i > 0) { - fputc ('&', stream); - type_print_base (domain, stream, 0, 0); - fprintf (stream, "::"); - fprintf (stream, "%s", TYPE_FIELD_NAME (domain, i)); - if (extra) - fprintf (stream, " + %d bytes", extra); - if (bits) - fprintf (stream, " (offset in bits)"); + int ptrsize = (TYPE_LENGTH (builtin_type_char) * TYPE_LENGTH (target)); + /* Somehow pointing into a field. */ + i -= 1; + extra = (val - TYPE_FIELD_BITPOS (domain, i)); + if (extra & 0x3) + bits = 1; + else + extra >>= 3; break; } } - fputc ('(', stream); - type_print (type, "", stream, -1); - fprintf (stream, ") %d", val >> 3); + if (i < len) + { + fprintf_filtered (stream, "&"); + type_print_base (domain, stream, 0, 0); + fprintf_filtered (stream, "::"); + fputs_filtered (TYPE_FIELD_NAME (domain, i), stream); + if (extra) + fprintf_filtered (stream, " + %d bytes", extra); + if (bits) + fprintf_filtered (stream, " (offset in bits)"); + break; + } + fprintf_filtered (stream, "%d", val >> 3); } else { - fprintf (stream, "0x%x", * (int *) valaddr); + fprintf_filtered (stream, "0x%x", * (int *) valaddr); /* For a pointer to char or unsigned char, also print the string pointed to, unless pointer is null. */ @@ -309,18 +477,17 @@ val_print (type, valaddr, address, stream, format, deref_ref) if (TYPE_LENGTH (elttype) == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT && format == 0 - /* Convex needs this typecast to a long */ - && (long) unpack_long (type, valaddr) != 0 + && unpack_long (type, valaddr) != 0 && print_max) { - fputc (' ', stream); + fprintf_filtered (stream, " "); /* Get first character. */ if (read_memory ( (CORE_ADDR) unpack_long (type, valaddr), &c, 1)) { /* First address out of bounds. */ - fprintf (stream, "
", + fprintf_filtered (stream, "
", (* (int *) valaddr)); break; } @@ -328,32 +495,31 @@ val_print (type, valaddr, address, stream, format, deref_ref) { /* A real string. */ int out_of_bounds = 0; - - fputc ('"', stream); - while (c) + char *string = (char *) alloca (print_max); + + while (i < print_max) { QUIT; - printchar (c, stream, '"'); - if (++i >= print_max) - break; if (read_memory ((CORE_ADDR) unpack_long (type, valaddr) + i, &c, 1)) { - /* This address was out of bounds. */ - fprintf (stream, - "\"***
", - (* (int *) valaddr) + i); out_of_bounds = 1; break; } + else if (c == '\0') + break; + else + string[i++] = c; } - if (!out_of_bounds) - { - fputc ('"', stream); - if (i == print_max) - fprintf (stream, "..."); - } + + if (i != 0) + print_string (stream, string, i); + if (out_of_bounds) + fprintf_filtered (stream, + "***
", + (*(int *) valaddr) + i); } + fflush (stream); } /* Return number of characters printed, plus one for the @@ -367,7 +533,7 @@ val_print (type, valaddr, address, stream, format, deref_ref) break; case TYPE_CODE_REF: - fprintf (stream, "(0x%x &) = ", * (int *) valaddr); + fprintf_filtered (stream, "(0x%x &) = ", * (int *) valaddr); /* De-reference the reference. */ if (deref_ref) { @@ -375,53 +541,94 @@ val_print (type, valaddr, address, stream, format, deref_ref) { value val = value_at (TYPE_TARGET_TYPE (type), * (int *) valaddr); val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), - VALUE_ADDRESS (val), stream, format, deref_ref); + VALUE_ADDRESS (val), stream, format, + deref_ref, recurse + 1, pretty); } else - fprintf (stream, "???"); + fprintf_filtered (stream, "???"); } break; - case TYPE_CODE_STRUCT: case TYPE_CODE_UNION: - fprintf (stream, "{"); + if (recurse && !unionprint) + { + fprintf_filtered (stream, "{...}"); + break; + } + /* Fall through. */ + case TYPE_CODE_STRUCT: + fprintf_filtered (stream, "{"); len = TYPE_NFIELDS (type); n_baseclasses = TYPE_N_BASECLASSES (type); for (i = 1; i <= n_baseclasses; i++) { - fprintf (stream, "\n<%s> = ", TYPE_NAME (TYPE_BASECLASS (type, i))); + fprintf_filtered (stream, "\n"); + if (pretty) + print_spaces_filtered (2 + 2 * recurse, stream); + fputs_filtered ("<", stream); + fputs_filtered (TYPE_NAME (TYPE_BASECLASS (type, i)), stream); + fputs_filtered ("> = ", stream); val_print (TYPE_FIELD_TYPE (type, 0), valaddr + TYPE_FIELD_BITPOS (type, i-1) / 8, - 0, stream, 0, 0); + 0, stream, 0, 0, recurse + 1, pretty); } - if (i > 1) fprintf (stream, "\nmembers of %s: ", TYPE_NAME (type)); - for (i -= 1; i < len; i++) + if (i > 1) { + fprintf_filtered (stream, "\n"); + print_spaces_filtered (2 + 2 * recurse, stream); + fputs_filtered ("members of ", stream); + fputs_filtered (TYPE_NAME (type), stream); + fputs_filtered (": ", stream); + } + if (!len && i == 1) + fprintf_filtered (stream, ""); + else { - if (i > n_baseclasses) fprintf (stream, ", "); - fprintf (stream, "%s = ", TYPE_FIELD_NAME (type, i)); - /* check if static field */ - if (TYPE_FIELD_STATIC (type, i)) - { - value v; - - v = value_static_field (type, TYPE_FIELD_NAME (type, i), i); - val_print (TYPE_FIELD_TYPE (type, i), - VALUE_CONTENTS (v), 0, stream, format, deref_ref); - } - else if (TYPE_FIELD_PACKED (type, i)) + for (i -= 1; i < len; i++) { - val = unpack_field_as_long (type, valaddr, i); - val_print (TYPE_FIELD_TYPE (type, i), &val, 0, - stream, format, deref_ref); + if (i > n_baseclasses) fprintf_filtered (stream, ", "); + if (pretty) + { + fprintf_filtered (stream, "\n"); + print_spaces_filtered (2 + 2 * recurse, stream); + } + fputs_filtered (TYPE_FIELD_NAME (type, i), stream); + fputs_filtered (" = ", stream); + /* check if static field */ + if (TYPE_FIELD_STATIC (type, i)) + { + value v; + + v = value_static_field (type, TYPE_FIELD_NAME (type, i), i); + val_print (TYPE_FIELD_TYPE (type, i), + VALUE_CONTENTS (v), 0, stream, format, + deref_ref, recurse + 1, pretty); + } + else if (TYPE_FIELD_PACKED (type, i)) + { + char *valp = (char *) & val; + union {int i; char c;} test; + test.i = 1; + if (test.c != 1) + valp += sizeof val - TYPE_LENGTH (TYPE_FIELD_TYPE (type, i)); + val = unpack_field_as_long (type, valaddr, i); + val_print (TYPE_FIELD_TYPE (type, i), valp, 0, + stream, format, deref_ref, recurse + 1, pretty); + } + else + { + val_print (TYPE_FIELD_TYPE (type, i), + valaddr + TYPE_FIELD_BITPOS (type, i) / 8, + 0, stream, format, deref_ref, + recurse + 1, pretty); + } } - else + if (pretty) { - val_print (TYPE_FIELD_TYPE (type, i), - valaddr + TYPE_FIELD_BITPOS (type, i) / 8, - 0, stream, format, deref_ref); + fprintf_filtered (stream, "\n"); + print_spaces_filtered (2 * recurse, stream); } } - fprintf (stream, "}"); + fprintf_filtered (stream, "}"); break; case TYPE_CODE_ENUM: @@ -431,7 +638,7 @@ val_print (type, valaddr, address, stream, format, deref_ref) break; } len = TYPE_NFIELDS (type); - val = (long) unpack_long (builtin_type_int, valaddr); + val = unpack_long (builtin_type_int, valaddr); for (i = 0; i < len; i++) { QUIT; @@ -439,9 +646,9 @@ val_print (type, valaddr, address, stream, format, deref_ref) break; } if (i < len) - fprintf (stream, "%s", TYPE_FIELD_NAME (type, i)); + fputs_filtered (TYPE_FIELD_NAME (type, i), stream); else - fprintf (stream, "%d", val); + fprintf_filtered (stream, "%d", (int) val); break; case TYPE_CODE_FUNC: @@ -450,10 +657,10 @@ val_print (type, valaddr, address, stream, format, deref_ref) print_scalar_formatted (valaddr, type, format, 0, stream); break; } - fprintf (stream, "{"); + fprintf_filtered (stream, "{"); type_print (type, "", stream, -1); - fprintf (stream, "} "); - fprintf (stream, "0x%x", address); + fprintf_filtered (stream, "} "); + fprintf_filtered (stream, "0x%x", address); break; case TYPE_CODE_INT: @@ -462,15 +669,26 @@ val_print (type, valaddr, address, stream, format, deref_ref) print_scalar_formatted (valaddr, type, format, 0, stream); break; } - fprintf (stream, - TYPE_UNSIGNED (type) ? "%u" : "%d", - unpack_long (type, valaddr)); +#ifdef PRINT_TYPELESS_INTEGER + PRINT_TYPELESS_INTEGER (stream, type, unpack_long (type, valaddr)); +#else +#ifndef LONG_LONG + fprintf_filtered (stream, + TYPE_UNSIGNED (type) ? "%u" : "%d", + unpack_long (type, valaddr)); +#else + fprintf_filtered (stream, + TYPE_UNSIGNED (type) ? "%llu" : "%lld", + unpack_long (type, valaddr)); +#endif +#endif + if (TYPE_LENGTH (type) == 1) { - fprintf (stream, " '"); + fprintf_filtered (stream, " '"); printchar ((unsigned char) unpack_long (type, valaddr), stream, '\''); - fputc ('\'', stream); + fprintf_filtered (stream, "'"); } break; @@ -480,12 +698,10 @@ val_print (type, valaddr, address, stream, format, deref_ref) print_scalar_formatted (valaddr, type, format, 0, stream); break; } - /* FIXME: When printing NaNs or invalid floats, print them - in raw hex in addition to the message. */ #ifdef IEEE_FLOAT - if (is_nan ((void *)valaddr, TYPE_LENGTH(type))) + if (is_nan ((void *) valaddr, TYPE_LENGTH (type))) { - fprintf (stream, "NaN"); + fprintf_filtered (stream, "NaN"); break; } #endif @@ -495,20 +711,22 @@ val_print (type, valaddr, address, stream, format, deref_ref) doub = unpack_double (type, valaddr, &inv); if (inv) - fprintf (stream, "Invalid float value"); + fprintf_filtered (stream, "Invalid float value"); else - fprintf (stream, TYPE_LENGTH (type) <= 4? "%.6g": "%.16g", doub); + fprintf_filtered (stream, + TYPE_LENGTH (type) <= 4? "%.6g": "%.16g", doub); } break; case TYPE_CODE_VOID: - fprintf (stream, "void"); + fprintf_filtered (stream, "void"); break; default: error ("Invalid type code in symbol table."); } fflush (stream); + return 0; } #ifdef IEEE_FLOAT @@ -517,27 +735,29 @@ val_print (type, valaddr, address, stream, format, deref_ref) int is_nan (fp, len) - void *fp; - int len; + void *fp; + int len; { int lowhalf, highhalf; - union ieee { - long i[2]; /* ASSUMED 32 BITS */ - float f; /* ASSUMED 32 BITS */ - double d; /* ASSUMED 64 BITS */ - } *arg; + union ieee + { + long i[2]; /* ASSUMED 32 BITS */ + float f; /* ASSUMED 32 BITS */ + double d; /* ASSUMED 64 BITS */ + } *arg; arg = (union ieee *)fp; /* * Single precision float. */ - if (len == sizeof(long)) { - highhalf = arg->i[0]; - return ((((highhalf >> 23) & 0xFF) == 0xFF) - && 0 != (highhalf & 0x7FFFFF)); - } - + if (len == sizeof(long)) + { + highhalf = arg->i[0]; + return ((((highhalf >> 23) & 0xFF) == 0xFF) + && 0 != (highhalf & 0x7FFFFF)); + } + /* Separate the high and low words of the double. Distinguish big and little-endian machines. */ #ifdef WORDS_BIG_ENDIAN @@ -545,11 +765,10 @@ is_nan (fp, len) #else lowhalf = arg->i[0], highhalf = arg->i[1]; #endif - + /* Nan: exponent is the maximum possible, and fraction is nonzero. */ return (((highhalf>>20) & 0x7ff) == 0x7ff - && - ! ((highhalf & 0xfffff == 0) && (lowhalf == 0))); + && ! ((highhalf & 0xfffff == 0) && (lowhalf == 0))); } #endif @@ -590,44 +809,49 @@ type_print_1 (type, varstring, stream, show, level) ((show > 0 || TYPE_NAME (type) == 0) && (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC + || code == TYPE_CODE_METHOD || code == TYPE_CODE_ARRAY || code == TYPE_CODE_MEMBER || code == TYPE_CODE_REF))) - fprintf (stream, " "); + fprintf_filtered (stream, " "); type_print_varspec_prefix (type, stream, show, 0); - fprintf (stream, "%s", varstring); + fputs_filtered (varstring, stream); type_print_varspec_suffix (type, stream, show, 0); } /* Print the method arguments ARGS to the file STREAM. */ static void -type_print_method_args (args, prefix, varstring, stream) +type_print_method_args (args, prefix, varstring, staticp, stream) struct type **args; char *prefix, *varstring; + int staticp; FILE *stream; { int i; - fprintf (stream, " %s%s (", prefix, varstring); - if (args[1] && args[1]->code != TYPE_CODE_VOID) + fputs_filtered (" ", stream); + fputs_filtered (prefix, stream); + fputs_filtered (varstring, stream); + fputs_filtered (" (", stream); + if (args && args[!staticp] && args[!staticp]->code != TYPE_CODE_VOID) { - i = 1; /* skip the class variable */ + i = !staticp; /* skip the class variable */ while (1) { type_print (args[i++], "", stream, 0); if (!args[i]) { - fprintf (stream, " ..."); + fprintf_filtered (stream, " ..."); break; } else if (args[i]->code != TYPE_CODE_VOID) { - fprintf (stream, ", "); + fprintf_filtered (stream, ", "); } else break; } } - fprintf (stream, ")"); + fprintf_filtered (stream, ")"); } /* If TYPE is a derived type, then print out derivation @@ -649,10 +873,11 @@ type_print_derivation_info (stream, type) if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype))) { while (*name != ' ') name++; - fprintf (stream, ": %s%s %s ", + fprintf_filtered (stream, ": %s%s ", TYPE_VIA_PUBLIC (basetype) ? "public" : "private", - TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "", - name + 1); + TYPE_VIA_VIRTUAL (basetype) ? " virtual" : ""); + fputs_filtered (name + 1, stream); + fputs_filtered (" ", stream); } n_baseclasses = TYPE_N_BASECLASSES (basetype); type = basetype; @@ -661,22 +886,22 @@ type_print_derivation_info (stream, type) if (type) { if (n_baseclasses != 0) - fprintf (stream, ": "); + fprintf_filtered (stream, ": "); for (i = 1; i <= n_baseclasses; i++) { basetype = TYPE_BASECLASS (type, i); if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype))) { while (*name != ' ') name++; - fprintf (stream, "%s%s %s", + fprintf_filtered (stream, "%s%s ", TYPE_VIA_PUBLIC (basetype) ? "public" : "private", - TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "", - name + 1); + TYPE_VIA_VIRTUAL (basetype) ? " virtual" : ""); + fputs_filtered (name + 1, stream); } if (i < n_baseclasses) - fprintf (stream, ", "); + fprintf_filtered (stream, ", "); } - putc (' ', stream); + fprintf_filtered (stream, " "); } } @@ -707,33 +932,48 @@ type_print_varspec_prefix (type, stream, show, passed_a_ptr) { case TYPE_CODE_PTR: type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); - fputc ('*', stream); + fprintf_filtered (stream, "*"); break; case TYPE_CODE_MEMBER: + if (passed_a_ptr) + fprintf_filtered (stream, "("); type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, - passed_a_ptr); - fputc (' ', stream); + 0); + fprintf_filtered (stream, " "); + type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, + passed_a_ptr); + fprintf_filtered (stream, "::"); + break; + + case TYPE_CODE_METHOD: + if (passed_a_ptr) + fprintf (stream, "("); + type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, + 0); + fprintf_filtered (stream, " "); type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr); - fprintf (stream, "::"); + fprintf_filtered (stream, "::"); break; case TYPE_CODE_REF: type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); - fputc ('&', stream); + fprintf_filtered (stream, "&"); break; case TYPE_CODE_FUNC: type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, - passed_a_ptr); + 0); if (passed_a_ptr) - fputc ('(', stream); + fprintf_filtered (stream, "("); break; case TYPE_CODE_ARRAY: type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, - passed_a_ptr); + 0); + if (passed_a_ptr) + fprintf_filtered (stream, "("); } } @@ -759,22 +999,51 @@ type_print_varspec_suffix (type, stream, show, passed_a_ptr) switch (TYPE_CODE (type)) { case TYPE_CODE_ARRAY: - type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, - passed_a_ptr); - fprintf (stream, "["); + if (passed_a_ptr) + fprintf_filtered (stream, ")"); + + fprintf_filtered (stream, "["); if (TYPE_LENGTH (type) >= 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0) - fprintf (stream, "%d", - TYPE_LENGTH (type) / TYPE_LENGTH (TYPE_TARGET_TYPE (type))); - fprintf (stream, "]"); + fprintf_filtered (stream, "%d", + (TYPE_LENGTH (type) + / TYPE_LENGTH (TYPE_TARGET_TYPE (type)))); + fprintf_filtered (stream, "]"); + + type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, + 0); break; case TYPE_CODE_MEMBER: if (passed_a_ptr) - fputc (')', stream); + fprintf_filtered (stream, ")"); type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0); break; + case TYPE_CODE_METHOD: + if (passed_a_ptr) + fprintf_filtered (stream, ")"); + type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0); + if (passed_a_ptr) + { + int i; + struct type **args = TYPE_ARG_TYPES (type); + + fprintf_filtered (stream, "("); + if (args[1] == 0) + fprintf_filtered (stream, "..."); + else for (i = 1; args[i] != 0 && args[i]->code != TYPE_CODE_VOID; i++) + { + type_print_1 (args[i], "", stream, -1, 0); + if (args[i+1] == 0) + fprintf_filtered (stream, "..."); + else if (args[i+1]->code != TYPE_CODE_VOID) + fprintf_filtered (stream, ","); + } + fprintf_filtered (stream, ")"); + } + break; + case TYPE_CODE_PTR: case TYPE_CODE_REF: type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1); @@ -784,8 +1053,8 @@ type_print_varspec_suffix (type, stream, show, passed_a_ptr) type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, passed_a_ptr); if (passed_a_ptr) - fprintf (stream, ")"); - fprintf (stream, "()"); + fprintf_filtered (stream, ")"); + fprintf_filtered (stream, "()"); break; } } @@ -819,13 +1088,13 @@ type_print_base (type, stream, show, level) if (type == 0) { - fprintf (stream, "type unknown"); + fprintf_filtered (stream, "type unknown"); return; } if (TYPE_NAME (type) && show <= 0) { - fprintf (stream, TYPE_NAME (type)); + fputs_filtered (TYPE_NAME (type), stream); return; } @@ -836,33 +1105,42 @@ type_print_base (type, stream, show, level) case TYPE_CODE_MEMBER: case TYPE_CODE_REF: case TYPE_CODE_FUNC: + case TYPE_CODE_METHOD: type_print_base (TYPE_TARGET_TYPE (type), stream, show, level); break; case TYPE_CODE_STRUCT: - fprintf (stream, "struct "); + fprintf_filtered (stream, "struct "); goto struct_union; case TYPE_CODE_UNION: - fprintf (stream, "union "); + fprintf_filtered (stream, "union "); struct_union: if (TYPE_NAME (type) && (name = TYPE_NAME (type))) { while (*name != ' ') name++; - fprintf (stream, "%s ", name + 1); + fputs_filtered (name + 1, stream); + fputs_filtered (" ", stream); } if (show < 0) - fprintf (stream, "{...}"); + fprintf_filtered (stream, "{...}"); else { int i; type_print_derivation_info (stream, type); - fprintf (stream, "{"); + fprintf_filtered (stream, "{"); len = TYPE_NFIELDS (type); - if (len) fprintf (stream, "\n"); - else fprintf (stream, "\n"); + if (len) + fprintf_filtered (stream, "\n"); + else + { + if (TYPE_FLAGS (type) & TYPE_FLAG_STUB) + fprintf_filtered (stream, "\n"); + else + fprintf_filtered (stream, "\n"); + } /* If there is a base class for this type, do not print the field that it occupies. */ @@ -874,10 +1152,10 @@ type_print_base (type, stream, show, level) "_vptr$", 6)) continue; - print_spaces (level + 4, stream); + print_spaces_filtered (level + 4, stream); if (TYPE_FIELD_STATIC (type, i)) { - fprintf (stream, "static "); + fprintf_filtered (stream, "static "); } type_print_1 (TYPE_FIELD_TYPE (type, i), TYPE_FIELD_NAME (type, i), @@ -885,14 +1163,20 @@ type_print_base (type, stream, show, level) if (!TYPE_FIELD_STATIC (type, i) && TYPE_FIELD_PACKED (type, i)) { - /* ??? don't know what to put here ??? */; + /* It is a bitfield. This code does not attempt + to look at the bitpos and reconstruct filler, + unnamed fields. This would lead to misleading + results if the compiler does not put out fields + for such things (I don't know what it does). */ + fprintf_filtered (stream, " : %d", + TYPE_FIELD_BITSIZE (type, i)); } - fprintf (stream, ";\n"); + fprintf_filtered (stream, ";\n"); } /* C++: print out the methods */ len = TYPE_NFN_FIELDS (type); - if (len) fprintf (stream, "\n"); + if (len) fprintf_filtered (stream, "\n"); for (i = 0; i < len; i++) { struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i); @@ -901,58 +1185,62 @@ type_print_base (type, stream, show, level) for (j = 0; j < len2; j++) { QUIT; - print_spaces (level + 4, stream); + print_spaces_filtered (level + 4, stream); if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) - fprintf (stream, "virtual "); - type_print (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j))), "", stream, 0); + fprintf_filtered (stream, "virtual "); + else if (TYPE_FN_FIELD_STATIC_P (f, j)) + fprintf_filtered (stream, "static "); + type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)), "", stream, 0); if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$') type_print_method_args (TYPE_FN_FIELD_ARGS (f, j) + 1, "~", - TYPE_FN_FIELDLIST_NAME (type, i), stream); + TYPE_FN_FIELDLIST_NAME (type, i), 0, stream); else type_print_method_args (TYPE_FN_FIELD_ARGS (f, j), "", - TYPE_FN_FIELDLIST_NAME (type, i), stream); + TYPE_FN_FIELDLIST_NAME (type, i), + TYPE_FN_FIELD_STATIC_P (f, j), stream); - fprintf (stream, ";\n"); + fprintf_filtered (stream, ";\n"); } - if (len2) fprintf (stream, "\n"); + if (len2) fprintf_filtered (stream, "\n"); } - print_spaces (level, stream); - fputc ('}', stream); + print_spaces_filtered (level, stream); + fprintf_filtered (stream, "}"); } break; case TYPE_CODE_ENUM: - fprintf (stream, "enum "); + fprintf_filtered (stream, "enum "); if (TYPE_NAME (type)) { name = TYPE_NAME (type); while (*name != ' ') name++; - fprintf (stream, "%s ", name + 1); + fputs_filtered (name + 1, stream); + fputs_filtered (" ", stream); } if (show < 0) - fprintf (stream, "{...}"); + fprintf_filtered (stream, "{...}"); else { - fprintf (stream, "{"); + fprintf_filtered (stream, "{"); len = TYPE_NFIELDS (type); lastval = 0; for (i = 0; i < len; i++) { QUIT; - if (i) fprintf (stream, ", "); - fprintf (stream, "%s", TYPE_FIELD_NAME (type, i)); + if (i) fprintf_filtered (stream, ", "); + fputs_filtered (TYPE_FIELD_NAME (type, i), stream); if (lastval != TYPE_FIELD_BITPOS (type, i)) { - fprintf (stream, " : %d", TYPE_FIELD_BITPOS (type, i)); + fprintf_filtered (stream, " : %d", TYPE_FIELD_BITPOS (type, i)); lastval = TYPE_FIELD_BITPOS (type, i); } lastval++; } - fprintf (stream, "}"); + fprintf_filtered (stream, "}"); } break; @@ -961,20 +1249,20 @@ type_print_base (type, stream, show, level) name = unsigned_type_table[TYPE_LENGTH (type)]; else name = signed_type_table[TYPE_LENGTH (type)]; - fprintf (stream, "%s", name); + fputs_filtered (name, stream); break; case TYPE_CODE_FLT: name = float_type_table[TYPE_LENGTH (type)]; - fprintf (stream, "%s", name); + fputs_filtered (name, stream); break; case TYPE_CODE_VOID: - fprintf (stream, "void"); + fprintf_filtered (stream, "void"); break; case 0: - fprintf (stream, "struct unknown"); + fprintf_filtered (stream, "struct unknown"); break; default: @@ -987,7 +1275,37 @@ set_maximum_command (arg) char *arg; { if (!arg) error_no_arg ("value for maximum elements to print"); - print_max = atoi (arg); + print_max = parse_and_eval_address (arg); +} + +static void +set_prettyprint_command (arg, from_tty) + char *arg; + int from_tty; +{ + prettyprint = parse_binary_operation ("set prettyprint", arg); +} + +static void +set_unionprint_command (arg, from_tty) + char *arg; + int from_tty; +{ + unionprint = parse_binary_operation ("set unionprint", arg); +} + +format_info (arg, from_tty) + char *arg; + int from_tty; +{ + if (arg) + error ("\"info format\" does not take any arguments."); + printf ("Prettyprinting of structures is %s.\n", + prettyprint ? "on" : "off"); + printf ("Printing of unions interior to structures is %s.\n", + unionprint ? "on" : "off"); + printf ("The maximum number of array elements printed is %d.\n", + print_max); } extern struct cmd_list_element *setlist; @@ -999,6 +1317,22 @@ _initialize_valprint () "Set NUMBER as limit on string chars or array elements to print.", &setlist); + add_cmd ("prettyprint", class_support, set_prettyprint_command, + "Turn prettyprinting of structures on and off.", + &setlist); + add_alias_cmd ("pp", "prettyprint", class_support, 1, &setlist); + + add_cmd ("unionprint", class_support, set_unionprint_command, + "Turn printing of unions interior to structures on and off.", + &setlist); + + add_info ("format", format_info, + "Show current settings of data formatting options."); + + /* Give people the defaults which they are used to. */ + prettyprint = 0; + unionprint = 1; + print_max = 200; unsigned_type_table diff --git a/gdb/value.h b/gdb/value.h index 3a14661f2f..07dd8e840e 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -1,22 +1,21 @@ /* Definitions for values of C expressions, for GDB. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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 @@ -168,6 +167,7 @@ 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 (); @@ -200,3 +200,13 @@ 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 + }; + diff --git a/gdb/values.c b/gdb/values.c index c81991ee94..fcf13a126c 100644 --- a/gdb/values.c +++ b/gdb/values.c @@ -1,23 +1,21 @@ - /* Low level packing and unpacking of values for GDB. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc. + +This file is part of GDB. -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. +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. -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. +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. -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! -*/ +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 #include "defs.h" @@ -196,7 +194,8 @@ record_latest_value (val) if (i == 0) { register struct value_history_chunk *new - = (struct value_history_chunk *) xmalloc (sizeof (struct value_history_chunk)); + = (struct value_history_chunk *) + xmalloc (sizeof (struct value_history_chunk)); bzero (new->values, sizeof new->values); new->next = value_history_chain; value_history_chain = new; @@ -272,17 +271,28 @@ clear_value_history () } static void -history_info (num_exp) +value_history_info (num_exp, from_tty) char *num_exp; + int from_tty; { register int i; register value val; - register int num; + static int num = 1; if (num_exp) - num = parse_and_eval_address (num_exp) - 5; + { + if (num_exp[0] == '+' && num_exp[1] == '\0') + /* "info history +" should print from the stored position. */ + ; + else + /* "info history " should print around value number . */ + num = parse_and_eval_address (num_exp) - 5; + } else - num = value_history_count - 9; + { + /* "info history" means print the last 10 values. */ + num = value_history_count - 9; + } if (num <= 0) num = 1; @@ -290,9 +300,21 @@ history_info (num_exp) for (i = num; i < num + 10 && i <= value_history_count; i++) { val = access_value_history (i); - printf ("$%d = ", i); - value_print (val, stdout, 0); - printf ("\n"); + printf_filtered ("$%d = ", i); + value_print (val, stdout, 0, Val_pretty_default); + printf_filtered ("\n"); + } + + /* The next "info history +" should start after what we just printed. */ + num += 10; + + /* Hitting just return after this command should do the same thing as + "info history +". If num_exp is null, this is unnecessary, since + "info history +" is not useful after "info history". */ + if (from_tty && num_exp) + { + num_exp[0] = '+'; + num_exp[1] = '\0'; } } @@ -332,7 +354,14 @@ value value_of_internalvar (var) struct internalvar *var; { - register value val = value_copy (var->value); + register value val; + +#ifdef IS_TRAPPED_INTERNALVAR + if (IS_TRAPPED_INTERNALVAR (var->name)) + return VALUE_OF_TRAPPED_INTERNALVAR (var); +#endif + + val = value_copy (var->value); VALUE_LVAL (val) = lval_internalvar; VALUE_INTERNALVAR (val) = var; return val; @@ -345,6 +374,12 @@ set_internalvar_component (var, offset, bitpos, bitsize, newval) value newval; { register char *addr = VALUE_CONTENTS (var->value) + offset; + +#ifdef IS_TRAPPED_INTERNALVAR + if (IS_TRAPPED_INTERNALVAR (var->name)) + SET_TRAPPED_INTERNALVAR (var, newval, bitpos, bitsize, offset); +#endif + if (bitsize) modify_field (addr, (int) value_as_long (newval), bitpos, bitsize); @@ -358,6 +393,11 @@ set_internalvar (var, val) struct internalvar *var; value val; { +#ifdef IS_TRAPPED_INTERNALVAR + if (IS_TRAPPED_INTERNALVAR (var->name)) + SET_TRAPPED_INTERNALVAR (var, val, 0, 0, 0); +#endif + free (var->value); var->value = value_copy (val); release_value (var->value); @@ -392,20 +432,27 @@ static void convenience_info () { register struct internalvar *var; - - if (internalvars) - printf ("Debugger convenience variables:\n\n"); - else - printf ("No debugger convenience variables now defined.\n\ -Convenience variables have names starting with \"$\";\n\ -use \"set\" as in \"set $foo = 5\" to define them.\n"); + int varseen = 0; for (var = internalvars; var; var = var->next) { +#ifdef IS_TRAPPED_INTERNALVAR + if (IS_TRAPPED_INTERNALVAR (var->name)) + continue; +#endif + if (!varseen) + { + printf ("Debugger convenience variables:\n\n"); + varseen = 1; + } printf ("$%s: ", var->name); - value_print (var->value, stdout, 0); + value_print (var->value, stdout, 0, Val_pretty_default); printf ("\n"); } + if (!varseen) + printf ("No debugger convenience variables now defined.\n\ +Convenience variables have names starting with \"$\";\n\ +use \"set\" as in \"set $foo = 5\" to define them.\n"); } /* Extract a value as a C number (either long or double). @@ -426,10 +473,10 @@ value_as_double (val) { double foo; int inv; - + foo = unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &inv); if (inv) - error ("Invalid floating value found in program."); + error ("Invalid floating value found in program."); return foo; } @@ -475,6 +522,10 @@ unpack_long (type, valaddr) if (len == sizeof (long)) return * (unsigned long *) valaddr; +#ifdef LONG_LONG + if (len == sizeof (long long)) + return * (unsigned long long *) valaddr; +#endif } else if (code == TYPE_CODE_INT) { @@ -508,9 +559,9 @@ unpack_long (type, valaddr) } /* Return a double value from the specified type and address. - * INVP points to an int which is set to 0 for valid value, - * 1 for invalid value (bad float format). In either case, - * the returned double is OK to use. */ + INVP points to an int which is set to 0 for valid value, + 1 for invalid value (bad float format). In either case, + the returned double is OK to use. */ double unpack_double (type, valaddr, invp) @@ -522,13 +573,14 @@ unpack_double (type, valaddr, invp) register int len = TYPE_LENGTH (type); register int nosign = TYPE_UNSIGNED (type); - *invp = 0; /* Assume valid */ + *invp = 0; /* Assume valid. */ if (code == TYPE_CODE_FLT) { - if (INVALID_FLOAT (valaddr, len)) { - *invp = 1; - return 1.234567891011121314; - } + if (INVALID_FLOAT (valaddr, len)) + { + *invp = 1; + return 1.234567891011121314; + } if (len == sizeof (float)) return * (float *) valaddr; @@ -582,6 +634,8 @@ unpack_double (type, valaddr, invp) } error ("Value not floating number."); + /* NOTREACHED */ + return (double) 0; /* To silence compiler warning. */ } /* Given a value ARG1 of a struct or union type, @@ -605,7 +659,7 @@ value_field (arg1, fieldno) if (TYPE_FIELD_BITSIZE (VALUE_TYPE (arg1), fieldno)) { v = value_from_long (type, - (LONGEST) unpack_field_as_long (VALUE_TYPE (arg1), + unpack_field_as_long (VALUE_TYPE (arg1), VALUE_CONTENTS (arg1), fieldno)); VALUE_BITPOS (v) = TYPE_FIELD_BITPOS (VALUE_TYPE (arg1), fieldno) % 8; @@ -677,13 +731,15 @@ value_virtual_fn_field (arg1, f, j, type) TYPE_VPTR_FIELDNO (type) = fill_in_vptr_fieldno (type); - /* Pretend that this array is just an array of pointers to integers. - This will have to change for multiple inheritance. */ - vtbl = value_copy (value_field (arg1, TYPE_VPTR_FIELDNO (type))); - VALUE_TYPE (vtbl) = lookup_pointer_type (builtin_type_int); + /* The virtual function table is now an array of structures + which have the form { int16 offset, delta; void *pfn; }. */ + vtbl = value_ind (value_field (arg1, TYPE_VPTR_FIELDNO (type))); - /* Index into the virtual function table. */ - vfn = value_subscript (vtbl, vi); + /* Index into the virtual function table. This is hard-coded because + looking up a field is not cheap, and it may be important to save + time, e.g. if the user has set a conditional breakpoint calling + a virtual function. */ + vfn = value_field (value_subscript (vtbl, vi), 2); /* Reinstantiate the function pointer with the correct type. */ VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j)); @@ -771,7 +827,7 @@ unpack_field_as_long (type, valaddr, fieldno) bcopy (valaddr + bitpos / 8, &val, sizeof val); - /* Extracting bits depends on endianness of the target machine. */ + /* Extracting bits depends on endianness of the machine. */ #ifdef BITS_BIG_ENDIAN val = val >> (sizeof val * 8 - bitpos % 8 - bitsize); #else @@ -790,11 +846,16 @@ modify_field (addr, fieldval, bitpos, bitsize) { long oword; + /* Reject values too big to fit in the field in question. + Otherwise adjoining fields may be corrupted. */ + if (fieldval & ~((1< diff --git a/gdb/version.c b/gdb/version.c index a83b002cb3..0136f8f57e 100644 --- a/gdb/version.c +++ b/gdb/version.c @@ -1,3 +1,20 @@ -/* Define the current version number of GDB. */ +/* Define the current version number of GDB. + Copyright (C) 1989, Free Software Foundation, Inc. -char *version = "3.1"; +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.3"; diff --git a/gdb/xgdb.c b/gdb/xgdb.c index 2431699a3a..54290ec8cc 100644 --- a/gdb/xgdb.c +++ b/gdb/xgdb.c @@ -1,22 +1,21 @@ /* Interface from GDB to X windows. - Copyright (C) 1987 Free Software Foundation, Inc. + Copyright (C) 1987, 1989 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. +This file is part of GDB. -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. +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. -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! -*/ +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. */ /* Original version was contributed by Derek Beatty, 30 June 87. */ @@ -214,6 +213,7 @@ print_prompt () { if (prompt_string) printf ("%s", prompt_string); + fflush (stdout); } /* Handlers for buttons. */ @@ -333,9 +333,12 @@ Widget w; char *command; caddr_t call_data; { - execute_command (command, 0); + char *copy = (char *) xmalloc (strlen (command) + 1); + strcpy (copy, command); + execute_command (copy, 0); xgdb_display_source (); print_prompt (); + free (copy); } static void @@ -422,6 +425,10 @@ create_text_widget (parent, filename) static Arg fileArgs[3]; XtTextSource src; XtTextSink sink; + Widget text_widget; + + text_widget = XtCreateManagedWidget ("disk", textWidgetClass, + parent, NULL, 0); XtSetArg (fileArgs[0], XtNfile, filename); src = XtDiskSourceCreate(parent, fileArgs, 1); @@ -430,7 +437,8 @@ create_text_widget (parent, filename) XtSetArg (fileArgs[0], XtNtextOptions, scrollVertical); XtSetArg (fileArgs[1], XtNtextSource, src); XtSetArg (fileArgs[2], XtNtextSink, sink); - return XtCreateManagedWidget("disk", textWidgetClass, parent, fileArgs, XtNumber (fileArgs)); + XtSetValues (text_widget, fileArgs, XtNumber (fileArgs)); + return text_widget; } /* Entry point to create the widgets representing our display. */ @@ -592,10 +600,12 @@ _initialize_xgdb () extern int inhibit_windows; if (getenv ("DISPLAY") && ! inhibit_windows) - if (xgdb_create_window ()) - window_hook = xgdb_window_hook; + { + if (xgdb_create_window ()) + window_hook = xgdb_window_hook; - specify_exec_file_hook (xgdb_display_exec_file); + specify_exec_file_hook (xgdb_display_exec_file); + } } -- 2.34.1