gdb-2.4+.aux.coff
authorgdb-2.4+.aux.coff <gdb@fsf.org>
Sat, 16 Jan 1988 04:39:57 +0000 (04:39 +0000)
committerPedro Alves <palves@redhat.com>
Sun, 3 Jun 2012 14:36:30 +0000 (15:36 +0100)
118 files changed:
gdb/=emacs [new file with mode: 0644]
gdb/=news [new file with mode: 0644]
gdb/=ns32k.msg [new file with mode: 0644]
gdb/=rt-ans2 [new file with mode: 0644]
gdb/=rt-answers [new file with mode: 0644]
gdb/=rt-changes [new file with mode: 0644]
gdb/=rt-extra [new file with mode: 0644]
gdb/=xgdb.msg [new file with mode: 0644]
gdb/COPYING [new file with mode: 0644]
gdb/ChangeLog [new file with mode: 0644]
gdb/Makefile [new file with mode: 0644]
gdb/RCS/Makefile,v [new file with mode: 0644]
gdb/RCS/coffread.c,v [new file with mode: 0644]
gdb/RCS/core.c,v [new file with mode: 0644]
gdb/RCS/infcmd.c,v [new file with mode: 0644]
gdb/RCS/inflow.c,v [new file with mode: 0644]
gdb/RCS/m-mac-aux.h,v [new file with mode: 0644]
gdb/RCS/m-mac-auxinit.h,v [new file with mode: 0644]
gdb/RCS/m68k-pinsn.c,v [new file with mode: 0644]
gdb/RCS/main.c,v [new file with mode: 0644]
gdb/RCS/source.c,v [new file with mode: 0644]
gdb/RCS/symmisc.c,v [new file with mode: 0644]
gdb/RCS/symtab.c,v [new file with mode: 0644]
gdb/RCS/utils.c,v [new file with mode: 0644]
gdb/README [new file with mode: 0644]
gdb/TAGS [new file with mode: 0644]
gdb/alloca.c [new file with mode: 0644]
gdb/bar.c [new file with mode: 0644]
gdb/bar.nm [new file with mode: 0644]
gdb/bar.s [new file with mode: 0644]
gdb/bar.sym [new file with mode: 0644]
gdb/blockframe.c [new file with mode: 0644]
gdb/breakpoint.c [new file with mode: 0644]
gdb/coffread.c [new file with mode: 0644]
gdb/command.c [new file with mode: 0644]
gdb/command.h [new file with mode: 0644]
gdb/core.c [new file with mode: 0644]
gdb/dbxread.c [new file with mode: 0644]
gdb/defs.h [new file with mode: 0644]
gdb/environ.c [new file with mode: 0644]
gdb/environ.h [new file with mode: 0644]
gdb/eval.c [new file with mode: 0644]
gdb/expprint.c [new file with mode: 0644]
gdb/expread.y [new file with mode: 0644]
gdb/expression.h [new file with mode: 0644]
gdb/findvar.c [new file with mode: 0644]
gdb/firstfile.c [new file with mode: 0644]
gdb/foo.c [new file with mode: 0644]
gdb/foo.nm [new file with mode: 0644]
gdb/foo.od [new file with mode: 0644]
gdb/foo.s [new file with mode: 0644]
gdb/foo.sym [new file with mode: 0644]
gdb/frame.h [new file with mode: 0644]
gdb/gdb.1 [new file with mode: 0644]
gdb/gdb.ideas [new file with mode: 0644]
gdb/infcmd.c [new file with mode: 0644]
gdb/inferior.h [new file with mode: 0644]
gdb/inflow.c [new file with mode: 0644]
gdb/infrun.c [new file with mode: 0644]
gdb/initialize.h [new file with mode: 0644]
gdb/kdb-start.c [new file with mode: 0644]
gdb/lastfile.c [new file with mode: 0644]
gdb/m-isi-ov.h [new file with mode: 0644]
gdb/m-mac-aux.h [new file with mode: 0644]
gdb/m-mac-auxinit.h [new file with mode: 0644]
gdb/m-merlin.h [new file with mode: 0644]
gdb/m-news800.h [new file with mode: 0644]
gdb/m-newsinit.h [new file with mode: 0644]
gdb/m-sun2.h [new file with mode: 0644]
gdb/m-sun3.h [new file with mode: 0644]
gdb/m-suninit.h [new file with mode: 0644]
gdb/m-umax.h [new file with mode: 0644]
gdb/m-vax.h [new file with mode: 0644]
gdb/m-vaxinit.h [new file with mode: 0644]
gdb/m68k-opcode.h [new file with mode: 0644]
gdb/m68k-pinsn.c [new file with mode: 0644]
gdb/main.c [new file with mode: 0644]
gdb/ns32k-opcode.h [new file with mode: 0644]
gdb/ns32k-pinsn.c [new file with mode: 0644]
gdb/obstack.c [new symlink]
gdb/obstack.h [new symlink]
gdb/param.h [new file with mode: 0644]
gdb/pinsn.c [new file with mode: 0644]
gdb/printcmd.c [new file with mode: 0644]
gdb/song [new file with mode: 0644]
gdb/source.c [new file with mode: 0644]
gdb/stack.c [new file with mode: 0644]
gdb/standalone.c [new file with mode: 0644]
gdb/stuff.c [new file with mode: 0644]
gdb/symmisc.c [new file with mode: 0644]
gdb/symseg.h [new file with mode: 0644]
gdb/symtab.c [new file with mode: 0644]
gdb/symtab.h [new file with mode: 0644]
gdb/test2.c [new file with mode: 0644]
gdb/test3.c [new file with mode: 0644]
gdb/testattach.c [new file with mode: 0644]
gdb/testbf.c [new file with mode: 0644]
gdb/testbit.c [new file with mode: 0644]
gdb/testenum.c [new file with mode: 0644]
gdb/testfb.c [new file with mode: 0644]
gdb/testfun.c [new file with mode: 0644]
gdb/testkill.c [new file with mode: 0644]
gdb/testrec.c [new file with mode: 0644]
gdb/testreg.c [new file with mode: 0644]
gdb/testregs.c [new file with mode: 0644]
gdb/testshort.c [new file with mode: 0644]
gdb/testsig.c [new file with mode: 0644]
gdb/utils.c.OK [new file with mode: 0644]
gdb/valarith.c [new file with mode: 0644]
gdb/valops.c [new file with mode: 0644]
gdb/valprint.c [new file with mode: 0644]
gdb/value.h [new file with mode: 0644]
gdb/values.c [new file with mode: 0644]
gdb/vax-opcode.h [new file with mode: 0644]
gdb/vax-pinsn.c [new file with mode: 0644]
gdb/version.c [new file with mode: 0644]
gdb/wait.h [new file with mode: 0644]
gdb/xgdb.c [new file with mode: 0644]

diff --git a/gdb/=emacs b/gdb/=emacs
new file mode 100644 (file)
index 0000000..74097b7
--- /dev/null
@@ -0,0 +1,108 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; gdb code changes
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+/*
+ * Core Problem:  when gdb says something like (../src/file.c 1234), the
+ * real file might be in any of the active dirs in use by gdb and thus
+ * emacs can not always find the file at "../src".  Emacs cannot just
+ * scan for GDB dir commands because these might be given in the .gdbinit
+ * file or other scripts.  The only solution is to have gdb be a bit more
+ * specific when it prints file names.
+ * 
+ * Remaining defects:
+ * 
+ * 1. Do I really have to open the file to find out if it exists?
+ *    There should be a faster way.
+ * 
+ * 2. Should there be a bdb command to toggle between short and absolute
+ * forms of the file name?
+ */
+
+
+/* Add this to ~emacs/gdb/source.c after the openp function */
+
+char *
+get_absolute_filename(table)
+/* Added by Lynn Slater, Silvar-Lisco 10/6/87
+   returns the address of the best possible name to use for the file
+   in the passed symtab.  Returns the filename if the path cannot be
+   resolved.
+   Please remember to free the absolute name after use.*/
+struct symtab *table;
+{
+  register int desc;
+  char *absolute_name;
+
+  desc = openp (source_path, 0, table->filename, O_RDONLY, 0, &absolute_name);
+  if (desc < 0)
+    return( savestring(table->filename, strlen(table->filename)));
+
+  close (desc);
+  return(absolute_name);
+}
+
+/* Replace this fcn in ~emacs/gdb/stack.c */
+void
+print_frame_info (fi, level, source, args)
+     struct frame_info *fi;
+     register int level;
+     int source;
+     int args;
+{
+  register FRAME frame = fi->frame;
+  struct symtab_and_line sal;
+  struct symbol *func;
+  register char *funname = 0;
+  int numargs;
+
+  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;
+    }
+
+  if (source >= 0 || !sal.symtab)
+    {
+      /* This avoids a bug in cc on the sun.  */
+      struct frame_info tem;
+      tem = *fi;
+
+      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, tem);
+         print_frame_args (func, FRAME_ARGS_ADDRESS (tem), numargs, stdout);
+       }
+      printf (")");
+      if (sal.symtab)
+        {
+         char * absolute_filename;
+         absolute_filename = (char *) get_absolute_filename(sal.symtab);
+         printf (" (%s line %d)", absolute_filename, sal.line);
+         free(absolute_filename);
+       }
+      printf ("\n");
+    }
+
+  if (source != 0 && sal.symtab)
+    {
+      if (source < 0 && fi->pc != sal.pc)
+       printf ("0x%x\t", fi->pc);
+      print_source_lines (sal.symtab, sal.line, sal.line + 1);
+      current_source_line = max (sal.line - 5, 1);
+    }
+  if (source != 0)
+    set_default_breakpoint (1, fi->pc, sal.symtab, sal.line);
+
+  fflush (stdout);
+}
+
diff --git a/gdb/=news b/gdb/=news
new file mode 100644 (file)
index 0000000..43de9bc
--- /dev/null
+++ b/gdb/=news
@@ -0,0 +1,136 @@
+===================================================================
+RCS file: RCS/printcmd.c,v
+retrieving revision 1.1
+diff -c3 -r1.1 printcmd.c
+*** /tmp/,RCSt1011248  Tue Jan 12 14:06:06 1988
+--- printcmd.c Mon Sep 21 21:33:39 1987
+***************
+*** 174,179
+       VALUE_TYPE (val) = builtin_type_float;
+        if (TYPE_LENGTH (VALUE_TYPE (val)) == sizeof (double))
+       VALUE_TYPE (val) = builtin_type_double;
+        printf ("%g", value_as_double (val));
+        break;
+  
+
+--- 174,185 -----
+       VALUE_TYPE (val) = builtin_type_float;
+        if (TYPE_LENGTH (VALUE_TYPE (val)) == sizeof (double))
+       VALUE_TYPE (val) = builtin_type_double;
++ #ifdef PRINTF_BUG
++       if (is_nan(value_as_double (val)))
++       printf ("Nan");
++       else
++         printf ("%g", value_as_double (val));
++ #else
+        printf ("%g", value_as_double (val));
+  #endif
+        break;
+***************
+*** 175,180
+        if (TYPE_LENGTH (VALUE_TYPE (val)) == sizeof (double))
+       VALUE_TYPE (val) = builtin_type_double;
+        printf ("%g", value_as_double (val));
+        break;
+  
+      case 0:
+
+--- 181,187 -----
+          printf ("%g", value_as_double (val));
+  #else
+        printf ("%g", value_as_double (val));
++ #endif
+        break;
+  
+      case 0:
+===================================================================
+RCS file: RCS/valprint.c,v
+retrieving revision 1.1
+diff -c3 -r1.1 valprint.c
+*** /tmp/,RCSt1011248  Tue Jan 12 14:06:09 1988
+--- valprint.c Mon Sep 21 21:35:45 1987
+***************
+*** 21,26
+  #include <stdio.h>
+  #include "defs.h"
+  #include "initialize.h"
+  #include "symtab.h"
+  #include "value.h"
+  
+
+--- 21,27 -----
+  #include <stdio.h>
+  #include "defs.h"
+  #include "initialize.h"
++ #include "param.h"
+  #include "symtab.h"
+  #include "value.h"
+  
+***************
+*** 249,255
+        break;
+  
+      case TYPE_CODE_FLT:
+!       fprintf (stream, "%g", unpack_double (type, valaddr));
+        break;
+  
+      case TYPE_CODE_VOID:
+
+--- 250,265 -----
+        break;
+  
+      case TYPE_CODE_FLT:
+!       { double d = unpack_double (type, valaddr);
+! #ifdef PRINTF_BUG
+!      if (is_nan(d))
+!          fprintf (stream, "Nan");
+!      else
+!          fprintf (stream, "%g", d);
+! #else
+!      fprintf (stream, "%g", d);
+! #endif
+!       }
+        break;
+  
+      case TYPE_CODE_VOID:
+***************
+*** 559,563
+    float_type_table[sizeof (float)] = "float";
+    float_type_table[sizeof (double)] = "double";
+  }
+  
+  END_FILE
+
+--- 569,599 -----
+    float_type_table[sizeof (float)] = "float";
+    float_type_table[sizeof (double)] = "double";
+  }
++ 
++ 
++ #ifdef PRINTF_BUG
++ 
++ struct ieee {                         /* IEEE floating format */
++   unsigned int s:1;
++   unsigned int e:11;
++   unsigned int f1:20;
++   unsigned int f2;
++ };
++ 
++ #define ZERO_F(x)  ((x.f1 == 0) && (x.f2 == 0))     /* zero fraction ? */
++ #define ZERO_E(x)  (x.e == 0)                       /* zero exponential ? */
++ #define MAX_E(x)   (x.e == 0x7ff)                   /* max exponential ? */
++ #define MINUS_S(x) (x.s == 1)                       /* minus ? */
++ 
++ int
++ is_nan(arg)                            /* Not a Number ? */
++ struct ieee arg;
++ {
++   if (MAX_E(arg) && !ZERO_F(arg))
++     return (1);
++   else
++     return (0);
++ }
++ #endif
+  
+  END_FILE
+
diff --git a/gdb/=ns32k.msg b/gdb/=ns32k.msg
new file mode 100644 (file)
index 0000000..5268fc7
--- /dev/null
@@ -0,0 +1,1182 @@
+From uwvax!sequent!ogcvax!reed!keith@RUTGERS.EDU Thu Jul 23 21:46:44 1987
+Received: by PREP.AI.MIT.EDU; Thu, 23 Jul 87 21:44:35 EDT
+Received: by RUTGERS.EDU (5.54/1.14) with UUCP 
+       id AA04584; Thu, 23 Jul 87 21:42:33 EDT
+Received: from sequent.UUCP by spool.WISC.EDU; Thu, 23 Jul 87 20:36:20 CDT
+Received: from reed.UUCP by ogcvax.OGC.EDU (5.51/OGC_4.6+)
+               id AA05332; Thu, 23 Jul 87 13:31:52 PDT
+Received: by reed.UUCP (5.51/5.17)
+       id AA23265; Thu, 23 Jul 87 11:19:20 PDT
+From: uwvax!sequent!ogcvax!reed!keith@RUTGERS.EDU (Keith Packard)
+Message-Id: <8707231819.AA23265@reed.UUCP>
+To: phr@prep.ai.mit.edu (Paul Rubin)
+Subject: Re: gdb 
+In-Reply-To: Your message of Thu, 23 Jul 87 02:06:52 EDT.
+             <8707230603.AA11722@EDDIE.MIT.EDU> 
+Date: Thu, 23 Jul 87 11:19:13 PDT
+Status: R
+
+
+Thanks much for the address -- the 2.1 sources that I have do not contain
+any bug reporting address.  The only real bug that I found was in
+write_register_bytes in findvar.c:
+
+was:
+
+  bcopy (myaddr, &registers[regbyte], len);
+  if (have_inferior_p ())
+    store_inferior_registers (0);
+
+should be:
+
+  bcopy (myaddr, &registers[regbyte], len);
+  if (have_inferior_p ())
+    store_inferior_registers (-1);
+
+Other than that, most of the porting effort to the 32k was in removing
+references to alloca - the 32k is adamant about not using alloca -- in fact
+someone at tektronix wrote a replacement which accepted another argument
+pointing to the function entry instruction so that the stack could be maimed
+mercilessly...  I just replaced them all with malloc and used free at
+judicious times.  It's not perfect but it worked fine.
+
+I would upload gdb 2.3 if I could, however I am not on the arpa net.  I'll
+probably end up sending GNU a tape.
+
+It's a great debugger, thanks!
+
+       keith packard
+       tektronix!reed!keith
+
+Here are the param files and instruction printer for the 32032:
+
+#!/bin/sh
+# shar:        Shell Archiver
+#      Run the following text with /bin/sh to create:
+#      m-merlin.h
+#      n32k-opcode.h
+#      n32k-pinsn.c
+sed 's/^X//' << 'SHAR_EOF' > m-merlin.h
+X/* Definitions to make GDB run on a merlin under utek 2.1
+X   Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+X
+XGDB is distributed in the hope that it will be useful, but WITHOUT ANY
+XWARRANTY.  No author or distributor accepts responsibility to anyone
+Xfor the consequences of using it or for whether it serves any
+Xparticular purpose or works at all, unless he says so in writing.
+XRefer to the GDB General Public License for full details.
+X
+XEveryone is granted permission to copy, modify and redistribute GDB,
+Xbut only under the conditions described in the GDB General Public
+XLicense.  A copy of this license is supposed to have been given to you
+Xalong with GDB so you can know your rights and responsibilities.  It
+Xshould be in a file named COPYING.  Among other things, the copyright
+Xnotice and this notice must be preserved on all copies.
+X
+XIn other words, go ahead and share GDB, but don't try to stop
+Xanyone else from sharing it farther.  Help stamp out software hoarding!
+X*/
+X
+X#ifndef ns16000
+X#define ns16000
+X#endif
+X
+X# include     <machine/reg.h>
+X
+X/* Define this if the C compiler puts an underscore at the front
+X   of external names before giving them to the linker.  */
+X
+X#define NAMES_HAVE_UNDERSCORE
+X
+X/* Offset from address of function to start of its code.
+X   Zero on most machines.  */
+X
+X#define FUNCTION_START_OFFSET 0
+X
+X/* Advance PC across any function entry prologue instructions
+X   to reach some "real" code.  */
+X
+X#define SKIP_PROLOGUE(pc)                             \
+X{ register int op = read_memory_integer (pc, 1);      \
+X  if (op == 0x82) { op = read_memory_integer (pc+2,1);  \
+X                  if ((op & 0x80) == 0) pc += 3;      \
+X                  else if ((op & 0xc0) == 0x80) pc += 4;      \
+X                  else pc += 6;                       \
+X                 }                                    \
+X}
+X
+X/* Immediately after a function call, return the saved pc.
+X   Can't always go through the frames for this because on some machines
+X   the new frame is not set up until the new function executes
+X   some instructions.  */
+X
+X#define SAVED_PC_AFTER_CALL(frame) \
+X      read_memory_integer (read_register (SP_REGNUM), 4)
+X
+X/* This is the amount to subtract from u.u_ar0
+X   to get the offset in the core file of the register values.  */
+X
+X#define KERNEL_U_ADDR (0xfef000)
+X
+X/* Address of end of stack space.  */
+X
+X#define STACK_END_ADDR (0x800000)
+X
+X/* Stack grows downward.  */
+X
+X#define INNER_THAN <
+X
+X/* Sequence of bytes for breakpoint instruction.  */
+X
+X#define BREAKPOINT {0xf2}
+X
+X/* Amount PC must be decremented by after a breakpoint.
+X   This is often the number of bytes in BREAKPOINT
+X   but not always.  */
+X
+X#define DECR_PC_AFTER_BREAK 0
+X
+X/* Nonzero if instruction at PC is a return instruction.  */
+X
+X#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0x12)
+X
+X/* Return 1 if P points to an invalid floating point value.  */
+X
+X#define INVALID_FLOAT(p) (0)
+X
+X/* Say how long (ordinary) registers are.  */
+X
+X#define REGISTER_TYPE long
+X
+X/* Number of machine registers */
+X
+X#define NUM_REGS              25
+X
+X#define NUM_GENERAL_REGS      8
+X
+X/* Initializer for an array of names of registers.
+X   There should be NUM_REGS strings in this initializer.  */
+X
+X#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",       \
+X                      "pc", "sp", "fp", "ps",                         \
+X                      "fsr",                                          \
+X                      "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+X                      "l0", "l1", "l2", "l3", "l4",                   \
+X                      }
+X
+X/* Register numbers of various important registers.
+X   Note that some of these values are "real" register numbers,
+X   and correspond to the general registers of the machine,
+X   and some are "phony" register numbers which are too large
+X   to be actual register numbers as far as the user is concerned
+X   but do serve to get the desired values when passed to read_register.  */
+X
+X#define AP_REGNUM FP_REGNUM
+X#define FP_REGNUM 10          /* Contains address of executing stack frame */
+X#define SP_REGNUM 9           /* Contains address of top of stack */
+X#define PC_REGNUM 8           /* Contains program counter */
+X#define PS_REGNUM 11          /* Contains processor status */
+X#define FPS_REGNUM 12         /* Floating point status register */
+X#define FP0_REGNUM 13         /* Floating point register 0 */
+X#define LP0_REGNUM 21         /* Double register 0 (same as FP0) */
+X
+X#define REGISTER_U_ADDR(addr, blockend, regno) \
+X{                                                                     \
+X  switch (regno) {                                                    \
+X  case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:     \
+X      addr = blockend + (R0 - regno) * sizeof (int); break;           \
+X  case PC_REGNUM:                                                     \
+X      addr = blockend + PC * sizeof (int); break;                     \
+X  case SP_REGNUM:                                                     \
+X      addr = blockend + SP * sizeof (int); break;                     \
+X  case FP_REGNUM:                                                     \
+X      addr = blockend + FP * sizeof (int); break;                     \
+X  case PS_REGNUM:                                                     \
+X      addr = blockend + 12 * sizeof (int); break;                     \
+X  case FPS_REGNUM:                                                    \
+X      addr = 108; break;                                              \
+X  case FP0_REGNUM + 0: case FP0_REGNUM + 1:                           \
+X  case FP0_REGNUM + 2: case FP0_REGNUM + 3:                           \
+X  case FP0_REGNUM + 4: case FP0_REGNUM + 5:                           \
+X  case FP0_REGNUM + 6: case FP0_REGNUM + 7:                           \
+X      addr = 76 + (regno - FP0_REGNUM) * sizeof (float); break;       \
+X  case LP0_REGNUM + 0: case LP0_REGNUM + 1:                           \
+X  case LP0_REGNUM + 2: case LP0_REGNUM + 3:                           \
+X      addr = 76 + (regno - LP0_REGNUM) * sizeof (double); break;      \
+X  default:                                                            \
+X      printf ("bad argument to REGISTER_U_ADDR %d\n", regno);         \
+X      abort ();                                                       \
+X  }                                                                   \
+X}
+X
+X/* Total amount of space needed to store our copies of the machine's
+X   register state, the array `registers'.  */
+X#define REGISTER_BYTES ((NUM_REGS - 4) * sizeof (int) + 4 * sizeof (double))
+X
+X/* Index within `registers' of the first byte of the space for
+X   register N.  */
+X
+X#define REGISTER_BYTE(N) ((N) >= LP0_REGNUM ? \
+X      LP0_REGNUM * 4 + ((N) - LP0_REGNUM) * 8 : (N) * 4)
+X
+X/* Number of bytes of storage in the actual machine representation
+X   for register N.  On the 32000, all regs are 4 bytes
+X   except for the doubled floating registers. */
+X
+X#define REGISTER_RAW_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
+X
+X/* Number of bytes of storage in the program's representation
+X   for register N.  On the 32000, all regs are 4 bytes
+X   except for the doubled floating registers. */
+X
+X#define REGISTER_VIRTUAL_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
+X
+X/* Largest value REGISTER_RAW_SIZE can have.  */
+X
+X#define MAX_REGISTER_RAW_SIZE 8
+X
+X/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+X
+X#define MAX_REGISTER_VIRTUAL_SIZE 8
+X
+X/* Nonzero if register N requires conversion
+X   from raw format to virtual format.  */
+X
+X#define REGISTER_CONVERTIBLE(N) 0
+X
+X/* Convert data from raw format for register REGNUM
+X   to virtual format for register REGNUM.  */
+X
+X#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)   \
+X  bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
+X
+X/* Convert data from virtual format for register REGNUM
+X   to raw format for register REGNUM.  */
+X
+X#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)       \
+X  bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
+X
+X/* Return the GDB type object for the "standard" data type
+X   of data in register N.  */
+X
+X#define REGISTER_VIRTUAL_TYPE(N) \
+X      ((N) >= FP0_REGNUM ?                    \
+X              (N) >= LP0_REGNUM ?             \
+X                      builtin_type_double     \
+X                      : builtin_type_float    \
+X              : builtin_type_int)     
+X\f
+X/* Describe the pointer in each stack frame to the previous stack frame
+X   (its caller).  */
+X
+X/* FRAME_CHAIN takes a frame's nominal address
+X   and produces the frame's chain-pointer.
+X
+X   FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+X   and produces the nominal address of the caller frame.
+X
+X   However, if FRAME_CHAIN_VALID returns zero,
+X   it means the given frame is the outermost one and has no caller.
+X   In that case, FRAME_CHAIN_COMBINE is not used.  */
+X
+X/* In the case of the Merlin, the frame's nominal address is the FP value,
+X   and at that address is saved previous FP value as a 4-byte word.  */
+X
+X#define FRAME_CHAIN(thisframe)  (read_memory_integer (thisframe, 4))
+X
+X#define FRAME_CHAIN_VALID(chain, thisframe) \
+X  (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
+X
+X#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+X
+X/* Define other aspects of the stack frame.  */
+X
+X#define FRAME_SAVED_PC(frame) (read_memory_integer (frame + 4, 4))
+X
+X/* compute base of arguments */
+X#define FRAME_ARGS_ADDRESS(fi) ((fi).frame)
+X
+X#define FRAME_LOCALS_ADDRESS(fi) ((fi).frame)
+X
+X/* Return number of args passed to a frame.
+X   Can return -1, meaning no way to tell.  */
+X
+X#define FRAME_NUM_ARGS(numargs, fi)                           \
+X{     CORE_ADDR pc;                                           \
+X      int insn;                                               \
+X      int addr_mode;                                          \
+X      int width;                                              \
+X                                                              \
+X      pc = FRAME_SAVED_PC (fi.frame);                         \
+X      insn = read_memory_integer (pc,2);                      \
+X      addr_mode = (insn >> 11) & 0x1f;                        \
+X      insn = insn & 0x7ff;                                    \
+X      if ((insn & 0x7fc) == 0x57c &&                          \
+X          addr_mode == 0x14) { /* immediate */                \
+X              if (insn == 0x57c) /* adjspb */                 \
+X                      width = 1;                              \
+X              else if (insn == 0x57d) /* adjspw */            \
+X                      width = 2;                              \
+X              else if (insn == 0x57f) /* adjspd */            \
+X                      width = 4;                              \
+X              numargs = read_memory_integer (pc+2,width);     \
+X              if (width > 1)                                  \
+X                      flip_bytes (&numargs, width);           \
+X              numargs = - sign_extend (numargs, width*8) / 4; \
+X      } else {                                                \
+X              numargs = -1;                                   \
+X      }                                                       \
+X}
+X
+X/* Return number of bytes at start of arglist that are not really args.  */
+X
+X#define FRAME_ARGS_SKIP 8
+X
+X/* Put here the code to store, into a struct frame_saved_regs,
+X   the addresses of the saved registers of frame described by FRAME_INFO.
+X   This includes special registers such as pc and fp saved in special
+X   ways in the stack frame.  sp is even more special:
+X   the address we return for it IS the sp for the next frame.  */
+X
+X#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+X{                                                             \
+X      int     regmask,regnum;                                 \
+X      int     localcount;                                     \
+X      CORE_ADDR       enter_addr;                             \
+X      CORE_ADDR       next_addr;                              \
+X                                                              \
+X      enter_addr = get_pc_function_start ((frame_info).pc);   \
+X      regmask = read_memory_integer (enter_addr+1, 1);        \
+X      localcount = n32k_localcount (enter_addr);              \
+X      next_addr = (frame_info).frame + localcount;            \
+X      for (regnum = 0; regnum < 8; regnum++, regmask >>= 1)   \
+X              (frame_saved_regs).regs[regnum] = (regmask & 1) ?       \
+X                              (next_addr -= 4) : 0;           \
+X      (frame_saved_regs).regs[SP_REGNUM] = (frame_info).frame + 4;    \
+X      (frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 4;    \
+X      (frame_saved_regs).regs[FP_REGNUM] = (read_memory_integer       \
+X                                      ((frame_info).frame, 4));       \
+X}
+X\f
+X/* Things needed for making the inferior call functions.  */
+X
+X/* Push an empty stack frame, to record the current PC, etc.  */
+X
+X#define PUSH_DUMMY_FRAME \
+X{ register CORE_ADDR sp = read_register (SP_REGNUM);\
+X  register int regnum;                                    \
+X  sp = push_word (sp, read_register (PC_REGNUM));   \
+X  sp = push_word (sp, read_register (FP_REGNUM));   \
+X  write_register (FP_REGNUM, sp);                 \
+X  for (regnum = 0; regnum < 8; regnum++)  \
+X    sp = push_word (sp, read_register (regnum));    \
+X  write_register (SP_REGNUM, sp);                     \
+X}
+X
+X/* Discard from the stack the innermost frame, restoring all registers.  */
+X
+X#define POP_FRAME  \
+X{ register CORE_ADDR fp = read_register (FP_REGNUM);           \
+X  register int regnum;                                                 \
+X  struct frame_saved_regs fsr;                                         \
+X  struct frame_info fi;                                                \
+X  fi = get_frame_info (fp);                                    \
+X  get_frame_saved_regs (&fi, &fsr);                            \
+X  for (regnum = 0; regnum < 8; regnum++)                       \
+X    if (fsr.regs[regnum])                                      \
+X      write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+X  write_register (FP_REGNUM, read_memory_integer (fp, 4));     \
+X  write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));   \
+X  write_register (SP_REGNUM, fp + 8);                          \
+X}
+X
+X/* This sequence of words is the instructions
+X     enter    0xff,0          82 ff 00
+X     jsr      @0x00010203     7f ae c0 01 02 03
+X     adjspd   0x69696969      7f a5 01 02 03 04
+X     bpt                      f2
+X   Note this is 16 bytes.  */
+X
+X#define CALL_DUMMY { 0x7f00ff82, 0x0201c0ae, 0x01a57f03, 0xf2040302 }
+X
+X#define CALL_DUMMY_START_OFFSET       3
+X#define CALL_DUMMY_LENGTH     16
+X#define CALL_DUMMY_ADDR               5
+X#define CALL_DUMMY_NARGS      11
+X
+X/* Insert the specified number of args and function address
+X   into a call sequence of the above form stored at DUMMYNAME.  */
+X
+X#define FIX_CALL_DUMMY(dummyname, fun, nargs)                 \
+X{                                                             \
+X      int     flipped;                                        \
+X      flipped = fun | 0xc0000000;                             \
+X      flip_bytes (&flipped, 4);                               \
+X      *((int *) (((char *) dummyname)+CALL_DUMMY_ADDR)) = flipped;    \
+X      flipped = - nargs * 4;                                  \
+X      flip_bytes (&flipped, 4);                               \
+X      *((int *) (((char *) dummyname)+CALL_DUMMY_NARGS)) = flipped;   \
+X}
+X\f
+X#ifdef notdef
+X/* Interface definitions for kernel debugger KDB.  */
+X
+X/* Map machine fault codes into signal numbers.
+X   First subtract 0, divide by 4, then index in a table.
+X   Faults for which the entry in this table is 0
+X   are not handled by KDB; the program's own trap handler
+X   gets to handle then.  */
+X
+X#define FAULT_CODE_ORIGIN 0
+X#define FAULT_CODE_UNITS 4
+X#define FAULT_TABLE    \
+X{ 0, SIGKILL, SIGSEGV, 0, 0, 0, 0, 0, \
+X  0, 0, SIGTRAP, SIGTRAP, 0, 0, 0, 0, \
+X  0, 0, 0, 0, 0, 0, 0, 0}
+X
+X/* Start running with a stack stretching from BEG to END.
+X   BEG and END should be symbols meaningful to the assembler.
+X   This is used only for kdb.  */
+X
+X#define INIT_STACK(beg, end)  \
+X{ asm (".globl end");         \
+X  asm ("movl $ end, sp");      \
+X  asm ("clrl fp"); }
+X
+X/* Push the frame pointer register on the stack.  */
+X#define PUSH_FRAME_PTR        \
+X  asm ("pushl fp");
+X
+X/* Copy the top-of-stack to the frame pointer register.  */
+X#define POP_FRAME_PTR  \
+X  asm ("movl (sp), fp");
+X
+X/* After KDB is entered by a fault, push all registers
+X   that GDB thinks about (all NUM_REGS of them),
+X   so that they appear in order of ascending GDB register number.
+X   The fault code will be on the stack beyond the last register.  */
+X
+X#define PUSH_REGISTERS        \
+X{ asm ("pushl 8(sp)");        \
+X  asm ("pushl 8(sp)");        \
+X  asm ("pushal 0x14(sp)");    \
+X  asm ("pushr $037777"); }
+X
+X/* Assuming the registers (including processor status) have been
+X   pushed on the stack in order of ascending GDB register number,
+X   restore them and return to the address in the saved PC register.  */
+X
+X#define POP_REGISTERS      \
+X{ asm ("popr $037777");    \
+X  asm ("subl2 $8,(sp)");   \
+X  asm ("movl (sp),sp");    \
+X  asm ("rei"); }
+X#endif
+SHAR_EOF
+sed 's/^X//' << 'SHAR_EOF' > n32k-opcode.h
+X/* n32k-opcode.h */
+X
+X#ifndef n32k_opcodeT
+X#define n32k_opcodeT int
+X#endif /* no n32k_opcodeT */
+X
+Xstruct not_wot                        /* n32k opcode table: wot to do with this */
+X                              /* particular opcode */
+X{
+X      int             obits;  /* number of opcode bits */
+X      int             ibits;  /* number of instruction bits */
+X      n32k_opcodeT    code;   /* op-code (may be > 8 bits!) */
+X      char            *args;  /* how to compile said opcode */
+X};
+X
+Xstruct not                    /* n32k opcode text */
+X{
+X  char *            name;     /* opcode name: lowercase string  [key]  */
+X  struct not_wot    detail;   /* rest of opcode table          [datum] */
+X};
+X
+X/* F : 32 bit float
+X * L : 64 bit float
+X * B : byte
+X * W : word
+X * D : double-word
+X * Q : quad-word
+X * d : displacement
+X * q : quick
+X * i : immediate (8 bits)
+X * r : register number (3 bits)
+X * p : displacement - pc relative addressing
+X*/
+Xstatic struct not
+Xnotstrs[] =
+X{
+X{ "absf",     14,24,  0x35be, "1F2F" },
+X{ "absl",     14,24,  0x34be, "1L2L" },
+X{ "absb",     14,24,  0x304e, "1B2B" },
+X{ "absw",     14,24,  0x314e, "1W2W" },
+X{ "absd",     14,24,  0x334e, "1D2D" },
+X{ "acbb",      7,16,  0x4c,   "2B1q3p" },
+X{ "addf",     14,24,  0x01be, "1F2F" },
+X{ "addl",     14,24,  0x00be, "1L2L" },
+X{ "addb",      6,16,  0x00,   "1B2B" },
+X{ "addw",      6,16,  0x01,   "1W2W" },
+X{ "addd",      6,16,  0x03,   "1D2D" },
+X{ "addcb",     6,16,  0x10,   "1B2B" },
+X{ "addcw",     6,16,  0x11,   "1W2W" },
+X{ "addcd",     6,16,  0x13,   "1D2D" },
+X{ "addpb",    14,24,  0x3c4e, "1B2B" },
+X{ "addpw",    14,24,  0x3d4e, "1W2W" },
+X{ "addpd",    14,24,  0x3f4e, "1D2D" },
+X{ "addqb",     7,16,  0x0c,   "2B1q" },
+X{ "addqw",     7,16,  0x0d,   "2W1q" },
+X{ "addqd",     7,16,  0x0f,   "2D1q" },
+X{ "addr",      6,16,  0x27,   "1D2D" },
+X{ "adjspb",   11,16,  0x057c, "1B" },
+X{ "adjspw",   11,16,  0x057d, "1W" },
+X{ "adjspd",   11,16,  0x057f, "1D" },
+X{ "andb",      6,16,  0x28,   "1B2B" },
+X{ "andw",      6,16,  0x29,   "1W2W" },
+X{ "andd",      6,16,  0x2b,   "1D2D" },
+X{ "ashb",     14,24,  0x044e, "1B2B" },
+X{ "ashw",     14,24,  0x054e, "1B2W" },
+X{ "ashd",     14,24,  0x074e, "1B2D" },
+X{ "beq",       8,8,   0x0a,   "1p" },
+X{ "bne",       8,8,   0x1a,   "1p" },
+X{ "bcs",       8,8,   0x2a,   "1p" },
+X{ "bcc",       8,8,   0x3a,   "1p" },
+X{ "bhi",       8,8,   0x4a,   "1p" },
+X{ "bls",       8,8,   0x5a,   "1p" },
+X{ "bgt",       8,8,   0x6a,   "1p" },
+X{ "ble",       8,8,   0x7a,   "1p" },
+X{ "bfs",       8,8,   0x8a,   "1p" },
+X{ "bfc",       8,8,   0x9a,   "1p" },
+X{ "blo",       8,8,   0xaa,   "1p" },
+X{ "bhs",       8,8,   0xba,   "1p" },
+X{ "blt",       8,8,   0xca,   "1p" },
+X{ "bge",       8,8,   0xda,   "1p" },
+X{ "bicb",      6,16,  0x08,   "1B2B" },
+X{ "bicw",      6,16,  0x09,   "1W2W" },
+X{ "bicd",      6,16,  0x0b,   "1D2D" },
+X{ "bicpsrb",  11,16,  0x17c,  "1B" },
+X{ "bicpsrw",  11,16,  0x17d,  "1W" },
+X{ "bispsrb",  11,16,  0x37c,  "1B" },
+X{ "bispsrw",  11,16,  0x37d,  "1W" },
+X{ "bpt",       8,8,   0xf2,   "" },
+X{ "br",                8,8,   0xea,   "1p" },
+X{ "bsr",       8,8,   0x02,   "1p" },
+X{ "caseb",    11,16,  0x77c,  "1B" },
+X{ "casew",    11,16,  0x77d,  "1W" },
+X{ "cased",    11,16,  0x77f,  "1D" },
+X{ "cbitb",    14,24,  0x084e, "1B2D" },
+X{ "cbitw",    14,24,  0x094e, "1W2D" },
+X{ "cbitd",    14,24,  0x0b4e, "1D2D" },
+X{ "cbitib",   14,24,  0x0c4e, "1B2D" },
+X{ "cbitiw",   14,24,  0x0d4e, "1W2D" },
+X{ "cbitid",   14,24,  0x0f4e, "1D2D" },
+X{ "checkb",   11,24,  0x0ee,  "2A3B1r" },
+X{ "checkw",   11,24,  0x1ee,  "2A3B1r" },
+X{ "checkd",   11,24,  0x3ee,  "2A3D1r" },
+X{ "cmpf",     14,24,  0x09be, "1F2F" },
+X{ "cmpl",     14,24,  0x08be, "1L2L" },
+X{ "cmpb",      6,16,  0x04,   "1B2B" },
+X{ "cmpw",      6,16,  0x05,   "1W2W" },
+X{ "cmpd",      6,16,  0x07,   "1D2D" },
+X{ "cmpmb",    14,24,  0x04ce, "1D2D3d" },
+X{ "cmpmw",    14,24,  0x05ce, "1D2D3d" },
+X{ "cmpmd",    14,24,  0x07ce, "1D2D3d" },
+X{ "cmpqb",     7,16,  0x1c,   "2B1q" },
+X{ "cmpqw",     7,16,  0x1d,   "2W1q" },
+X{ "cmpqd",     7,16,  0x1f,   "2D1q" },
+X{ "cmpsb",    16,16,  0x040e, "i" },
+X{ "cmpsw",    16,16,  0x050e, "i" },
+X{ "cmpsd",    16,16,  0x070e, "i" },
+X{ "cmpst",    16,16,  0x840e, "i" },
+X{ "comb",     14,24,  0x344e, "1B2B" },
+X{ "comw",     14,24,  0x354e, "1W2W" },
+X{ "comd",     14,24,  0x374e, "1D2D" },
+X{ "cvtp",     11,24,  0x036e, "2D3D1r" },
+X{ "cxp",       8,8,   0x22,   "1p" },
+X{ "cxpd",     11,16,  0x07f,  "1D" },
+X{ "deib",     14,24,  0x2cce, "1B2W" },
+X{ "deiw",     14,24,  0x2cce, "1W2D" },
+X{ "deid",     14,24,  0x2cce, "1D2Q" },
+X{ "dia",       8,8,   0xc2,   "" },
+X{ "divf",     14,24,  0x21be, "1F2F" },
+X{ "divl",     14,24,  0x20be, "1L2L" },
+X{ "divb",     14,24,  0x3cce, "1B2B" },
+X{ "divw",     14,24,  0x3dce, "1W2W" },
+X{ "divd",     14,24,  0x3fce, "1D2D" },
+X{ "enter",     8,8,   0x82,   "1i2d" },
+X{ "exit",      8,8,   0x92,   "1i" },
+X{ "extb",     11,24,  0x02e,  "2D3B1r4d" },
+X{ "extw",     11,24,  0x12e,  "2D3W1r4d" },
+X{ "extd",     11,24,  0x32e,  "2D3D1r4d" },
+X{ "extsb",    14,24,  0x0cce, "1D2B3i" },
+X{ "extsw",    14,24,  0x0dce, "1D2W3i" },
+X{ "extsd",    14,24,  0x0fce, "1D2D3i" },
+X{ "ffsb",     14,24,  0x046e, "1B2B" },
+X{ "ffsw",     14,24,  0x056e, "1W2B" },
+X{ "ffsd",     14,24,  0x076e, "1D2B" },
+X{ "flag",      8,8,   0xd2,   "" },
+X{ "floorfb",  14,24,  0x3c3e, "1F2B" },
+X{ "floorfw",  14,24,  0x3d3e, "1F2W" },
+X{ "floorfd",  14,24,  0x3f3e, "1F2D" },
+X{ "floorlb",  14,24,  0x383e, "1L2B" },
+X{ "floorlw",  14,24,  0x393e, "1L2W" },
+X{ "floorld",  14,24,  0x3b3e, "1L2D" },
+X{ "ibitb",    14,24,  0x384e, "1B2D" },
+X{ "ibitw",    14,24,  0x394e, "1W2D" },
+X{ "ibitd",    14,24,  0x3b4e, "1D2D" },
+X{ "indexb",   11,24,  0x42e,  "2B3B1r" },
+X{ "indexw",   11,24,  0x52e,  "2W3W1r" },
+X{ "indexd",   11,24,  0x72e,  "2D3D1r" },
+X{ "insb",     11,24,  0x0ae,  "2B3B1r4d" },
+X{ "insw",     11,24,  0x1ae,  "2W3W1r4d" },
+X{ "insd",     11,24,  0x3ae,  "2D3D1r4d" },
+X{ "inssb",    14,24,  0x08ce, "1B2D3i" },
+X{ "inssw",    14,24,  0x09ce, "1W2D3i" },
+X{ "inssd",    14,24,  0x0bce, "1D2D3i" },
+X{ "jsr",      11,16,  0x67f,  "1A" },
+X{ "jump",     11,16,  0x27f,  "1A" },
+X{ "lfsr",     19,24,  0x00f3e,"1D" },
+X{ "lmr",      15,24,  0x0b1e, "2D1q" },
+X{ "lprb",      7,16,  0x6c,   "2B1q" },
+X{ "lprw",      7,16,  0x6d,   "2W1q" },
+X{ "lprd",      7,16,  0x6f,   "2D1q" },
+X{ "lshb",     14,24,  0x144e, "1B2B" },
+X{ "lshw",     14,24,  0x154e, "1B2W" },
+X{ "lshd",     14,24,  0x174e, "1B2D" },
+X{ "meib",     14,24,  0x24ce, "1B2W" },
+X{ "meiw",     14,24,  0x25ce, "1W2D" },
+X{ "meid",     14,24,  0x27ce, "1D2Q" },
+X{ "modb",     14,24,  0x38ce, "1B2B" },
+X{ "modw",     14,24,  0x39ce, "1W2W" },
+X{ "modd",     14,24,  0x3bce, "1D2D" },
+X{ "movf",     14,24,  0x05be, "1F2F" },
+X{ "movl",     14,24,  0x04be, "1L2L" },
+X{ "movb",      6,16,  0x14,   "1B2B" },
+X{ "movw",      6,16,  0x15,   "1W2W" },
+X{ "movd",      6,16,  0x17,   "1D2D" },
+X{ "movbf",    14,24,  0x043e, "1B2F" },
+X{ "movwf",    14,24,  0x053e, "1W2F" },
+X{ "movdf",    14,24,  0x073e, "1D2F" },
+X{ "movbl",    14,24,  0x003e, "1B2L" },
+X{ "movwl",    14,24,  0x013e, "1W2L" },
+X{ "movdl",    14,24,  0x033e, "1D2L" },
+X{ "movfl",    14,24,  0x1b3e, "1F2L" },
+X{ "movlf",    14,24,  0x163e, "1L2F" },
+X{ "movmb",    14,24,  0x00ce, "1D2D3d" },
+X{ "movmw",    14,24,  0x00de, "1D2D3d" },
+X{ "movmd",    14,24,  0x00fe, "1D2D3d" },
+X{ "movqb",     7,16,  0x5c,   "2B1q" },
+X{ "movqw",     7,16,  0x5d,   "2B1q" },
+X{ "movqd",     7,16,  0x5f,   "2B1q" },
+X{ "movsb",    16,16,  0x000e, "i" },
+X{ "movsw",    16,16,  0x010e, "i" },
+X{ "movsd",    16,16,  0x030e, "i" },
+X{ "movst",    16,16,  0x800e, "i" },
+X{ "movsub",   14,24,  0x0cae, "1A1A" },
+X{ "movsuw",   14,24,  0x0dae, "1A1A" },
+X{ "movsud",   14,24,  0x0fae, "1A1A" },
+X{ "movusb",   14,24,  0x1cae, "1A1A" },
+X{ "movusw",   14,24,  0x1dae, "1A1A" },
+X{ "movusd",   14,24,  0x1fae, "1A1A" },
+X{ "movxbd",   14,24,  0x1cce, "1B2D" },
+X{ "movxwd",   14,24,  0x1dce, "1W2D" },
+X{ "movxbw",   14,24,  0x10ce, "1B2W" },
+X{ "movzbd",   14,24,  0x18ce, "1B2D" },
+X{ "movzwd",   14,24,  0x19ce, "1W2D" },
+X{ "movzbw",   14,24,  0x14ce, "1B2W" },
+X{ "mulf",     14,24,  0x31be, "1F2F" },
+X{ "mull",     14,24,  0x30be, "1L2L" },
+X{ "mulb",     14,24,  0x20ce, "1B2B" },
+X{ "mulw",     14,24,  0x21ce, "1W2W" },
+X{ "muld",     14,24,  0x23ce, "1D2D" },
+X{ "negf",     14,24,  0x15be, "1F2F" },
+X{ "negl",     14,24,  0x14be, "1L2L" },
+X{ "negb",     14,24,  0x204e, "1B2B" },
+X{ "negw",     14,24,  0x214e, "1W2W" },
+X{ "negd",     14,24,  0x234e, "1D2D" },
+X{ "nop",       8,8,   0xa2,   "" },
+X{ "notb",     14,24,  0x244e, "1B2B" },
+X{ "notw",     14,24,  0x254e, "1W2W" },
+X{ "notd",     14,24,  0x274e, "1D2D" },
+X{ "orb",       6,16,  0x18,   "1B1B" },
+X{ "orw",       6,16,  0x19,   "1W1W" },
+X{ "ord",       6,16,  0x1b,   "1D1D" },
+X{ "quob",     14,24,  0x30ce, "1B2B" },
+X{ "quow",     14,24,  0x31ce, "1W2W" },
+X{ "quod",     14,24,  0x33ce, "1D2D" },
+X{ "rdval",    19,24,  0x0031e,"1A" },
+X{ "remb",     14,24,  0x34ce, "1B2B" },
+X{ "remw",     14,24,  0x35ce, "1W2W" },
+X{ "remd",     14,24,  0x37ce, "1D2D" },
+X{ "restore",   8,8,   0x72,   "1i" },
+X{ "ret",       8,8,   0x12,   "1d" },
+X{ "reti",      8,8,   0x52,   "" },
+X{ "rett",      8,8,   0x42,   "" },
+X{ "rotb",     14,24,  0x004e, "1B2B" },
+X{ "rotw",     14,24,  0x014e, "1B2W" },
+X{ "rotd",     14,24,  0x034e, "1B2D" },
+X{ "roundfb",  14,24,  0x243e, "1F2B" },
+X{ "roundfw",  14,24,  0x253e, "1F2W" },
+X{ "roundfd",  14,24,  0x273e, "1F2D" },
+X{ "roundlb",  14,24,  0x203e, "1L2B" },
+X{ "roundlw",  14,24,  0x213e, "1L2W" },
+X{ "roundld",  14,24,  0x233e, "1L2D" },
+X{ "rxp",       8,8,   0x32,   "1d" },
+X{ "sCONDb",    7,16,  0x3c,   "2B1q" },
+X{ "sCONDw",    7,16,  0x3d,   "2D1q" },
+X{ "sCONDd",    7,16,  0x3f,   "2D1q" },
+X{ "save",      8,8,   0x62,   "1i" },
+X{ "sbitb",    14,24,  0x184e, "1B2A" },
+X{ "sbitw",    14,24,  0x194e, "1W2A" },
+X{ "sbitd",    14,24,  0x1b4e, "1D2A" },
+X{ "sbitib",   14,24,  0x1c4e, "1B2A" },
+X{ "sbitiw",   14,24,  0x1d4e, "1W2A" },
+X{ "sbitid",   14,24,  0x1f4e, "1D2A" },
+X{ "setcfg",   15,24,  0x0b0e, "5D1q" },
+X{ "sfsr",     14,24,  0x673e, "5D1D" },
+X{ "skpsb",    16,16,  0x0c0e, "i" },
+X{ "skpsw",    16,16,  0x0d0e, "i" },
+X{ "skpsd",    16,16,  0x0f0e, "i" },
+X{ "skpst",    16,16,  0x8c0e, "i" },
+X{ "smr",      15,24,  0x0f1e, "2D1q" },
+X{ "sprb",      7,16,  0x2c,   "2B1q" },
+X{ "sprw",      7,16,  0x2d,   "2W1q" },
+X{ "sprd",      7,16,  0x2f,   "2D1q" },
+X{ "subf",     14,24,  0x11be, "1F2F" },
+X{ "subl",     14,24,  0x10be, "1L2L" },
+X{ "subb",      6,16,  0x20,   "1B2B" },
+X{ "subw",      6,16,  0x21,   "1W2W" },
+X{ "subd",      6,16,  0x23,   "1D2D" },
+X{ "subcb",     6,16,  0x30,   "1B2B" },
+X{ "subcw",     6,16,  0x31,   "1W2W" },
+X{ "subcd",     6,16,  0x33,   "1D2D" },
+X{ "subpb",    14,24,  0x2c4e, "1B2B" },
+X{ "subpw",    14,24,  0x2d4e, "1W2W" },
+X{ "subpd",    14,24,  0x2f4e, "1D2D" },
+X{ "svc",       8,8,   0xe2,   "2i1i" }, /* not really, but unix uses it */
+X{ "tbitb",     6,16,  0x34,   "1B2A" },
+X{ "tbitw",     6,16,  0x35,   "1W2A" },
+X{ "tbitd",     6,16,  0x37,   "1D2A" },
+X{ "truncfb",  14,24,  0x2c3e, "1F2B" },
+X{ "truncfw",  14,24,  0x2d3e, "1F2W" },
+X{ "truncfd",  14,24,  0x2f3e, "1F2D" },
+X{ "trunclb",  14,24,  0x283e, "1L2B" },
+X{ "trunclw",  14,24,  0x293e, "1L2W" },
+X{ "truncld",  14,24,  0x2b3e, "1L2D" },
+X{ "wait",      8,8,   0xb2,   "" },
+X{ "wrval",    19,24,  0x0071e,"1A" },
+X{ "xorb",      6,16,  0x38,   "1B2B" },
+X{ "xorw",      6,16,  0x39,   "1W2W" },
+X{ "xord",      6,16,  0x3b,   "1D2D" },
+X};                            /* notstrs */
+X
+X/* end: n32k.opcode.h */
+X
+X# define      MAX_ARGS        4
+X# define      ARG_LEN         50
+SHAR_EOF
+sed 's/^X//' << 'SHAR_EOF' > n32k-pinsn.c
+X/* Print 32000 instructions for GDB, the GNU debugger.
+X   Copyright (C) 1986 Free Software Foundation, Inc.
+X
+XGDB is distributed in the hope that it will be useful, but WITHOUT ANY
+XWARRANTY.  No author or distributor accepts responsibility to anyone
+Xfor the consequences of using it or for whether it serves any
+Xparticular purpose or works at all, unless he says so in writing.
+XRefer to the GDB General Public License for full details.
+X
+XEveryone is granted permission to copy, modify and redistribute GDB,
+Xbut only under the conditions described in the GDB General Public
+XLicense.  A copy of this license is supposed to have been given to you
+Xalong with GDB so you can know your rights and responsibilities.  It
+Xshould be in a file named COPYING.  Among other things, the copyright
+Xnotice and this notice must be preserved on all copies.
+X
+XIn other words, go ahead and share GDB, but don't try to stop
+Xanyone else from sharing it farther.  Help stamp out software hoarding!
+X*/
+X
+X#include <stdio.h>
+X
+X#include "defs.h"
+X#include "param.h"
+X#include "symtab.h"
+X#include "n32k-opcode.h"
+X
+X/* 32000 instructions are never longer than this.  */
+X#define MAXLEN 62
+X
+X/* Number of elements in the opcode table.  */
+X#define NOPCODES (sizeof notstrs / sizeof notstrs[0])
+X
+Xextern char *reg_names[];
+X
+X#define NEXT_IS_ADDR  '|'
+X
+X/*
+X * extract "count" bits starting "offset" bits
+X * into buffer
+X */
+X
+Xint
+Xbit_extract (buffer, offset, count)
+Xchar  *buffer;
+Xint   offset;
+Xint   count;
+X{
+X      int     result;
+X      int     mask;
+X      int     bit;
+X
+X      buffer += offset >> 3;
+X      offset &= 7;
+X      bit = 1;
+X      result = 0;
+X      while (count--) {
+X              if ((*buffer & (1 << offset)))
+X                      result |= bit;
+X              if (++offset == 8) {
+X                      offset = 0;
+X                      buffer++;
+X              }
+X              bit <<= 1;
+X      }
+X      return result;
+X}
+X
+Xdouble
+Xdbit_extract (buffer, offset, count)
+X{
+X      union {
+X              struct {
+X                      int     low, high;
+X              } ival;
+X              double  dval;
+X      } foo;
+X
+X      foo.ival.low = bit_extract (buffer, offset, 32);
+X      foo.ival.high = bit_extract (buffer, offset+32, 32);
+X      return foo.dval;
+X}
+X
+Xsign_extend (value, bits)
+X{
+X      value = value & ((1 << bits) - 1);
+X      return (value & (1 << (bits-1))) ?
+X              (value | (~((1 << bits) - 1)))
+X              : value;
+X}
+X
+Xflip_bytes (ptr, count)
+Xchar  *ptr;
+Xint   count;
+X{
+X      char    tmp;
+X
+X      while (count > 0) {
+X              tmp = *ptr;
+X              ptr[0] = ptr[count-1];
+X              ptr[count-1] = tmp;
+X              ptr++;
+X              count -= 2;
+X      }
+X}
+X
+X\f
+X/* Print the 32000 instruction at address MEMADDR in debugged memory,
+X   on STREAM.  Returns length of the instruction, in bytes.  */
+X
+Xint
+Xprint_insn (memaddr, stream)
+XCORE_ADDR memaddr;
+XFILE *stream;
+X{
+X      unsigned char buffer[MAXLEN];
+X      register int i;
+X      register unsigned char *p;
+X      register char *d;
+X      unsigned short  first_word;
+X      int     gen, disp;
+X      int     ioffset;        /* bits into instruction */
+X      int     aoffset;        /* bits into arguments */
+X      char    arg_bufs[MAX_ARGS+1][ARG_LEN];
+X      int     argnum;
+X      int     maxarg;
+X
+X      read_memory (memaddr, buffer, MAXLEN);
+X
+X      first_word = *(unsigned short *) buffer;
+X      for (i = 0; i < NOPCODES; i++) {
+X              if ((first_word & ((1 << notstrs[i].detail.obits) - 1)) ==
+X                  notstrs[i].detail.code)
+X                      break;
+X      }
+X
+X      /* Handle undefined instructions.  */
+X      if (i == NOPCODES) {
+X              fprintf (stream, "0%o", buffer[0]);
+X              return 1;
+X      }
+X
+X      fprintf (stream, "%s", notstrs[i].name);
+X
+X      ioffset = notstrs[i].detail.ibits;
+X      aoffset = notstrs[i].detail.ibits;
+X      d = notstrs[i].detail.args;
+X
+X      if (*d) {
+X              fputc ('\t', stream);
+X
+X              maxarg = 0;
+X              while (*d)
+X              {
+X                      argnum = *d - '1';
+X                      d++;
+X                      if (argnum > maxarg && argnum < MAX_ARGS)
+X                              maxarg = argnum;
+X                      ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
+X                                      memaddr, arg_bufs[argnum]);
+X                      d++;
+X              }
+X              for (argnum = 0; argnum <= maxarg; argnum++) {
+X                      CORE_ADDR       addr;
+X                      char            *ch, *index ();
+X                      for (ch = arg_bufs[argnum]; *ch;) {
+X                              if (*ch == NEXT_IS_ADDR) {
+X                                      ++ch;
+X                                      addr = atoi (ch);
+X                                      print_address (addr, stream);
+X                                      while (*ch && *ch != NEXT_IS_ADDR)
+X                                              ++ch;
+X                                      if (*ch)
+X                                              ++ch;
+X                              } else
+X                                      putc (*ch++, stream);
+X                      }
+X                      if (argnum < maxarg)
+X                              fprintf (stream, ", ");
+X              }
+X      }
+X      return aoffset / 8;
+X}
+X
+Xprint_insn_arg (d, ioffset, aoffsetp, buffer, addr, result)
+Xchar  d;
+Xint   ioffset, *aoffsetp;
+Xchar  *buffer;
+XCORE_ADDR addr;
+Xchar  *result;
+X{
+X      int     addr_mode;
+X      float   Fvalue;
+X      double  Lvalue;
+X      int     Ivalue;
+X      int     disp1, disp2;
+X      int     index;
+X
+X      switch (d) {
+X      case 'F':
+X      case 'L':
+X      case 'B':
+X      case 'W':
+X      case 'D':
+X      case 'A':
+X              addr_mode = bit_extract (buffer, ioffset-5, 5);
+X              ioffset -= 5;
+X              switch (addr_mode) {
+X              case 0x0: case 0x1: case 0x2: case 0x3:
+X              case 0x4: case 0x5: case 0x6: case 0x7:
+X                      sprintf (result, "r%d", addr_mode);
+X                      break;
+X              case 0x8: case 0x9: case 0xa: case 0xb:
+X              case 0xc: case 0xd: case 0xe: case 0xf:
+X                      disp1 = get_displacement (buffer, aoffsetp);
+X                      sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
+X                      break;
+X              case 0x10:
+X              case 0x11:
+X              case 0x12:
+X                      disp1 = get_displacement (buffer, aoffsetp);
+X                      disp2 = get_displacement (buffer, aoffsetp);
+X                      sprintf (result, "%d(%d(%s))", disp2, disp1,
+X                              addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb");
+X                      break;
+X              case 0x13:
+X                      sprintf (result, "reserved");
+X                      break;
+X              case 0x14:
+X                      switch (d) {
+X                      case 'B':
+X                              Ivalue = bit_extract (buffer, *aoffsetp, 8);
+X                              Ivalue = sign_extend (Ivalue, 8);
+X                              *aoffsetp += 8;
+X                              sprintf (result, "$%d", Ivalue);
+X                              break;
+X                      case 'W':
+X                              Ivalue = bit_extract (buffer, *aoffsetp, 16);
+X                              flip_bytes (&Ivalue, 2);
+X                              *aoffsetp += 16;
+X                              Ivalue = sign_extend (Ivalue, 16);
+X                              sprintf (result, "$%d", Ivalue);
+X                              break;
+X                      case 'D':
+X                              Ivalue = bit_extract (buffer, *aoffsetp, 32);
+X                              flip_bytes (&Ivalue, 4);
+X                              *aoffsetp += 32;
+X                              sprintf (result, "$%d", Ivalue);
+X                              break;
+X                      case 'A':
+X                              Ivalue = bit_extract (buffer, *aoffsetp, 32);
+X                              flip_bytes (&Ivalue, 4);
+X                              *aoffsetp += 32;
+X                              sprintf (result, "$|%d|", Ivalue);
+X                              break;
+X                      case 'F':
+X                              Fvalue = (float) bit_extract
+X                                      (buffer, *aoffsetp, 32);
+X                              flip_bytes (&Fvalue, 4);
+X                              *aoffsetp += 32;
+X                              sprintf (result, "$%g", Fvalue);
+X                              break;
+X                      case 'L':
+X                              Lvalue = dbit_extract
+X                                      (buffer, *aoffsetp, 64);
+X                              flip_bytes (&Lvalue, 8);
+X                              *aoffsetp += 64;
+X                              sprintf (result, "$%g", Lvalue);
+X                              break;
+X                      }
+X                      break;
+X              case 0x15:
+X                      disp1 = get_displacement (buffer, aoffsetp);
+X                      sprintf (result, "@|%d|", disp1);
+X                      break;
+X              case 0x16:
+X                      disp1 = get_displacement (buffer, aoffsetp);
+X                      disp2 = get_displacement (buffer, aoffsetp);
+X                      sprintf (result, "EXT(%d) + %d", disp1, disp2);
+X                      break;
+X              case 0x17:
+X                      sprintf (result, "tos");
+X                      break;
+X              case 0x18:
+X                      disp1 = get_displacement (buffer, aoffsetp);
+X                      sprintf (result, "%d(fp)", disp1);
+X                      break;
+X              case 0x19:
+X                      disp1 = get_displacement (buffer, aoffsetp);
+X                      sprintf (result, "%d(sp)", disp1);
+X                      break;
+X              case 0x1a:
+X                      disp1 = get_displacement (buffer, aoffsetp);
+X                      sprintf (result, "%d(sb)", disp1);
+X                      break;
+X              case 0x1b:
+X                      disp1 = get_displacement (buffer, aoffsetp);
+X                      sprintf (result, "|%d|", addr + disp1);
+X                      break;
+X              case 0x1c:
+X              case 0x1d:
+X              case 0x1e:
+X              case 0x1f:
+X                      index = bit_extract (buffer, *aoffsetp, 8);
+X                      *aoffsetp += 8;
+X                      print_insn_arg (d, *aoffsetp, aoffsetp, buffer, addr,
+X                              result);
+X                      {
+X                              static char     *ind[] = {"b", "w", "d", "q"};
+X                              char            *off;
+X
+X                              off = result + strlen (result);
+X                              sprintf (off, "[r%d:%s]", index & 7,
+X                                      ind[addr_mode & 3]);
+X                      }
+X                      break;
+X              }
+X              break;
+X      case 'q':
+X              Ivalue = bit_extract (buffer, ioffset-4, 4);
+X              Ivalue = sign_extend (Ivalue, 4);
+X              sprintf (result, "%d", Ivalue);
+X              ioffset -= 4;
+X              break;
+X      case 'r':
+X              Ivalue = bit_extract (buffer, ioffset-3, 3);
+X              sprintf (result, "r%d", Ivalue&7);
+X              ioffset -= 3;
+X              break;
+X      case 'd':
+X              sprintf (result, "%d", get_displacement (buffer, aoffsetp));
+X              break;
+X      case 'p':
+X              sprintf (result, "%c%d%c", NEXT_IS_ADDR, addr +
+X                      get_displacement (buffer, aoffsetp),
+X                      NEXT_IS_ADDR);
+X              break;
+X      case 'i':
+X              Ivalue = bit_extract (buffer, *aoffsetp, 8);
+X              *aoffsetp += 8;
+X              sprintf (result, "0x%x", Ivalue);
+X              break;
+X      }
+X      return ioffset;
+X}
+X
+Xget_displacement (buffer, aoffsetp)
+Xchar  *buffer;
+Xint   *aoffsetp;
+X{
+X      int     Ivalue;
+X
+X      Ivalue = bit_extract (buffer, *aoffsetp, 8);
+X      switch (Ivalue & 0xc0) {
+X      case 0x00:
+X      case 0x40:
+X              Ivalue = sign_extend (Ivalue, 7);
+X              *aoffsetp += 8;
+X              break;
+X      case 0x80:
+X              Ivalue = bit_extract (buffer, *aoffsetp, 16);
+X              flip_bytes (&Ivalue, 2);
+X              Ivalue = sign_extend (Ivalue, 14);
+X              *aoffsetp += 16;
+X              break;
+X      case 0xc0:
+X              Ivalue = bit_extract (buffer, *aoffsetp, 32);
+X              flip_bytes (&Ivalue, 4);
+X              Ivalue = sign_extend (Ivalue, 30);
+X              *aoffsetp += 32;
+X              break;
+X      }
+X      return Ivalue;
+X}
+X/*
+X * return the number of locals in the current frame given a pc
+X * pointing to the enter instruction
+X */
+Xn32k_localcount (enter_pc)
+XCORE_ADDR     enter_pc;
+X{
+X      int     localtype, localcount;
+X
+X      localtype = read_memory_integer (enter_pc+2, 1);
+X      if ((localtype & 0x80) == 0)
+X              localcount = localtype;
+X      else if ((localtype & 0xc0) == 0x80)
+X              localcount =
+X                  ((read_memory_integer (enter_pc+2, 1) & ~0xc0) << 8) |
+X                  ((read_memory_integer (enter_pc+3, 1)));
+X      else
+X              localcount =
+X                  ((read_memory_integer (enter_pc+2, 1) & ~0xc0) << 24) |
+X                  ((read_memory_integer (enter_pc+3, 1)) << 16) |
+X                  ((read_memory_integer (enter_pc+4, 1)) << 8 ) |
+X                  ((read_memory_integer (enter_pc+5, 1)));
+X      return localcount;
+X}
+SHAR_EOF
+exit
+
diff --git a/gdb/=rt-ans2 b/gdb/=rt-ans2
new file mode 100644 (file)
index 0000000..cd5f9fa
--- /dev/null
@@ -0,0 +1,103 @@
+BABYL OPTIONS:
+Version: 5
+Labels:
+Note:   This is the header of an rmail file.
+Note:   If you are seeing it in rmail,
+Note:    it means the file has no messages in it.
+\1f\f
+1,answered,,
+Received: by PREP.AI.MIT.EDU; Tue, 26 May 87 14:03:00 EDT
+Received: by po2.andrew.cmu.edu (5.54/3.15) id <AA00274> for rms@PREP.AI.MIT.EDU; Tue, 26 May 87 13:12:52 EDT
+Received: via switchmail; Tue, 26 May 87 13:12:49 edt
+Received: FROM mooncrest VIA qmail
+          ID </cmu/common/mailqs/q004/QF.mooncrest.20b9cce3.d0134>;
+          Tue, 26 May 87 13:12:08 edt
+Received: FROM mooncrest VIA qmail
+          ID </cmu/itc/kazar/.Outgoing/QF.mooncrest.20b9ccb0.1b570>;
+          Tue, 26 May 87 13:11:14 edt
+Message-Id: <0UiQmky00UkA06w0Ci@andrew.cmu.edu>
+X-Trace: MS Version 3.24 on ibm032 host mooncrest, by kazar (71).
+Date: Tue, 26 May 87 13:11:12 edt
+From: kazar#@andrew.cmu.edu (Mike Kazar)
+To: rms@PREP.AI.MIT.EDU (Richard M. Stallman)
+Subject: Re: Fwd: RT diffs for gdb version 2.1
+Cc: zs01#@andrew.cmu.edu (Zalman Stern)
+In-Reply-To: <4UiN0ly00Vs8Njw0PC@andrew.cmu.edu>
+
+*** EOOH ***
+X-Trace: MS Version 3.24 on ibm032 host mooncrest, by kazar (71).
+Date: Tue, 26 May 87 13:11:12 edt
+From: kazar#@andrew.cmu.edu (Mike Kazar)
+To: rms@PREP.AI.MIT.EDU (Richard M. Stallman)
+Subject: Re: Fwd: RT diffs for gdb version 2.1
+Cc: zs01#@andrew.cmu.edu (Zalman Stern)
+In-Reply-To: <4UiN0ly00Vs8Njw0PC@andrew.cmu.edu>
+
+I'm afraid that neither of your proposed simplifications to the gdb RT port
+actually work.
+
+First, the trace table problem.  The fundamental problem is that gdb expects
+to be able to pass in a frame pointer and get that frame's parent.  This is
+the purpose of FRAME_CHAIN, a macro whose one parameter is the frame whose
+parent is desired.
+
+This is simply insufficient information with which to compute the preceding
+frame's address.  In order to truly appreciate how bad things are, let me
+describe the procedure involved in going from a set of saved registers
+(including the pc), say after a core dump occurs, to the address of the
+preceding frame.  I assure you that you'll be shocked by its complexity....
+
+I start off knowing only one thing: the PC of the guy who pushed the last
+stack frame.  At the time of a core dump, this is in the saved PC, and for
+other stack frames, it is in register R15 (the return address is put in R15
+by the procedure call sequence).  My first goal is to compute the frame
+register number!  Not the contents of the frame register, but the register
+number itself, because the RT calling convention lets you change frame
+pointers from procedure to procedure!  So, I scan for the trace table, based
+on the PC, and obtain a structure that gives the frame register number (for
+both of our C compilers, this is R13, but it doesn't have to be), the number
+of arguments to the procedure, the space used by the locals and the number of
+registers saved by the procedure prolog.  This enables me to take the frame
+pointer, compute the offset of the saved registers off of this frame pointer
+and essentially restore the registers to the state they were at the time this
+procedure was called.  R15 now contains *its* callers PC, and I can redo this
+procedure again to back up another frame.
+
+In essence, in order to compute the preceding frame's address, I need more
+than just the current frame's address.  I need the full machine state at the
+time of the call, including all of the registers since I don't know which one
+will even turn out to be the frame pointer for the preceding procedure.
+
+This is why I put in the frame caching code.  Note that even were I to assume
+that the frame pointer is always in R13 (and this is almost certainly a
+mistake; IBM will surely eventually come up with a compiler where the frame
+pointer is NOT r13), I still either need r15 or the PC (depending upon which
+frame we're dealing with) in order to compute the preceding frame address.
+
+As for the _foo v.s. _.foo issue, there are two problems.  First, we can not
+simply ignore _foo symbols, since an _foo symbol is only "junk" if there is
+(possibly later) an _.foo symbol.  We might be able to have the processing
+for the "_.foo" change the value in the symbol table placed under the name
+_foo.  I do not know if this will work, since I do not know what processing
+is done when a symbol is first encountered, and how much can be done a second
+time.  The second problem is that sometimes we need to see what is in the
+variable named _foo, and we can't if it actually refers to _.foo.  I
+personally might be willing to live with this loss of functionality, but
+other people probably would not.
+
+As for initialize.h, we simply have no guarantees that IBM won't again change
+the junk they stick in front of procedures in the text segment.  Already,
+depending upon which compiler (and we use both), pcc puts a funny string (and
+maybe an integer, too) in front of every procedure, while the metaware hc
+compiler puts a funny string in front of the first procedure in a file, but
+nothing in front of the others.  IBM has made it clear to us that they feel
+free to change this at any time, so I feel quite strongly that it would be a
+mistake to assume that they've finished playing around with junk at the start
+of the text.  BTW, for all I know, some of these magic text strings disappear
+when you compile with -O.  They certainly *should*.
+
+       Mike
+
+
+
+\1f
\ No newline at end of file
diff --git a/gdb/=rt-answers b/gdb/=rt-answers
new file mode 100644 (file)
index 0000000..b23cfee
--- /dev/null
@@ -0,0 +1,147 @@
+X-Trace: MS Version 3.24 on ibm032 host dublin.itc.cmu.edu, by zs01 (623).
+Date: Mon, 25 May 87 10:30:10 edt
+From: zs01#@andrew.cmu.edu (Zalman Stern)
+To: rms@PREP.AI.MIT.EDU (Richard M. Stallman)
+Subject: Re: RT diffs for gdb version 2.1
+Cc: kazar#@andrew.cmu.edu (Mike Kazar), zs01#@andrew.cmu.edu (Zalman Stern)
+In-Reply-To: <8705250107.AA13256@prep.ai.mit.edu>
+
+Richard,
+
+First I will cover the easy questions.
+
+Either of our fixes to environ.c (i.e. with respect to version 1.9 which was
+broken) will work. As I understand it, the intent of init_environ is to fill
+in the environment and leave a little extra space for later additions. I do
+not understand why you would want to only leave the extra space when the
+original size was within 10 elements of the final size.
+
+add_com returning something is probably left over from a fix I put in which
+is superceeded by the "user" class to distinguish command lists from function
+pointers. I should have removed it.
+
+We use csh instead of sh because I got tired of putting up with sh's crapping
+out on large environments.
+
+The change to inferior_args involves putting an explicit initializer of NULL
+on it, and testing it for NULL before freeing it. I guess most
+implementations of free ignore NULL pointers. The one we have on our Sun-2's
+does not.
+
+I can't remember why the alloca's were moved out of the variable
+initializations. It may have been to avoid a compiler problem. In any event,
+ignoring this modification shouldn't hurt.
+
+Now for the hard ones...
+
+The RT is a very different architecture from either a Sun or a VAX. It does
+not use a self-describing stack frame and it does not use the same
+conventions for symbols within object modules. There are also certain
+subtleties to the way it lays out its address space that cause problems. Many
+people at the ITC, including myself, are very impressed with the quality of
+the port Mike did in spite of these obstacles. You may feel that these
+problems are not worth effort. I have attempted to describe the differences
+involved with the RT in case you choose to address them. If not, we are still
+quite happy with the debugger we have and thank you for providing us with the
+code...
+
+Both the 68k family and the VAX have a frame pointer and a stack pointer.
+Using these to values and the information on the stack, one can do a complete
+stack trace. The RT on the other hand has only a stack pointer and a very
+loose concept of a frame pointer. The stack pointer will point just below a
+section of the stack dedicated to the maximum number of outgoing parameters
+minus 4 (the first 4 are in registers). The frame pointer will point
+somewhere in the stack where the compiler has deemed it optimal for
+addressing locals and parameters. There are variable length fields in the
+stack frame, such as the register save areas. In all, the thing looks like
+so:
+
+
+Higher Address
+-----------------
+
+a) Incoming args 5 through N   <---- Previous sp was here
+    (part of previous function's stack frame)
+b) Four words to save register passed arguments.
+c) Four words of linkage area (reserved).
+d) 1 word static link.
+e) 1 - 16 words of register save area.
+    (Variable length, return address is at the top of this since it was in
+r15)
+f) 0 -8 words of floating point reg. save area. (Variable length)
+g) Local variables (variable length)
+h) Outgoing arguments, words 5 - N <---- Current sp points to bottom of this.
+
+Lower Address
+----------------
+
+These and the stack contents are not enough to get back to the previous stack
+frame because you do not know how far back it is to the register save area.
+The code works because each function has been compiled to know how to pop its
+stack frame (i.e. it has embedded constants). In order to facilitate
+debugging, there is a trace table at the end of each function containing all
+the necessary information. (Namely the offset from the frame pointer to the
+top of the stack frame b in the above diagram) The trace table is located by
+starting at the beginning of the function and looking for the illegal
+instruction sequence 0xdf07df. Since the RT does not have 32bit constants in
+the instruction stream, this actually works. In general, the iar and the
+stack pointer are needed to do frame manipulations. The cache is necessary
+because finding the trace table is very expensive. In short, the machinery
+present in gdb was not up to handling this system, so we added what we
+thought would work. It is interesting to note that similar calling
+conventions are used on other RISC machines, notably the MIPS R2000. If you
+wish to take advantage of these high performance machines, you will have to
+do something like what we have done.
+
+The POP_DUMMY_FRAME problem is related to this. The RT stores return address
+in r15. We can not use this location to store the current iar since we must
+store r15 for later restoration. This rules out using the same function for
+popping both kinds of frames. There is also some hassle involved in getting
+the stack and frame pointers correct, but I think this might be fixed by
+generating an appropriate trace back table for the dummy function.
+
+The other problem we faced is the non-standard use of symbols within object
+modules. The RT defines two symbols for a function foo. There is "_.foo"
+which corresponds to the actual code in the text segment (just like "_foo" on
+a Sun or VAX), and "_foo" which points to the data area for the function in
+the data segment. The first word of the data area contains a pointer to the
+code. A function pointer (i.e. int (*foo)()) points to the data area (_foo),
+not the code (_.foo). This is what the TYPE_CODE_PTR modification in valops.c
+is for. Since both of these symbols are used for certain things, we cannot
+simply remove the dots. This is a bogus IBM feature and we do not like it any
+better than you do. We have to live with it if we want a working debugger.
+
+The "fix" to find_pc_misc function handles a special case on the RT where
+certain functions are in the high end of the address space. The RT uses the
+top 4 bits of an address as a segment number. The text segment is seg. 0, the
+data segment is seg. 1, and the kernel is mapped into seg. 14. Certain kernel
+functions (i.e. floating point functions) are directly callable by user code
+and so occur in the misc_function_vector. I realize this is bogus.
+
+The initialization code will not run because both the RT compilers (pcc and
+hc) output ascii data in the text section preceding the first function. Pcc
+outputs the name of each function before the function. Hc outputs the name of
+the source file at the beginning of the object module. Coding around this may
+be possible, but what is the point? I see no reason for this hackery. I have
+had problems getting it to work not only on the RT, but on the Sun-3. It is
+guaranteed to be a portability headache on many other machines as well. If
+you intend for gdb to only work when compiled with gcc, I suppose you may be
+able to use this method.
+
+I strongly agree with your statements that cleaner solutions are better in
+every way. Unfortunately, we did not write gdb, nor is the system we are
+working with particularly supportive of symbolic debugging. We were faced
+with the task of both figuring out gdb, and hacking our way around a
+contorted system (featuring among other things, a plethora of compiler bugs).
+The fact that our version of gdb is the only working symbolic debugger on the
+IBM RT (despite much effort by IBM) is proof that we have done something
+right. I am willing to discuss what would make this port better. However, it
+is not our intent to maintain or rewrite gdb. We merely wish to use it, and
+if not a terrible hassle, let other people use it too. Mike and I would
+prefer a copyright assignment. I would appreciate it if you would send me
+info on what we need to do.
+
+-Z-
+
+
+
diff --git a/gdb/=rt-changes b/gdb/=rt-changes
new file mode 100644 (file)
index 0000000..1eda81c
--- /dev/null
@@ -0,0 +1,3338 @@
+From: zs01#@andrew.cmu.edu (Zalman Stern)
+Date: Sun, 24 May 87 03:20:57 edt
+To: rms@prep.ai.mit.edu
+Subject: RT diffs for gdb version 2.1
+
+Here are the new files, followed by the diffs to old files. The first file below
+is ITCMODS which is my attempt to document some of our changes. Unfortunately,
+it has not been maintained particularly well and notably does not include info
+about our changes to support the HIGH-C compiler. One big change we put in was
+to use a number of initialize routines instead of the "linked list of object
+modules" that is used on other machines. The RT object file format appears to
+have a variable size header before the code, making it very difficult
+(impossible?) to get the initialization stuff to work. If you have any
+questions, don't hesitate to send me mail.
+
+-Z-
+
+Only in .: ITCMODS
+
+blockframe.c:
+    set_current_frame now takes an extra argument.
+    RT specific code for interpreting and caching of trace table entries.
+    Added initialize routine.
+
+breakpoint.c:
+    Added new_breakpoint_commands flag to prevent incorrect interpretation of command lists containing a continue statement.
+    Modified do_breakpoint_commands to know about new_breakpoint_commands.
+    Modified clear_breakpoint_commands to set new_breakpoint_commands.
+    Added initialize routine.
+
+core.c:
+    RT specific code to find the uarea.
+    RT specific code to indicate the start of the data segment.
+    set_current_frame now takes an extra argument.
+    Added initialize routine.
+
+dbxread.c:
+    Added support for the Camphor dynamic loading system. (All under #ifdef CAMPHOR).
+    Fix for multiple declarations of register variables (i.e. they are declared twice). The fix munges the incorrect declaration (i.e. the one which is not register).
+    set_rel_command to set relocation offset for camphor loaded files. (Under #ifdef CAMPHOR).
+    add_file_command to append a file's symbols to the current symbol table instead of replacing it. (Under #ifdef CAMPHOR).
+    RT specific code to deal with function names being _.foo instead of _foo.
+    Added initialize routine.
+
+    Feb 8, 1987 Zalman Stern.
+        Added test in symbol_file_command to see if file was compiled with debugging. If not print an error message instead of dumping core.
+        Added same test in add_file_command and made it run through BZPATH, CLASSPATH, and PATH in that order (Under #ifdef CAMPHOR).
+
+environ.c:
+    Fixed error in calculating new size of a reallocated environment.
+
+eval.c:
+    Added initialize routine.
+
+expread.y:
+    Moved alloca call out of variable initializations.
+
+findvar.c:
+    Added initialize routine.
+
+firstfile.c:
+    Added main initialization driver routine.
+
+frame.h:
+    Added RT specific declarations to hold frame information, and to deal with trace table caching.
+
+ibm032-pinsn.c:
+    New file, contains RT disassembler.
+
+ibm032-opcode.h:
+    New file, contains RT opcode definitions.
+
+infcmd.c
+    Changed code to use csh instead of sh to avoid the anoyance of the environment bug.
+    Added initialize routine.
+
+inflow.c:
+    Added initialize routine.
+
+infrun.c:
+    set_current_frame now takes an extra argument.
+    Added some code to deal with stopping in the middle of a camphor link. (Under #ifdef CAMPHOR).
+    Added RT specific code to get the return values from the right registers. Replaces code that was there for RT.
+    RT specific code to do a "POP_DUMMY_FRAME." Dummy frames are to store more complete state than a normal frame. Makes calling a function in inferior more reliable. Perhaps this should be expanded to other machine types.
+    Added initialize routine.
+
+    Feb 9, 1987 Zalman Stern.
+        Added call to select_frame after popping a stack dummy frame in normal_stop. This fixes the bug where you could not print variables without doing a "frame 0" after printing an expression with a function call in it.
+
+iniitialize.h:
+    Changed file to use #ifdef's for machine type. Allows one to use same sources for different machines.
+
+m-ibm032.h:
+    New file, contains RT specific macros and variables.
+
+param.h:
+    Changed file to use #ifdef's for machine type. Allows one to use same sources for different machines.
+
+pinsn.c:
+    Changed file to use #ifdef's for machine type. Allows one to use same sources for different machines.
+
+printcmd.c:
+    Moved alloca calls out of variable initialization.
+    Added initialize routine.
+
+source.c:
+    Added initialize routine.
+
+stack.c:
+    Added initialize routine.
+
+symmisc.c:
+    Added initialize routine.
+
+symtab.c:
+    RT specific code to deal with function names being _.foo instead of _foo.
+    Added initialize routine.
+
+utils.c:
+    Added comment.
+
+valarith.c:
+    Added initialize routine.
+
+valops.c:
+    Added initialize routine.
+
+valprint.c:
+    Added initialize routine.
+
+values.c:
+    Added initialize routine.
+
+Only in .: ibm032-opcode.h
+
+/* The opcode table consists of a 256 element array containing an
+ * instruction mnemonic and an instruction type field. This can be
+ * indexed directly by the first eight bits of an RT instruction.
+ * The instruction type consists of a type field and some flags. 
+ * In addition to this, there is an ifdef'd out "instruction" table
+ * at the end of the file. This is an alphabetical listing of the instructions
+ * containing mnemonic, opcode, and type. This is useful for modification
+ * purposes. There is also some code in the ifdef to convert the
+ * instruction table into an opcode table.
+ */
+
+/* Various useful bit masks. */
+#define ibm032_typeMask                0x0f /* Mask to get actual type info out of instruction type. */
+#define LOW4                   0x0f
+#define HIGH4                  0xf0
+#define LOW16                  0x0000ffff
+#define HIGH16                 0xffff0000
+#define LOW20                  0x000fffff
+#define LOW24                  0x00ffffff
+
+/* Instruction types consist of a type id in the low 4 bits and flags above that. */
+
+/* Flags. */
+#define ibm032_conditional     0x10
+#define ibm032_negative                0x20
+
+/* Format types. */
+#define ibm032_JI      0x0     /* Jump immediate. */
+#define ibm032_X       0x1     /* ??? */
+
+/* These next ones are in a special bit position. Do not change their defines. */
+#define ibm032_DS0     0x2     /* Data short with no shift for immediate value. */
+#define ibm032_DS1     0x3     /* Data short with 1 bit shift for immediate value. */
+#define ibm032_DS2     0x4     /* Data short with 2 bit shift for immediate value */
+#define ibm032_DSShiftOffset   ibm032_DS0 /* Offset to get shift value from ibm032_DS? types. */
+
+#define ibm032_RR      0x5     /* R format where second argument is a register */
+#define ibm032_RI      0x6     /* R format where second argument is 4 bit immediate. */
+#define ibm032_BI      0x7     /* Branch immediate. */
+#define ibm032_BA      0x8     /* Branch absolute. */
+#define ibm032_D       0x9     /* Data. */
+
+/* What an instruction looks like. */
+struct ibm032_opcode {
+    char *mnemonic; /* the name. NULL indicates illegal instruction. */
+    int type; /* See above. */
+};
+
+#define MAXOPCODES 256 /* Pretty well hardwired. */
+
+#ifndef BUILDTABLE
+/* The actual data. */
+struct ibm032_opcode ibm032_opcodes[] = {
+    {"j%s",            ibm032_JI | ibm032_conditional | ibm032_negative},
+    {"j%s",            ibm032_JI | ibm032_conditional | ibm032_negative},
+    {"j%s",            ibm032_JI | ibm032_conditional | ibm032_negative},
+    {"j%s",            ibm032_JI | ibm032_conditional | ibm032_negative},
+    {"j%s",            ibm032_JI | ibm032_conditional | ibm032_negative},
+    {"j%s",            ibm032_JI | ibm032_conditional | ibm032_negative},
+    {"j%s",            ibm032_JI | ibm032_conditional | ibm032_negative},
+    {"j%s",            ibm032_JI | ibm032_conditional | ibm032_negative},
+    {"j%s",            ibm032_JI | ibm032_conditional},
+    {"j%s",            ibm032_JI | ibm032_conditional},
+    {"j%s",            ibm032_JI | ibm032_conditional},
+    {"j%s",            ibm032_JI | ibm032_conditional},
+    {"j%s",            ibm032_JI | ibm032_conditional},
+    {"j%s",            ibm032_JI | ibm032_conditional},
+    {"j%s",            ibm032_JI | ibm032_conditional},
+    {"j%s",            ibm032_JI | ibm032_conditional},
+    {"stcs",           ibm032_DS0},
+    {"stcs",           ibm032_DS0},
+    {"stcs",           ibm032_DS0},
+    {"stcs",           ibm032_DS0},
+    {"stcs",           ibm032_DS0},
+    {"stcs",           ibm032_DS0},
+    {"stcs",           ibm032_DS0},
+    {"stcs",           ibm032_DS0},
+    {"stcs",           ibm032_DS0},
+    {"stcs",           ibm032_DS0},
+    {"stcs",           ibm032_DS0},
+    {"stcs",           ibm032_DS0},
+    {"stcs",           ibm032_DS0},
+    {"stcs",           ibm032_DS0},
+    {"stcs",           ibm032_DS0},
+    {"stcs",           ibm032_DS0},
+    {"sths",           ibm032_DS1},
+    {"sths",           ibm032_DS1},
+    {"sths",           ibm032_DS1},
+    {"sths",           ibm032_DS1},
+    {"sths",           ibm032_DS1},
+    {"sths",           ibm032_DS1},
+    {"sths",           ibm032_DS1},
+    {"sths",           ibm032_DS1},
+    {"sths",           ibm032_DS1},
+    {"sths",           ibm032_DS1},
+    {"sths",           ibm032_DS1},
+    {"sths",           ibm032_DS1},
+    {"sths",           ibm032_DS1},
+    {"sths",           ibm032_DS1},
+    {"sths",           ibm032_DS1},
+    {"sths",           ibm032_DS1},
+    {"sts",            ibm032_DS2},
+    {"sts",            ibm032_DS2},
+    {"sts",            ibm032_DS2},
+    {"sts",            ibm032_DS2},
+    {"sts",            ibm032_DS2},
+    {"sts",            ibm032_DS2},
+    {"sts",            ibm032_DS2},
+    {"sts",            ibm032_DS2},
+    {"sts",            ibm032_DS2},
+    {"sts",            ibm032_DS2},
+    {"sts",            ibm032_DS2},
+    {"sts",            ibm032_DS2},
+    {"sts",            ibm032_DS2},
+    {"sts",            ibm032_DS2},
+    {"sts",            ibm032_DS2},
+    {"sts",            ibm032_DS2},
+    {"lcs",            ibm032_DS0},
+    {"lcs",            ibm032_DS0},
+    {"lcs",            ibm032_DS0},
+    {"lcs",            ibm032_DS0},
+    {"lcs",            ibm032_DS0},
+    {"lcs",            ibm032_DS0},
+    {"lcs",            ibm032_DS0},
+    {"lcs",            ibm032_DS0},
+    {"lcs",            ibm032_DS0},
+    {"lcs",            ibm032_DS0},
+    {"lcs",            ibm032_DS0},
+    {"lcs",            ibm032_DS0},
+    {"lcs",            ibm032_DS0},
+    {"lcs",            ibm032_DS0},
+    {"lcs",            ibm032_DS0},
+    {"lcs",            ibm032_DS0},
+    {"lhas",           ibm032_DS1},
+    {"lhas",           ibm032_DS1},
+    {"lhas",           ibm032_DS1},
+    {"lhas",           ibm032_DS1},
+    {"lhas",           ibm032_DS1},
+    {"lhas",           ibm032_DS1},
+    {"lhas",           ibm032_DS1},
+    {"lhas",           ibm032_DS1},
+    {"lhas",           ibm032_DS1},
+    {"lhas",           ibm032_DS1},
+    {"lhas",           ibm032_DS1},
+    {"lhas",           ibm032_DS1},
+    {"lhas",           ibm032_DS1},
+    {"lhas",           ibm032_DS1},
+    {"lhas",           ibm032_DS1},
+    {"lhas",           ibm032_DS1},
+    {"cas",            ibm032_X},
+    {"cas",            ibm032_X},
+    {"cas",            ibm032_X},
+    {"cas",            ibm032_X},
+    {"cas",            ibm032_X},
+    {"cas",            ibm032_X},
+    {"cas",            ibm032_X},
+    {"cas",            ibm032_X},
+    {"cas",            ibm032_X},
+    {"cas",            ibm032_X},
+    {"cas",            ibm032_X},
+    {"cas",            ibm032_X},
+    {"cas",            ibm032_X},
+    {"cas",            ibm032_X},
+    {"cas",            ibm032_X},
+    {"cas",            ibm032_X},
+    {"ls",             ibm032_DS2},
+    {"ls",             ibm032_DS2},
+    {"ls",             ibm032_DS2},
+    {"ls",             ibm032_DS2},
+    {"ls",             ibm032_DS2},
+    {"ls",             ibm032_DS2},
+    {"ls",             ibm032_DS2},
+    {"ls",             ibm032_DS2},
+    {"ls",             ibm032_DS2},
+    {"ls",             ibm032_DS2},
+    {"ls",             ibm032_DS2},
+    {"ls",             ibm032_DS2},
+    {"ls",             ibm032_DS2},
+    {"ls",             ibm032_DS2},
+    {"ls",             ibm032_DS2},
+    {"ls",             ibm032_DS2},
+    {0,                        0},
+    {0,                        0},
+    {0,                        0},
+    {0,                        0},
+    {0,                        0},
+    {0,                        0},
+    {0,                        0},
+    {0,                        0},
+    {"b%s",            ibm032_BI | ibm032_conditional | ibm032_negative},
+    {"b%sx",           ibm032_BI | ibm032_conditional | ibm032_negative},
+    {"bala",           ibm032_BA},
+    {"balax",          ibm032_BA},
+    {"bali",           ibm032_BI},
+    {"balix",          ibm032_BI},
+    {"b%s",            ibm032_BI | ibm032_conditional},
+    {"b%sx",           ibm032_BI | ibm032_conditional},
+    {"ais",            ibm032_RI},
+    {"inc",            ibm032_RI},
+    {"sis",            ibm032_RI},
+    {"dec",            ibm032_RI},
+    {"cis",            ibm032_RI},
+    {"clrsb",          ibm032_RI},
+    {"mfs",            ibm032_RR},
+    {"setsb",          ibm032_RI},
+    {"clrbu",          ibm032_RI},
+    {"clrbl",          ibm032_RI},
+    {"setbu",          ibm032_RI},
+    {"setbl",          ibm032_RI},
+    {"mftbiu",         ibm032_RI},
+    {"mftbil",         ibm032_RI},
+    {"mttbiu",         ibm032_RI},
+    {"mttbil",         ibm032_RI},
+    {"sari",           ibm032_RI},
+    {"sari16",         ibm032_RI},
+    {0,                        0},
+    {0,                        0},
+    {"lis",            ibm032_RI},
+    {0,                        0},
+    {0,                        0},
+    {0,                        0},
+    {"sri",            ibm032_RI},
+    {"sri16",          ibm032_RI},
+    {"sli",            ibm032_RI},
+    {"sli16",          ibm032_RI},
+    {"srpi",           ibm032_RI},
+    {"srpi16",         ibm032_RI},
+    {"slpi",           ibm032_RI},
+    {"slpi16",         ibm032_RI},
+    {"sar",            ibm032_RR},
+    {"exts",           ibm032_RR},
+    {"sf",             ibm032_RR},
+    {"cl",             ibm032_RR},
+    {"c",              ibm032_RR},
+    {"mts",            ibm032_RR},
+    {"d",              ibm032_RR},
+    {0,                        0},
+    {"sr",             ibm032_RR},
+    {"srp",            ibm032_RR},
+    {"sl",             ibm032_RR},
+    {"slp",            ibm032_RR},
+    {"mftb",           ibm032_RR},
+    {"tgte",           ibm032_RR},
+    {"tlt",            ibm032_RR},
+    {"mttb",           ibm032_RR},
+    {"svc",            ibm032_D},
+    {"ai",             ibm032_D},
+    {"cal16",          ibm032_D},
+    {"oiu",            ibm032_D},
+    {"oil",            ibm032_D},
+    {"nilz",           ibm032_D},
+    {"nilo",           ibm032_D},
+    {"xil",            ibm032_D},
+    {"cal",            ibm032_D},
+    {"lm",             ibm032_D},
+    {"lha",            ibm032_D},
+    {"ior",            ibm032_D},
+    {"ti",             ibm032_D},
+    {"l",              ibm032_D},
+    {"lc",             ibm032_D},
+    {"tsh",            ibm032_D},
+    {"lps",            ibm032_D},
+    {"aei",            ibm032_D},
+    {"sfi",            ibm032_D},
+    {"cli",            ibm032_D},
+    {"ci",             ibm032_D},
+    {"niuz",           ibm032_D},
+    {"niuo",           ibm032_D},
+    {"xiu",            ibm032_D},
+    {"cau",            ibm032_D},
+    {"stm",            ibm032_D},
+    {"lh",             ibm032_D},
+    {"iow",            ibm032_D},
+    {"sth",            ibm032_D},
+    {"st",             ibm032_D},
+    {"stc",            ibm032_D},
+    {0,                        0},
+    {"abs",            ibm032_RR},
+    {"a",              ibm032_RR},
+    {"s",              ibm032_RR},
+    {"o",              ibm032_RR},
+    {"twoc",           ibm032_RR},
+    {"n",              ibm032_RR},
+    {"m",              ibm032_RR},
+    {"x",              ibm032_RR},
+    {"b%sr",           ibm032_RR | ibm032_conditional | ibm032_negative},
+    {"b%srx",          ibm032_RR | ibm032_conditional | ibm032_negative},
+    {0,                        0},
+    {"lhs",            ibm032_RR},
+    {"balr",           ibm032_RR},
+    {"balrx",          ibm032_RR},
+    {"b%sr",           ibm032_RR | ibm032_conditional},
+    {"b%srx",          ibm032_RR | ibm032_conditional},
+    {"wait",           ibm032_RR},
+    {"ae",             ibm032_RR},
+    {"se",             ibm032_RR},
+    {"ca16",           ibm032_RR},
+    {"onec",           ibm032_RR},
+    {"clz",            ibm032_RR},
+    {0,                        0},
+    {0,                        0},
+    {0,                        0},
+    {"mc03",           ibm032_RR},
+    {"mc13",           ibm032_RR},
+    {"mc23",           ibm032_RR},
+    {"mc33",           ibm032_RR},
+    {"mc30",           ibm032_RR},
+    {"mc31",           ibm032_RR},
+    {"mc32",           ibm032_RR},
+};
+
+#else
+struct ibm032_opcode ibm032_opcodes[MAXOPCODES];
+
+struct ibm032_instruction {
+    char *mnemonic; /* Mnemonic for this instruction */
+    char opcode; /* Numerical value of opcode. */
+    int type; /* This instructions format. */
+};
+
+struct ibm032_instruction ibm032_instructions[] =
+{
+ {"a",         0xe1, ibm032_RR},
+ {"abs",       0xe0, ibm032_RR},
+ {"ae",                0xf1, ibm032_RR},
+ {"aei",       0xd1, ibm032_D},
+ {"ai",                0xc1, ibm032_D},
+ {"ais",       0x90, ibm032_RI},
+ {"bala",      0x8a, ibm032_BA},
+ {"balax",     0x8b, ibm032_BA},
+ {"bali",      0x8c, ibm032_BI},
+ {"balix",     0x8d, ibm032_BI},
+ {"balr",      0xec, ibm032_RR},
+ {"balrx",     0xed, ibm032_RR},
+ {"b%s",       0x8e, ibm032_BI | ibm032_conditional},
+ {"b%sr",      0xee, ibm032_RR | ibm032_conditional},
+ {"b%srx",     0xef, ibm032_RR | ibm032_conditional},
+ {"b%sx",      0x8f, ibm032_BI | ibm032_conditional},
+ {"b%s",       0x88, ibm032_BI | ibm032_conditional | ibm032_negative},
+ {"b%sr",      0xe8, ibm032_RR | ibm032_conditional | ibm032_negative},
+ {"b%srx",     0xe9, ibm032_RR | ibm032_conditional | ibm032_negative},
+ {"b%sx",      0x89, ibm032_BI | ibm032_conditional | ibm032_negative},
+ {"c",         0xb4, ibm032_RR},
+ {"cal",       0xc8, ibm032_D},
+ {"cal16",     0xc2, ibm032_D},
+ {"cas",       0x60, ibm032_X},
+ {"cau",       0xd8, ibm032_D},
+ {"ca16",      0xf3, ibm032_RR},
+ {"ci",                0xd4, ibm032_D},
+ {"cis",       0x94, ibm032_RI},
+ {"cl",                0xb3, ibm032_RR},
+ {"cli",       0xd3, ibm032_D},
+ {"clrbl",     0x99, ibm032_RI},
+ {"clrbu",     0x98, ibm032_RI},
+ {"clrsb",     0x95, ibm032_RI},
+ {"clz",       0xf5, ibm032_RR},
+ {"d",         0xb6, ibm032_RR},
+ {"dec",       0x93, ibm032_RI},
+ {"exts",      0xb1, ibm032_RR},
+ {"inc",       0x91, ibm032_RI},
+ {"ior",       0xcb, ibm032_D},
+ {"iow",       0xdb, ibm032_D},
+
+ {"j%s",       0x08, ibm032_JI | ibm032_conditional},
+ {"j%s",       0x00, ibm032_JI | ibm032_conditional | ibm032_negative},
+
+ {"l",         0xcd, ibm032_D},
+ {"lc",                0xce, ibm032_D},
+ {"lcs",       0x40, ibm032_DS0},
+ {"lh",                0xda, ibm032_D},
+ {"lha",       0xca, ibm032_D},
+ {"lhas",      0x50, ibm032_DS1},
+ {"lhs",       0xeb, ibm032_RR},
+ {"lis",       0xa4, ibm032_RI},
+ {"lm",                0xc9, ibm032_D},
+ {"lps",       0xd0, ibm032_D},
+ {"ls",                0x70, ibm032_DS2},
+ {"m",         0xe6, ibm032_RR},
+ {"mc03",      0xf9, ibm032_RR},
+ {"mc13",      0xfa, ibm032_RR},
+ {"mc23",      0xfb, ibm032_RR},
+ {"mc33",      0xfc, ibm032_RR},
+ {"mc30",      0xfd, ibm032_RR},
+ {"mc31",      0xfe, ibm032_RR},
+ {"mc32",      0xff, ibm032_RR},
+ {"mfs",       0x96, ibm032_RR},
+ {"mftb",      0xbc, ibm032_RR},
+ {"mftbil",    0x9d, ibm032_RI},
+ {"mftbiu",    0x9c, ibm032_RI},
+ {"mts",       0xb5, ibm032_RR},
+ {"mttb",      0xbf, ibm032_RR},
+ {"mttbil",    0x9f, ibm032_RI},
+ {"mttbiu",    0x9e, ibm032_RI},
+ {"n",         0xe5, ibm032_RR},
+
+ {"nilo",      0xc6, ibm032_D},
+ {"nilz",      0xc5, ibm032_D},
+ {"niuo",      0xd6, ibm032_D},
+ {"niuz",      0xd5, ibm032_D},
+ {"o",         0xe3, ibm032_RR},
+ {"oil",       0xc4, ibm032_D},
+ {"oiu",       0xc3, ibm032_D},
+ {"onec",      0xf4, ibm032_RR},
+ {"s",         0xe2, ibm032_RR},
+ {"sar",       0xb0, ibm032_RR},
+ {"sari",      0xa0, ibm032_RI},
+ {"sari16",    0xa1, ibm032_RI},
+ {"se",                0xf2, ibm032_RR},
+ {"setbl",     0x9b, ibm032_RI},
+ {"setbu",     0x9a, ibm032_RI},
+ {"setsb",     0x97, ibm032_RI},
+ {"sf",                0xb2, ibm032_RR},
+
+ {"sfi",       0xd2, ibm032_D},
+
+ {"sis",       0x92, ibm032_RI},
+ {"sl",                0xba, ibm032_RR},
+ {"sli",       0xaa, ibm032_RI},
+ {"sli16",     0xab, ibm032_RI},
+ {"slp",       0xbb, ibm032_RR},
+ {"slpi",      0xae, ibm032_RI},
+ {"slpi16",    0xaf, ibm032_RI},
+ {"sr",                0xb8, ibm032_RR},
+ {"sri",       0xa8, ibm032_RI},
+ {"sri16",     0xa9, ibm032_RI},
+ {"srp",       0xb9, ibm032_RR},
+ {"srpi",      0xac, ibm032_RI},
+ {"srpi16",    0xad, ibm032_RI},
+
+ {"st",                0xdd, ibm032_D},
+
+ {"stc",       0xde, ibm032_D},
+ {"stcs",      0x10, ibm032_DS0},
+ {"sth",       0xdc, ibm032_D},
+ {"sths",      0x20, ibm032_DS1},
+ {"stm",       0xd9, ibm032_D},
+ {"sts",       0x30, ibm032_DS2},
+ {"svc",       0xc0, ibm032_D},
+ {"tgte",      0xbd, ibm032_RR},
+ {"ti",                0xcc, ibm032_D},
+ {"tlt",       0xbe, ibm032_RR},
+ {"tsh",       0xcf, ibm032_D},
+ {"twoc",      0xe4, ibm032_RR},
+ {"wait",      0xf0, ibm032_RR},
+ {"x",         0xe7, ibm032_RR},
+ {"xil",       0xc7, ibm032_D},
+ {"xiu",       0xd7, ibm032_D}
+};
+
+/* Code to generate the packed opcode table from the instructions table. */
+
+#include <stdio.h>
+
+char *typeNames[] = {
+    "ibm032_JI",
+    "ibm032_X",
+    "ibm032_DS0",
+    "ibm032_DS1",
+    "ibm032_DS2",
+    "ibm032_RR",
+    "ibm032_RI",
+    "ibm032_BI",
+    "ibm032_BA",
+    "ibm032_D"
+};
+
+main()
+{
+
+    int i, j, opcode, type;
+
+    for (j = (sizeof(ibm032_instructions) / sizeof(struct ibm032_instruction)); j >= 0; j--) {
+        opcode = ibm032_instructions[j].opcode;
+        switch (ibm032_instructions[j].type & ibm032_typeMask) {
+            case ibm032_JI:
+                i = 7;
+                break;
+            case ibm032_X:
+            case ibm032_DS0:
+            case ibm032_DS1:
+            case ibm032_DS2:
+                i = 15;
+                break;
+            case ibm032_RR:
+            case ibm032_RI:
+            default:
+                i = 0;
+                break;
+        }
+        for (;i >= 0; i--) {
+            ibm032_opcodes[opcode + i].mnemonic = ibm032_instructions[j].mnemonic;
+            ibm032_opcodes[opcode + i].type = ibm032_instructions[j].type;
+        }
+    }
+
+    printf("struct ibm032_opcode ibm032_opcodes[] = {\n");
+    for ( j = 0; j < 256; j++) {
+        type = ibm032_opcodes[j].type;      
+        if (ibm032_opcodes[j].mnemonic != NULL)
+            printf("    {\"%s\",\t\t%s%s%s},\n", ibm032_opcodes[j].mnemonic,
+                   typeNames[type & ibm032_typeMask],
+                   (type & ibm032_conditional) ? " | ibm032_conditional" : "",
+                   (type & ibm032_negative) ? " | ibm032_negative" : "");
+        else
+            printf("    {0,\t\t\t0},\n");
+    }
+    printf("};\n");
+}
+#endif /* BUILDTABLE */
+
+Only in .: ibm032-pinsn.c
+
+/* Print ibm032 instructions 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 <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "ibm032-opcode.h"
+
+/* ibm032 instructions are never longer than this many bytes.  */
+#define MAXLEN 4
+
+extern char *reg_names[];
+
+static char *mapCondition();
+
+\f
+/* Print the ibm032 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];
+  int opcodeIndex, instructionBits, type;
+  char *mnemonic;
+
+  read_memory (memaddr, buffer, MAXLEN);
+  instructionBits = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3]; /* Get it into an int for easy use. */
+
+  if ((mnemonic = ibm032_opcodes[opcodeIndex = buffer[0]].mnemonic) == NULL)
+    {
+      fprintf (stream, "0%o", (instructionBits & HIGH16) >> 16);
+      return 2;
+    }
+  type = ibm032_opcodes[opcodeIndex].type;
+  if (!(type & ibm032_conditional)) {
+    fprintf (stream, "%s", mnemonic);
+
+    switch (type) {
+
+      int displacement; /* Used for sign extensions. */
+      char *sign;
+
+      case ibm032_X:
+        fprintf(stream, "\t%s, %s(%s)", reg_names[buffer[0] & LOW4], (buffer[1] & HIGH4) ? (reg_names[(buffer[1] & HIGH4) >> 4]) : "", reg_names[buffer[1] & LOW4]);
+        return 2;
+      case ibm032_DS0:
+      case ibm032_DS1:
+      case ibm032_DS2:
+        fprintf(stream, "\t%s, %x", reg_names[(buffer[1] & HIGH4) >> 4], (buffer[0] & LOW4) << (ibm032_opcodes[opcodeIndex].type - ibm032_DSShiftOffset)); /* Hacked to shift imediate field. */
+        if (buffer[1] & LOW4)
+          fprintf(stream, "(%s)", reg_names[buffer[1] & LOW4]);
+        return 2;
+      case ibm032_RR:
+        fprintf(stream, "\t%s, %s", reg_names[(buffer[1] & HIGH4) >> 4], reg_names[buffer[1] & 0x0f]);
+        return 2;
+      case ibm032_RI:
+        fprintf(stream, "\t%s, %x", reg_names[(buffer[1] & HIGH4) >> 4], buffer[1] & LOW4);
+        return 2;
+      case ibm032_BI:
+        fprintf(stream, "\t%s, ", reg_names[(buffer[1] & HIGH4) >> 4]);
+        displacement = (instructionBits & LOW20);
+        if ((displacement & (1 << 19)) != 0) /* Cover sign extension. */
+            displacement |= 0xfff00000;
+        print_address(memaddr + (displacement * 2), stream); /* Need sign extension. */
+        return 4;
+      case ibm032_BA:
+        print_address((instructionBits & LOW24) & ~1, stream);
+        return 4;
+      case ibm032_D:
+        displacement = (instructionBits & LOW16);
+        if ((displacement & (1 << 15)) != 0) { /* Cover sign extension. */
+          displacement = - (displacement | 0xffff0000);
+          sign = "-";
+        }
+        else
+          sign = "";
+        fprintf(stream, "\t%s, %s, %s%x", reg_names[(buffer[1] & HIGH4) >> 4], reg_names[buffer[1] & LOW4], sign, displacement);
+        return 4;
+    }
+  }
+  else { /* Conditional branches are hacked. */
+    switch (type & 0x0f) {
+
+      int displacement;
+
+      case ibm032_JI:
+        fprintf(stream, ibm032_opcodes[opcodeIndex].mnemonic, mapCondition(type & ibm032_negative, buffer[0] & LOW4));
+      putc('\t', stream);
+      print_address((buffer[1] << 1) + memaddr, stream);
+      return 2;
+    case ibm032_BI:
+      fprintf(stream, ibm032_opcodes[opcodeIndex].mnemonic, mapCondition(type & ibm032_negative, (buffer[1] & HIGH4) >> 4));
+      putc('\t', stream);
+        displacement = (instructionBits & LOW20);
+        if ((displacement & (1 << 19)) != 0) /* Cover sign extension. */
+            displacement |= 0xfff00000;
+        print_address((displacement * 2) + memaddr, stream);
+      return 4;
+    case ibm032_RR:
+      fprintf(stream, ibm032_opcodes[opcodeIndex].mnemonic, mapCondition(type & ibm032_negative, (buffer[1] & HIGH4) >> 4));
+      fprintf(stream, "\t%s", reg_names[buffer[1] & LOW4]);
+      return 2;   
+    }
+  }
+}
+
+/* Converts a 4 bit "conditional specifier" into a semi-meaningful name. */
+static char *mapCondition(negative, conditionBits)
+    int conditionBits;
+{
+
+    char *condition;
+
+    if (negative)
+        switch (conditionBits) {
+            case 0x8:
+                condition = "";
+                break;
+            case 0x9:
+                condition = "ge";
+                break;
+            case 0xa:
+                condition = "ne";
+                break;
+            case 0xb:
+                condition = "le";
+                break;
+            case 0xc:
+                condition = "nc";
+                break;
+            case 0xd: /* Reserved. */
+                condition = "notbogus";
+                break;
+            case 0xe:
+                 condition = "no";
+                break;
+            case 0xf:
+                condition = "ntb";
+                break;
+            default:
+                condition = "notbogus";
+                break;
+        }
+    else
+        switch (conditionBits) {
+            case 0x8:
+                condition = "nop";
+                break;
+            case 0x9:
+                condition = "lt";
+                break;
+            case 0xa:
+                condition = "eq";
+                break;
+            case 0xb:
+                condition = "gt";
+                break;
+            case 0xc:
+                condition = "c";
+                break;
+            case 0xd: /* Reserved. */
+                condition = "bogus";
+                break;
+            case 0xe:
+                condition = "o";
+                break;
+            case 0xf:
+                condition = "tb";
+                break;
+            default:
+                condition = "bogus";
+                break;
+        }
+    return condition;
+}
+
+Only in .: m-ibm032.h
+
+/* Parameters for execution on an IBM RT, 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!
+*/
+
+/* 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
+
+/* 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, 1) & 0x00ff; \
+    if (op == 0xd9) { \
+       pc += 4; \
+       op = read_memory_integer (pc, 2); \
+       if ((op & 0xff00) == 0xc100) { /* pcc prolog add r1, number */ \
+           pc += 4; \
+           op = read_memory_integer (pc, 1) & 0x00ff; \
+           if (op == 0x6e) {                   /* cas r14, 0 */ \
+               pc += 2; \
+               op = read_memory_integer (pc, 2) & 0xffff; \
+               if (op == 0xc8d1) pc += 4; /* cal r13, junk(r1) */ \
+           } \
+       } \
+       else if ((op & 0xffff) == 0x6e00) { /* hc prolog cas r14, 0 */ \
+           pc += 4; \
+           op = read_memory_integer(pc, 1) & 0xff; \
+           if (op == 0x6d) { /* cas r13 junk, probably */ \
+               pc += 2; \
+               op = read_memory_integer(pc, 2) & 0xffff; \
+               if (op == 0xc811) pc += 4; /* cal r1,  foo(r1) */       \
+           } \
+       } \
+    } \
+    while (1) { \
+       /* now watch for st, sth, stc, and short versions thereof, cas instructions and exts */ \
+       /* which are all used to store the parameters from r2-r5 onto the stack or into reg vars */ \
+       op = read_memory_integer (pc, 2); \
+       if ((op & 0xff00) == 0x3000 && (op & 0xf0) >= 0x20 && (op & 0xf0) <= 0x50) pc += 2; \
+       else if ((op & 0xff00) == 0x2300 && (op & 0xf0) >= 0x20 && (op & 0xf0) <= 0x50) pc += 2; \
+       else if ((op & 0xff00) == 0x1b00 && (op & 0xf0) >= 0x20 && (op & 0xf0) <= 0x50) pc += 2; \
+       else if ((op & 0xff00) == 0x6c00 && (op & 0xf0) >= 0x20 && (op & 0xf0) <= 0x50) pc += 2; \
+       else if ((op & 0xff00) == 0xb100) pc += 2; /* extend sign */ \
+       else if ((op & 0xff00) == 0xdd00 && (op & 0xf0) >= 0x20 && (op & 0xf0) <= 0x50) pc += 4; \
+       else break; \
+    } \
+}
+
+/* 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_register (15)
+
+/* 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 (0x20000000 - NBPG * (UPAGES))
+
+/* Address of end of stack space.  */
+
+/* extra page is for the "red zone" */
+#define STACK_END_ADDR (0x20000000 - NBPG * (UPAGES+1))
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {0xbd, 0x00}
+
+/* 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, 1) & 0x00ff == 0xc9)
+
+/* Return 1 if P points to an invalid floating point value.  */
+
+#define INVALID_FLOAT(p) 0   /* Just a first guess; not checked */
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 18
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "iar", "mq"}
+
+/* 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 13           /* Contains address of executing stack frame */
+#define SP_REGNUM 1            /* Contains address of top of stack */
+#define PS_REGNUM 17           /* Contains processor status */
+#define PC_REGNUM 16           /* Contains program counter */
+
+#define REGISTER_U_ADDR(addr, blockend, regno)         \
+{ addr = blockend + regno * 4; }
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES (NUM_REGS*4)
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N) ((N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  On the vax, 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 vax, all regs are 4 bytes.  */
+
+#define REGISTER_VIRTUAL_SIZE(N) 4
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)    \
+  bcopy ((FROM), (TO), 4);
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)        \
+  bcopy ((FROM), (TO), 4);
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) builtin_type_int
+\f
+/* 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 Sun, the frame's nominal address
+   is the address of a 4-byte word containing the calling frame's address.  */
+
+#define FRAME_CHAIN(thisframe)  (rt_prev_frame(thisframe))
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+  (chain >= 0x10000000 && chain < 0x20000000)
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame.  */
+
+#define FRAME_SAVED_PC(frame) (rt_frame_reg(frame, 15))
+
+#define FRAME_ARGS_ADDRESS(fi) (rt_frame_args(fi.frame))
+
+#define FRAME_LOCALS_ADDRESS(fi) (fi.frame)
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.  */
+
+#define FRAME_NUM_ARGS(val, fi)  \
+{register struct rt_frame *tf; \
+    tf = get_cached_frame(fi.frame); \
+    val = -1; \
+    if (tf) val = tf->nParms;\
+}
+
+/* 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.  */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs)            \
+{ register int regnum;                                                 \
+  register struct rt_frame *tf;                        \
+  register CORE_ADDR next_addr;                                                \
+  bzero (&(frame_saved_regs), sizeof (frame_saved_regs));                      \
+  tf = get_cached_frame((frame_info).frame);                                   \
+  if (tf) {                                                                                    \
+    for(regnum = tf->firstReg; regnum < 16; regnum++) {                \
+      (frame_saved_regs).regs[regnum] = tf->firstRLoc+ 4*(regnum - tf->firstReg); \
+    } \
+  } \
+}
+
+\f
+/* 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;                             \
+  sp = push_word (sp, read_register (PC_REGNUM));   \
+  for (regnum = 15; regnum >= 0; regnum--)  \
+    sp = push_word (sp, read_register (regnum));    \
+  write_register (FP_REGNUM, sp+64);               \
+  write_register (SP_REGNUM, sp);  }
+
+/* discard special frame pushed by PUSH_DUMMY_FRAME */
+#define POP_DUMMY_FRAME \
+    {register CORE_ADDR sp; \
+    register int regnum; \
+    sp = read_register(FP_REGNUM)-64; \
+    for(regnum = 0; regnum < 16;regnum++) { \
+       write_register(regnum, read_memory_integer(sp, 4)); \
+       sp += 4; \
+    } \
+    /* now get the pc */ \
+    write_register(PC_REGNUM, read_memory_integer(sp, 4)); \
+    sp += 4; \
+    }
+
+/* Discard from the stack the innermost frame, restoring all registers.  */
+/* THIS ROUTINE DOES NOT SET R1 (SP_REGNUM) CORRECTLY */
+/* REALLY MUST CONSULT TRACE TBL TO FIND OUT FRAME SIZE */
+#define POP_FRAME  \
+{ register CORE_ADDR fp = read_register (FP_REGNUM);            \
+  register int regnum;                                          \
+  register struct rt_frame *tf;                        \
+  tf = (struct rt_frame *) get_cached_frame(fp);                       \
+  if (tf) {                                                    \
+    for(regnum = tf->firstReg; regnum < 16; regnum++) {                \
+       write_register(regnum,                          \
+           read_memory_integer (tf->firstRLoc + 4*(regnum-tf->firstReg), 4)    \
+           );  \
+    }          \
+    write_register(PC_REGNUM, read_register(15));              \
+    write_register(SP_REGNUM, tf->firstRLoc + 4*(16-tf->firstReg) + 36);       \
+  }            \
+}
+
+/* This sequence of words is the instructions
+     ls                r2,0(r1)                        2 bytes         pick up args
+     ls                r3,4(r1)                        2 bytes         pick up args
+     ls                r4,8(r1)                        2 bytes         pick up args
+     ls                r5,c(r1)                        2 bytes         pick up args
+     cal       r1,16(r1)                       4 bytes         fix up ap (==sp)
+     cal16     r15,<low>                       4 bytes         do call
+     oiu       r15,<high>(r15) 4
+     lr                r0,r15                  2
+     ls                r15,0(r15)                      2
+     balr      r15                             2
+     bpt                                       2                       get back to gdb
+     <4 byte trace table>              4
+
+This is 16 bytes.
+*/
+
+#define CALL_DUMMY {0x70217131, 0x72417351, 0xc8110010, 0xc2f06969, \
+    0xc3ff6969, 0x60f070ff, 0xecffbd00, 0xdf7fdf00}
+
+#define CALL_DUMMY_LENGTH 32
+
+#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, fun, nargs)     \
+{ *((short *)(((char *)dummyname)+14)) = fun&0xffff; \
+*((short *)(((char *)dummyname)+18)) = (fun>>16)&0xffff; \
+}
+\f
+/* 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, which we do not support. */
+
+#define INIT_STACK(beg, end)  \
+{  }
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR \
+{ }
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR \
+{ }
+
+/* After KDB is entered by a fault, push all registers
+   that GDB thinks about (all NUM_REGS of them),
+   so that they appear in order of ascending GDB register number.
+   The fault code will be on the stack beyond the last register.  */
+
+#define PUSH_REGISTERS        \
+{ }
+
+/* Assuming the registers (including processor status) have been
+   pushed on the stack in order of ascending GDB register number,
+   restore them and return to the address in the saved PC register.  */
+
+#define POP_REGISTERS          \
+{ }
+
+Only in .: m-ibm032init.h
+
+/* This is how the size of an individual .o file's text segment
+   is rounded on a sun.  */
+
+#define FILEADDR_ROUND(addr) ((addr + 3) & -4)
+
+diff -c ../../gnu/gdb/blockframe.c ./blockframe.c
+*** ../../gnu/gdb/blockframe.c Sat Apr  4 22:06:18 1987
+--- ./blockframe.c     Mon Apr 27 01:06:06 1987
+***************
+*** 53,62 ****
+  }
+  
+  void
+! set_current_frame (frame)
+       FRAME frame;
+  {
+    current_frame = frame;
+  }
+  
+  /* Return the frame that called FRAME.
+--- 53,67 ----
+  }
+  
+  void
+! set_current_frame (frame, validp)
+       FRAME frame;
++      int validp;
+  {
+    current_frame = frame;
++ #ifdef ibm032
++   if (validp)
++     recache_frames();
++ #endif
+  }
+  
+  /* Return the frame that called FRAME.
+***************
+*** 291,301 ****
+       CORE_ADDR pc;
+  {
+    register int i;
+  
+    /* Note that the last thing in the vector is always _etext.  */
+    for (i = 0; i < misc_function_count; i++)
+      {
+!       if (pc < misc_function_vector[i].address)
+       return i - 1;
+      }
+    return -1;
+--- 296,309 ----
+       CORE_ADDR pc;
+  {
+    register int i;
++   register long j;
+  
+    /* Note that the last thing in the vector is always _etext.  */
+    for (i = 0; i < misc_function_count; i++)
+      {
+!       if ((j = misc_function_vector[i].address) < 0)
+!         continue;
+!       if (pc < j)
+       return i - 1;
+      }
+    return -1;
+***************
+*** 325,333 ****
+--- 333,610 ----
+      }
+  }
+  
++ #ifdef ibm032
++ /* RT frame format:
++     arg 3    these are not really here, but are in regs
++     arg 2
++     arg 1
++     arg 0
++     resvd 20 bytes
++     rn to r15        saved regs
++     floating regs (at first assume 0 bytes, fix later)
++     locals
++ 
++ N.B. r13 points 64 bytes below the end of the locals.
++ */
++ 
++ /*
++  * Routine for ibm032 stack trace.  Called after a new frame has been set.  Do an entire stack
++  * trace, and squirrel away the information.  We need to do this since the ibm032 (rt) does
++  * not have enough info in a known place off of the frame ptr (r13) to do anything useful.
++  * Instead, one also requires the pc, and can then perform various operations to find
++  * out how that procedure built its frame, and thus, to decode it.  However, since this is
++  * fairly slow, we only do it after a set_current_frame operation has been performed.
++ */
++ 
++ #define rtTTSize 50
++ static struct rtTTCache {
++     CORE_ADDR lbound;                /* lowest address so far known as using this trace table */
++     CORE_ADDR ttaddr;                /* address of the last '0xdf' in the trace table */
++     char ttype;                              /* type of the trace table -- 0 == unused */
++ } ttcache[rtTTSize];
++ short ttptr = 0;
++ 
++ #define rtSize       50
++ static struct rt_frame rtFrames[rtSize];
++ static int rtCount;
++ static CORE_ADDR rt_next_frame, rt_next_pc;
++ 
++ static struct rtTTCache *ttfind (addr)
++     CORE_ADDR addr; {
++     register int i;
++     register struct rtTTCache *tp;
++     for(i=0,tp=ttcache;i<rtTTSize;i++,tp++) {
++      if (addr >= tp->lbound && addr <= tp->ttaddr) return tp;
++     }
++     return 0;
++ }
++ 
++ static ttadd(lowaddr, ttaddr, type)
++     register CORE_ADDR lowaddr, ttaddr;
++     char type; {
++     register struct rtTTCache *tp;
++     if (tp = ttfind(ttaddr)) {
++      /* possibly increase the bound on this cache element */
++      if (lowaddr < tp->lbound) tp->lbound = lowaddr;
++     }
++     else {
++      /* add a new element */
++      tp = &ttcache[ttptr++];
++      tp->lbound = lowaddr;
++      tp->ttaddr = ttaddr;
++      tp->ttype = type;
++      if (ttptr >= rtTTSize) ttptr = 0;       /* keep it in bounds */
++     }
++ }
++ 
++ /* this routine scans for a trace table, and returns 4 bytes: 0 0 <n params> <first saved reg> */
++ rt_num_regs (pc, tf)
++ register struct rt_frame *tf;
++ CORE_ADDR pc; {
++     register state = 0;
++     register long newpc = pc;
++     register int tc;
++     short nparms, firstreg;
++     short ttype;
++     short optx;
++     long offset;
++     char offtype;
++     struct rtTTCache *tp;
++     CORE_ADDR frame;
++ 
++     frame = tf->frame;
++     /* first see if it is in our ttcache */
++     if (tp = ttfind(pc)) {
++      state = 3;
++      ttype = tp->ttype;
++      newpc = tp->ttaddr;
++     }
++     else {
++      /* state machine to look for 'df' 'xx' 'df' */
++      while (1) {
++          tc = read_memory_integer(newpc, 2);
++          if (state == 0 && (tc&0xff00) == 0xdf00) {
++              state = 1;
++              ttype = tc & 0xff;
++          }
++          else if (state == 1 && (tc & 0xff00) == 0xdf00) {
++              state = 3;
++              break;
++          }
++          else state = 0;
++          if (newpc - pc > 20000) break;
++          newpc += 2;
++      }
++      if (state == 3) ttadd(pc, newpc, ttype);        /* add to cache */
++     }
++     if (state != 3) {
++      printf("No trace table for pc %x, making one up.\n", pc);
++      tf->nParms = 0;
++      tf->firstReg = 12;
++      tf->firstRLoc = frame+64;
++      rt_next_pc = read_memory_integer(frame+64+12, 4);
++      rt_next_frame = read_memory_integer(frame+64+4, 4);
++      return 0;
++     }
++     /* otherwise newpc is pointing at the last 'df' in the trace table */
++     else if (ttype == 3) {
++      /* funny trace table found by OBSERVATION (not doc) to be in program prolog */
++      return -1;              /* special value checked by recache_frames */
++     }
++     else if (ttype == 2) {
++      /* assembly: no registers were saved */
++      tf->nParms = 0;
++      tf->firstReg = 16;
++      tf->firstRLoc = 0;
++      rt_next_pc = read_register(15);         /* where we go back to */
++      rt_next_frame = frame;
++      tf->frame -= 100;               /* hack to eliminate duplicate tags */
++      return 0;
++     }
++     else if (ttype == 0x7f) {
++      /* special machine state frame saved by STACK_DUMMY */
++      tf->nParms = 0;
++      tf->firstReg = 16;
++      tf->firstRLoc = 0;
++      rt_next_pc = read_memory_integer(frame + 64 - 64, 4);
++      rt_next_frame = read_memory_integer(frame -64 + 13*4, 4);
++      return 0;
++     }
++     else {
++      /* C program, I hope */
++      nparms = (read_memory_integer(newpc+2, 1) >> 4) & 0x0f;
++      firstreg = ((tc=read_memory_integer(newpc+1, 1)) >> 4) & 0x0f;
++      optx = ((tc&4)? 1 : 0); /* flags says if floating registers described */
++      offtype = read_memory_integer(newpc+optx+3, 1) & 0xff;
++      if ((offtype & 0xc0) == 0) {
++          /* 6 bits of local offset */
++          offset = offtype & 0x3f;
++      }
++      else if ((offtype & 0xc0) == 0x40) {
++          /* 14 bits of local offset */
++          offset = (offtype & 0x3f) << 8;
++          offset += (read_memory_integer(newpc+optx+4, 1) & 0xff);
++      }
++      else if ((offtype & 0xc0) == 0x80) {
++          /* 22 bits of local offset */
++          offset = (offtype & 0x3f) << 8;
++          offset += (read_memory_integer(newpc+optx+4, 1) & 0xff);
++          offset <<= 8;
++          offset += (read_memory_integer(newpc+optx+5, 1) & 0xff);
++      }
++      else if ((offtype & 0xc0) == 0xc0) {
++          /* 30 bits of local offset */
++          offset = (offtype & 0x3f) << 8;
++          offset += (read_memory_integer(newpc+optx+4, 1) & 0xff);
++          offset <<= 8;
++          offset += (read_memory_integer(newpc+optx+5, 1) & 0xff);
++          offset <<= 8;
++          offset += (read_memory_integer(newpc+optx+6, 1) & 0xff);
++      }
++      offset <<= 2;
++      tf->nParms = nparms;
++      tf->firstReg = firstreg;
++      tf->firstRLoc = frame   /* initial frame location */
++          + offset                            /* to top of frame */
++          - 36                                /* pascal static link, incomings args and linkage */
++          - (4*(16-firstreg));        /* space used by general regs */
++      rt_next_pc = read_memory_integer(tf->firstRLoc + 4*(15-firstreg), 4);
++      rt_next_frame = read_memory_integer(tf->firstRLoc + 4*(13-firstreg), 4);
++      return 0;
++     }
++ }
++ 
++ recache_frames() {
++     register long i, j;
++     long pc;
++     CORE_ADDR curfp;
++     struct rt_frame *tf;
++ 
++     pc = read_pc();
++     curfp = current_frame;
++     rtCount = 0;
++     /* these next special cases can only occur with frame #0; others can't make calls
++         in these intermediate states.
++     */
++     /* if pc points at br or brx, we're doing a return, so set the pc to the target */
++     i=read_memory_integer(pc, 2);
++     if ((i & 0xfe00) == 0xe800) {
++      /* we're looking at a br or brx instruction */
++      pc = read_register(i&0x0f);
++     }
++     /* also, if pc points at d9xx or c111 we're in the middle of a frame push, and should
++        use r15 for the pc.
++    */
++    if ((i & 0xff00) == 0xd900 || (i & 0xffff) == 0xc111) {
++      pc = read_register(15);
++    }
++     while (1) {
++      if (curfp <= 0x10000000 || curfp >= 0x20000000) break;
++      if (pc > 0x20000000) break;
++      /* otherwise try to add a new frame structure */
++      if (rtCount >= rtTTSize) break;
++      tf = &rtFrames[rtCount++];
++      tf->frame = curfp;
++      tf->pc = pc;
++      i = rt_num_regs(pc, tf);
++      if (i<0) {      /* exceptional values */
++          rtCount--;          /* last frame was bogus */
++          break;
++      }
++      /* now setup for next iteration */
++      pc = rt_next_pc;
++      curfp = rt_next_frame;
++     }
++ }
++ 
++ struct rt_frame *get_cached_frame(aframe)
++ CORE_ADDR aframe; {
++     register int i;
++     for(i=0;i<rtCount;i++) {
++      if (rtFrames[i].frame == aframe) return &rtFrames[i];
++     }
++     return 0;
++ }
++ 
++ long rt_prev_frame(frame)
++ register CORE_ADDR frame; {
++     register int i;
++     for(i=0;i<rtCount-1;i++) {
++      if (rtFrames[i].frame == frame) return rtFrames[i+1].frame;
++     }
++     return 0;
++ }
++ 
++ long rt_frame_reg(frame, reg)
++ CORE_ADDR frame;
++ register long reg; {
++     register struct rt_frame *tf;
++     tf = get_cached_frame(frame);
++     if (tf == 0) return 0;
++     if (tf->firstReg > reg) return 0;        /* didn't save this one! */
++     return read_memory_integer(tf->firstRLoc + 4 * (reg - tf->firstReg), 4);
++ }
++ 
++ long rt_frame_args(frame)
++ CORE_ADDR frame; {
++     register struct rt_frame *tf;
++     tf = get_cached_frame(frame);
++     if (!tf) return 0;
++     return tf->firstRLoc + 20 + 4*(16 - tf->firstReg);
++ }
++ #endif
++ 
++ blockinitialize() {initialize();}
++ 
+  static
+  initialize ()
+  {
++ #ifdef ibm032
++ #ifdef CAMPHOR
++   add_com ("recache-frames", class_stack, recache_frames,
++       "Tell debugger to recompute PC/RT stack frame cache\n");
++ #endif
++ #endif
+  }
+  
+  END_FILE
+diff -c ../../gnu/gdb/breakpoint.c ./breakpoint.c
+*** ../../gnu/gdb/breakpoint.c Sat Apr  4 22:22:44 1987
+--- ./breakpoint.c     Sun Apr 26 23:02:20 1987
+***************
+*** 94,99 ****
+--- 94,100 ----
+     of last breakpoint hit.  */
+  
+  struct command_line *breakpoint_commands;
++ char new_breakpoint_commands = 0; /* Zalman Stern, ITC 1/12/1987 */
+  
+  START_FILE
+  
+***************
+*** 203,210 ****
+      {
+        execute_command (breakpoint_commands->line, 0);
+        /* If command was "cont", breakpoint_commands is 0 now.  */
+!       if (breakpoint_commands)
+       breakpoint_commands = breakpoint_commands->next;
+      }
+    clear_momentary_breakpoints ();
+  }
+--- 204,213 ----
+      {
+        execute_command (breakpoint_commands->line, 0);
+        /* If command was "cont", breakpoint_commands is 0 now.  */
+!       if (breakpoint_commands && !new_breakpoint_commands) /* Zalman Stern, ITC 1/12/1987 */
+       breakpoint_commands = breakpoint_commands->next;
++       else /* Zalman Stern, ITC 1/12/1987 */
++         new_breakpoint_commands = 0; /* Zalman Stern, ITC 1/12/1987 */
+      }
+    clear_momentary_breakpoints ();
+  }
+***************
+*** 215,220 ****
+--- 218,225 ----
+  void
+  clear_breakpoint_commands ()
+  {
++   if (breakpoint_commands != 0) /* Zalman Stern, ITC 1/12/1987 */
++     new_breakpoint_commands = 1; /* Zalman Stern, ITC 1/12/1987 */
+    breakpoint_commands = 0;
+    breakpoint_auto_delete (0);
+  }
+***************
+*** 921,926 ****
+--- 926,933 ----
+  struct cmd_list_element *enablelist;
+  
+  extern struct cmd_list_element *cmdlist;
++ 
++ breakinitialize() {initialize();}
+  
+  static
+  initialize ()
+diff -c ../../gnu/gdb/command.c ./command.c
+*** ../../gnu/gdb/command.c    Sat Apr  4 22:24:07 1987
+--- ./command.c        Sat Apr 25 17:18:15 1987
+***************
+*** 94,100 ****
+  You are forbidden to forbid anyone else to use, share and improve
+  what you give them.   Help stamp out software-hoarding!  */
+  
+- 
+  #include "command.h"
+  #include <stdio.h>
+  
+--- 94,99 ----
+***************
+*** 388,394 ****
+      {
+        if (nfound > 1 && allow_unknown >= 0)
+       {
+!        *p = 0;
+         ambbuf[0] = 0;
+         for (c = list; c; c = c->next)
+           if (!strncmp (*line, c->name, p - *line))
+--- 387,393 ----
+      {
+        if (nfound > 1 && allow_unknown >= 0)
+       {
+!           *p = 0;
+         ambbuf[0] = 0;
+         for (c = list; c; c = c->next)
+           if (!strncmp (*line, c->name, p - *line))
+diff -c ../../gnu/gdb/core.c ./core.c
+*** ../../gnu/gdb/core.c       Sat Apr  4 22:27:23 1987
+--- ./core.c   Mon Apr 27 13:20:47 1987
+***************
+*** 163,172 ****
+       int reg_offset;
+  
+       /* 4.2bsd-style core dump */
+       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;
+--- 163,180 ----
+       int reg_offset;
+  
+       /* 4.2bsd-style core dump */
++ #ifdef ibm032
++      /* on ibm032, uarea is at the far end of the u pages */
++      lseek(corechan, UPAGES*NBPG - sizeof(u), 0);
++ #endif
+       val = myread (corechan, &u, sizeof u);
+       if (val < 0)
+!        perror_with_name (execfile);
+! #ifdef ibm032
+!      data_start = 0x10000000;
+! #else
+       data_start = exec_data_start;
++ #endif
+       data_end = data_start + NBPG * u.u_dsize;
+       stack_start = stack_end - NBPG * u.u_ssize;
+       data_offset = NBPG * UPAGES;
+***************
+*** 208,214 ****
+         corefile = concat (dirname, "/", filename);
+       }
+  
+!       set_current_frame (read_register (FP_REGNUM));
+        select_frame (get_current_frame (), 0);
+        validate_files ();
+      }
+--- 216,222 ----
+         corefile = concat (dirname, "/", filename);
+       }
+  
+!       set_current_frame (read_register (FP_REGNUM), 1);
+        select_frame (get_current_frame (), 0);
+        validate_files ();
+      }
+***************
+*** 523,528 ****
+--- 531,539 ----
+  
+  #endif /* not NEW_SUN_CORE */
+  \f
++ 
++ coreinitialize() {initialize();}
++ 
+  static
+  initialize ()
+  {
+diff -c ../../gnu/gdb/dbxread.c ./dbxread.c
+*** ../../gnu/gdb/dbxread.c    Sat Apr  4 22:29:54 1987
+--- ./dbxread.c        Fri May 15 15:52:24 1987
+***************
+*** 28,33 ****
+--- 28,36 ----
+  #include "initialize.h"
+  #include "symtab.h"
+  #include "param.h"
++ #ifdef CAMPHOR
++ #include "value.h"
++ #endif
+  
+  static void add_symbol_to_list ();
+  static void read_dbx_symtab ();
+***************
+*** 89,94 ****
+--- 92,109 ----
+    int prev_line_number;
+  };
+  
++ /*  When dealing with dynamically loaded objects, the symbol table in the sym file
++     does not match where we actually load the files.  Thus, gdb has to relocate those
++     symbols during dbxread.  This is only used by the camphor support code, and
++     probably should be under an ifdef camphor.  */
++ 
++ struct dlreloc
++   {
++     long text;
++     long data;
++     long bss;
++   } dlreloc;
++ 
+  static struct subfile *subfiles;
+  
+  static struct subfile *current_subfile;
+***************
+*** 1015,1020 ****
+--- 1030,1037 ----
+    register int i, nbl;
+    register struct blockvector *bv;
+    register struct block *b;
++   int j;
++   struct symbol *ts1, *ts2;
+  
+    for (s = symtab_list; s; s = s->next)
+      {
+***************
+*** 1025,1034 ****
+--- 1042,1238 ----
+         b = BLOCKVECTOR_BLOCK (bv, i);
+         qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
+                sizeof (struct symbol *), compare_symbols);
++           /* Register parms have two decls, but the register one is the only one of interest */
++        /* So, trash the name of the bad one, since binary srch could get either.  Yucko. */
++        /* doing name this way enables symbol freeing code to keep working */
++           for(j=1;j<BLOCK_NSYMS(b);j++)
++           {
++              ts1 = BLOCK_SYM(b,j-1);
++                 ts2 = BLOCK_SYM(b, j);
++              if (SYMBOL_NAMESPACE(ts1) == VAR_NAMESPACE
++               && SYMBOL_NAMESPACE(ts2) == VAR_NAMESPACE
++               && strcmp(SYMBOL_NAME(ts1), SYMBOL_NAME(ts2)) == 0)
++                {if (SYMBOL_CLASS(ts1) == LOC_REGISTER)
++                  {SYMBOL_CLASS(ts2) = LOC_REGISTER;
++                  SYMBOL_TYPE(ts2) = SYMBOL_TYPE(ts1);
++                  SYMBOL_VALUE(ts2) = SYMBOL_VALUE(ts1);
++                  }
++                else if (SYMBOL_CLASS(ts2) == LOC_REGISTER )
++                  {SYMBOL_CLASS(ts1) = LOC_REGISTER;
++                  SYMBOL_TYPE(ts1) = SYMBOL_TYPE(ts2);
++                  SYMBOL_VALUE(ts1) = SYMBOL_VALUE(ts2);
++                  }
++ #ifdef notdef
++                else printf("Check out def of symbol %s\n", SYMBOL_NAME(ts1));
++ #endif
++                }
++           }
+       }
+      }
+  }
+  \f
++ 
++ #ifdef CAMPHOR
++ set_rel_command(exp)
++       char *exp;
++ {
++   struct expression *expr = (struct expression *) parse_c_expression (exp);
++   register value val;
++   register long temp;
++   register struct cleanup *old_chain
++     = make_cleanup (free_current_contents, &expr);
++   val = evaluate_expression (expr);
++   temp = value_as_long (val);
++   dlreloc.text = dlreloc.data = dlreloc.bss = temp;
++   printf("Relocation for all segs set to %x.\n", temp);
++   do_cleanups (old_chain);
++ }
++ 
++ void
++ add_file_command (name)
++      char *name;
++ {
++   register int desc;
++   struct exec hdr;
++   struct nlist *nlist;
++   char *stringtab;
++   long buffer;
++   register int val;
++   extern void close ();
++   struct cleanup *old_chain;
++   int in_this_dir = 1;
++   struct symtab *symtab_temp;
++ 
++   dont_repeat ();
++ 
++   if (name == 0)
++     error_no_arg ("file to add symbols from");
++ 
++   if (symtab_list && !query ("Add more symbols from \"%s\"? ", name))
++     error ("Not confirmed.");
++ 
++   if (symfile)
++     free (symfile);
++   symfile = 0;
++ 
++   desc = open (name, 0);
++   if (desc < 0)
++     {
++       if ((desc = openp (getenv ("BZPATH"), name, 0, 0)) < 0)
++         if ((desc = openp (getenv ("CLASSPATH"), name, 0, 0)) < 0)
++           desc = openp (getenv ("PATH"), name, 0, 0);
++ 
++       in_this_dir = 0;
++     }
++   if (desc < 0)
++     perror_with_name (name);
++ 
++   old_chain = make_cleanup (close, 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);
++ 
++   if (hdr.a_syms == 0)
++     {
++       free_all_symtabs ();           /* check this */
++       return;
++     }
++ 
++   /* Now read the string table, all at once.  */
++   val = lseek (desc, N_SYMOFF (hdr) + hdr.a_syms, 0);
++   if (val < 0)
++     perror_with_name (name);
++   val = myread (desc, &buffer, sizeof buffer);
++   if (val < 0)
++     perror_with_name (name);
++   stringtab = (char *) alloca (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 ();
++ #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, N_SYMOFF (hdr), 0);
++   if (val < 0)
++     perror_with_name (name);
++ 
++   printf ("Reading symbol data from %s...", name);
++   fflush (stdout);
++ 
++   init_misc_functions ();
++   make_cleanup (discard_misc_bunches, 0);
++   init_header_files ();
++   make_cleanup (free_header_files, 0);
++ 
++  /* Remember symtab_list to check if the added file had any dbx info in it. */
++   symtab_temp = symtab_list;
++ 
++   /* 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, hdr.a_syms / sizeof (struct nlist));
++ 
++   if (symtab_list == symtab_temp) {
++     printf("\n%s not compiled with -g, debugging posibilities are limited.\n", name);
++     fflush(stdout);
++   }
++   else {
++ 
++   /* Sort symbols alphabetically within each block.  */
++ 
++     sort_syms ();
++ 
++   /* Go over the misc functions and install them in vector.  */
++ 
++     condense_misc_bunches ();
++ 
++   /* Make a default for file to list.  */
++ 
++     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;
++     }
++ 
++   if (in_this_dir && name[0] != '/')
++     {
++       char dirname[MAXPATHLEN];
++ 
++       getwd (dirname);
++       symfile = concat (dirname, "/",
++                      savestring (name, strlen (name)));
++     }
++   else
++     symfile = savestring (name, strlen (name));
++ 
++   printf ("done.\n");
++   fflush (stdout);
++ }
++ #endif
++ 
+  /* This is the symbol-file command.  Read the file, analyze its symbols,
+     and add a struct symtab to symtab_list.  */
+  
+***************
+*** 1047,1052 ****
+--- 1251,1263 ----
+  
+    dont_repeat ();
+  
++ #ifdef CAMPHOR
++   /* this command does not deal with automatically relocated stuff */
++   dlreloc.text = 0;
++   dlreloc.data = 0;
++   dlreloc.bss = 0;
++ #endif
++ 
+    if (name == 0)
+      error_no_arg ("file to read symbols from");
+  
+***************
+*** 1130,1151 ****
+  
+    read_dbx_symtab (desc, stringtab, hdr.a_syms / sizeof (struct nlist));
+  
+    /* 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);
+--- 1341,1372 ----
+  
+    read_dbx_symtab (desc, stringtab, hdr.a_syms / sizeof (struct nlist));
+  
++   /* Check to make sure file was compiled with -g. */
++ 
++   if (symtab_list == NULL) {
++     printf("\n%s not compiled with -g, debugging posibilities are limited.\n", name);
++     fflush(stdout);
++   }
++   else {
++ 
+    /* 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);
+***************
+*** 1204,1209 ****
+--- 1425,1440 ----
+      {
+        fread (&buf, sizeof buf, 1, stream);
+        namestring = buf.n_un.n_strx ? buf.n_un.n_strx + stringtab : 0;
++ #ifdef CAMPHOR
++       if ((buf.n_type & N_TYPE) == N_UNDF) {
++        /* don't screw around with undefined symbols */
++       }
++       else {
++      if ((buf.n_type & N_TYPE) == N_TEXT) buf.n_value += dlreloc.text;
++      else if ((buf.n_type & N_TYPE) == N_DATA) buf.n_value += dlreloc.data;
++      else if ((buf.n_type & N_TYPE) == N_BSS) buf.n_value += dlreloc.bss;
++       }
++ #endif
+        if (buf.n_type & N_STAB)
+       process_one_symbol (buf.n_type, buf.n_desc,
+                           buf.n_value, namestring);
+***************
+*** 1356,1361 ****
+--- 1587,1596 ----
+      }
+  }
+  \f
++ #ifdef ibm032
++ static  char hcState;                /* two different, incompatible compilers for the RT */
++ #endif
++   
+  static void
+  process_one_symbol (type, desc, value, name)
+       int type, desc;
+***************
+*** 1363,1369 ****
+       char *name;
+  {
+    register struct context_stack *new;
+!   
+    /* Something is wrong if we see real data before
+       seeing a source file name.  */
+    
+--- 1598,1633 ----
+       char *name;
+  {
+    register struct context_stack *new;
+!   char tname[256];
+!   /* Now, there are two compilers for the RT, and they are seriously incompatible.
+!       pcc is just like normal c compilers: stabs for a block occur before the LBRAC
+!       stab for that same block.  Thus this code squirrels them away in the context
+!       and when the RBRAC is hit, restores local_symbols as of the time the LBRAC
+!       was encountered, and adds these symbosl to the block that just ended.
+!       
+!       However, with the HC compiler, those symbols occur *after* the LBRAC symbol
+!       declaring the block's start.  Totally incompatible, of course.  One expects no
+!       less from IBM.  For hc compiled  programs, we use the symbols in local_symbols
+!       *before* the RBRAC command pops the context stack.
+!       
+!       Amazingly enough, when we complained to IBM/Palo Alto about this incompatibility,
+!       they claimed that Mark Linton (original author of dbx) liked the new way better, and
+!       that he didn't even know that pcc used a different order.  Sorta explains some things
+!       about dbx, n'est-ce pas?  Furthermore, of course, IBM  doesn't want to change
+!       either pcc or hc.
+! 
+!       Anyway, hc and pcc compiled .o files often co-exist in programs.  How do we
+!       tell which is which?  Stupid heuristic which doesn't work with programs
+!       with no top-level locals or parameters: after seeing a function's start, if we see
+!       an LBRAC before seeing a variable, then we are using hc, otherwise it is pcc.
+!       Stupid heuristics are better than none, so we use it.
+!       
+!       The variable hcState is used to keep track of this crap.
+!       0 ==> saw function symbol
+!       1 ==> saw lbrac in state 0, this is hc.
+!       2 ==> saw symbol in state 0, this is pcc.
+!   */
+! 
+    /* Something is wrong if we see real data before
+       seeing a source file name.  */
+    
+***************
+*** 1384,1389 ****
+--- 1648,1656 ----
+        also the end of the lexical context for the previous function.  */
+        new = context_stack;
+        within_function = 1;
++ #ifdef ibm032
++       hcState = 0;
++ #endif
+        if (new)
+       {
+         /* Make a block for the local symbols within.  */
+***************
+*** 1400,1406 ****
+--- 1667,1679 ----
+        new->locals = 0;
+        new->old_blocks = pending_blocks;
+        new->start_addr = value;
++ #ifdef ibm032
++       strcpy(tname, ".");
++       strcat(tname, name);
++       new->name = define_symbol(value, tname);
++ #else
+        new->name = define_symbol (value, name);
++ #endif
+        local_symbols = 0;
+        break;
+  
+***************
+*** 1407,1412 ****
+--- 1680,1688 ----
+      case N_LBRAC:
+        /* This "symbol" just indicates the start of an inner lexical
+        context within a function.  */
++ #ifdef ibm032
++       if (hcState == 0) hcState = 1;
++ #endif
+        new = (struct context_stack *) xmalloc (sizeof (struct context_stack));
+        new->depth = desc;
+        new->next = context_stack;
+***************
+*** 1422,1430 ****
+        /* This "symbol" just indicates the end of an inner lexical
+        context that was started with N_RBRAC.  */
+        new = context_stack;
+        if (new == 0 || desc != new->depth)
+       error ("Invalid symbol data: N_LBRAC/N_RBRAC symbol mismatch, symtab pos %d.", symnum);
+-       local_symbols = new->locals;
+        context_stack = new->next;
+        /* If this is not the outermost LBRAC...RBRAC pair in the
+        function, its local symbols preceded it, and are the ones
+--- 1698,1711 ----
+        /* This "symbol" just indicates the end of an inner lexical
+        context that was started with N_RBRAC.  */
+        new = context_stack;
++ #ifdef ibm032
++       if (hcState == 2)      /* pcc */
++        local_symbols = new->locals;
++ #else
++       local_symbols = new->locals;
++ #endif
+        if (new == 0 || desc != new->depth)
+       error ("Invalid symbol data: N_LBRAC/N_RBRAC symbol mismatch, symtab pos %d.", symnum);
+        context_stack = new->next;
+        /* If this is not the outermost LBRAC...RBRAC pair in the
+        function, its local symbols preceded it, and are the ones
+***************
+*** 1443,1448 ****
+--- 1724,1733 ----
+                       new->start_addr + last_source_start_addr,
+                       value + last_source_start_addr);
+       }
++ #ifdef ibm032
++       if (hcState == 1 && context_stack->next)       /* hc */
++         local_symbols = new->locals;         /* now we get them */
++ #endif
+        free (new);
+        break;
+  
+***************
+*** 1493,1498 ****
+--- 1778,1786 ----
+        break;
+  
+      default:
++ #ifdef ibm032
++       if (hcState == 0) hcState = 2;
++ #endif
+        if (name)
+       define_symbol (value, name);
+      }
+***************
+*** 1553,1558 ****
+--- 1841,1849 ----
+        Dbx data never actually contains 'l'.  */
+      case 'l':
+        SYMBOL_CLASS (sym) = LOC_LOCAL;
++ #ifdef ibm032
++       if (hcState == 1) value += 1000000;            /* temporary hack until rel 3 pcc matches hc */
++ #endif
+        SYMBOL_VALUE (sym) = value;
+        SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+        add_symbol_to_list (sym, &local_symbols);
+***************
+*** 1572,1577 ****
+--- 1863,1875 ----
+        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;
+***************
+*** 1616,1622 ****
+        break;
+  
+      default:
+!       error ("Invalid symbol data: unknown symbol-type code `%c' at symtab pos %d.", deftype, symnum);
+      }
+    return sym;
+  }
+--- 1914,1928 ----
+        break;
+  
+      default:
+!       printf ("Unknown symbol-type code '%c' in dbx symbol table, assuming local.\n", deftype);
+!       SYMBOL_CLASS (sym) = LOC_LOCAL;
+! #ifdef ibm032
+!       if (hcState == 1) value += 1000000;            /* temporary hack until rel 3 pcc matches hc */
+! #endif
+!       SYMBOL_VALUE (sym) = value;
+!       SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+!       add_symbol_to_list (sym, &local_symbols);      
+!       break;
+      }
+    return sym;
+  }
+***************
+*** 1741,1746 ****
+--- 2047,2056 ----
+       (*pp) += 5;
+        else if (!strncmp (*pp, "r(0,1);0;", 9))
+       (*pp) += 9;
++ #if 1
++       else if ((**pp == 'r') && (!strncmp(*pp + 2, ";0;", 3)))
++         (*pp) += 5;
++ #endif
+        else break;
+  
+        TYPE_CODE (type) = TYPE_CODE_ARRAY;
+***************
+*** 1980,1986 ****
+       rather than -128 which is what I would like.
+       So use n1 != 0 to prevent char from being taken as unsigned.  */
+  
+!   else if (n2 == 0 && n1 == 1)
+      {
+        /* an unsigned type */
+        if (n3 == (1 << (8 * sizeof (int))))
+--- 2290,2296 ----
+       rather than -128 which is what I would like.
+       So use n1 != 0 to prevent char from being taken as unsigned.  */
+  
+!   if (n2 == 0)
+      {
+        /* an unsigned type */
+        if (n3 == (1 << (8 * sizeof (int))))
+***************
+*** 1989,1994 ****
+--- 2299,2306 ----
+       return builtin_type_unsigned_short;
+        if (n3 == (1 << (8 * sizeof (char))))
+       return builtin_type_unsigned_char;
++       if (n3 == (1 << (8 * sizeof (char) - 1)))
++      return builtin_type_char;
+      }
+    else
+      {
+***************
+*** 2002,2007 ****
+--- 2314,2321 ----
+        if (n3 == (1 << (8 * sizeof (char) - 1)))
+       return builtin_type_char;
+      }
++    if (n2 == 0 && n3 == 1)
++     return builtin_type_void;
+    error ("Invalid symbol data: range type spec %s at symtab pos %d.",
+        errp - 1, symnum);
+  }
+***************
+*** 2033,2040 ****
+--- 2347,2364 ----
+  
+    /* Read the digits, as far as they go.  */
+  
++ #if 0 /* Yet another "Compiler sucks" fix. */
+    while ((c = *p++) >= '0' && c <= '9')
++ #else
++   while (((c = *p++) >= '0' && c <= '9') || ((end != '\n') && (c == '\n')))
++ #endif
+      {
++ #if 1
++       if (c == '\n') {
++         printf("Ignoring bogus newline in stabs entry. Your compiler should be fixed.\n");
++         continue;
++       }
++ #endif
+        n *= 10;
+        n += c - '0';
+      }
+***************
+*** 2050,2060 ****
+--- 2374,2392 ----
+    return n * sign;
+  }
+  
++ dbxinitialize() {initialize();}
++ 
+  static
+  initialize ()
+  {
+    symfile = 0;
+  
++ #ifdef CAMPHOR
++   add_com ("add-file", class_files, add_file_command,
++            "Add a new symbol table (in dbx format) from file FILE.");
++   add_com("set-rel", class_files, set_rel_command,
++            "Set relocation for add-file command to NUMBER.");
++ #endif
+    add_com ("symbol-file", class_files, symbol_file_command,
+          "Load symbol table (in dbx format) from executable file FILE.");
+  }
+diff -c ../../gnu/gdb/environ.c ./environ.c
+*** ../../gnu/gdb/environ.c    Sat Apr  4 22:31:16 1987
+--- ./environ.c        Sun Apr 26 23:48:05 1987
+***************
+*** 129,135 ****
+  
+    if (e->allocated < i)
+      {
+!       e->allocated = max (i, e->allocated + 10);
+        e->vector = (char **) xrealloc (e->vector,
+                                     (e->allocated + 1) * sizeof (char *));
+      }
+--- 129,136 ----
+  
+    if (e->allocated < i)
+      {
+!       e->allocated = i + 10;
+        e->vector = (char **) xrealloc (e->vector,
+                                     (e->allocated + 1) * sizeof (char *));
+      }
+diff -c ../../gnu/gdb/eval.c ./eval.c
+*** ../../gnu/gdb/eval.c       Sat Apr  4 22:32:36 1987
+--- ./eval.c   Mon Apr 27 00:01:27 1987
+***************
+*** 546,551 ****
+--- 546,553 ----
+      }
+  }
+  \f
++ evalinitialize() {initialize();}
++ 
+  static
+  initialize ()
+  { }
+diff -c ../../gnu/gdb/expread.y ./expread.y
+*** ../../gnu/gdb/expread.y    Sat Apr  4 22:35:27 1987
+--- ./expread.y        Sun Apr 26 23:56:51 1987
+***************
+*** 650,655 ****
+--- 650,656 ----
+           ;
+         else
+           {
++            /*N.B. error does a longjmp, so we do not have to worry about storage */
+             err_copy = (char *) alloca (olen + 1);
+             bcopy (lexptr, err_copy, olen);
+             err_copy[olen] = 0;
+***************
+*** 945,953 ****
+  {
+    register int len = sizeof (struct expression) +
+                                   expr->nelts * sizeof (union exp_element);
+!   register struct expression *temp
+!     = (struct expression *) alloca (len);
+    register int inpos = expr->nelts, outpos = 0;
+  
+    /* Copy the original expression into temp.  */
+    bcopy (expr, temp, len);
+--- 946,955 ----
+  {
+    register int len = sizeof (struct expression) +
+                                   expr->nelts * sizeof (union exp_element);
+!   register struct expression *temp;
+    register int inpos = expr->nelts, outpos = 0;
++ 
++   temp = (struct expression *) alloca(len);
+  
+    /* Copy the original expression into temp.  */
+    bcopy (expr, temp, len);
+diff -c ../../gnu/gdb/findvar.c ./findvar.c
+*** ../../gnu/gdb/findvar.c    Sat Apr  4 22:36:38 1987
+--- ./findvar.c        Mon Apr 27 00:01:44 1987
+***************
+*** 359,364 ****
+--- 359,366 ----
+    return value_cast (lookup_pointer_type (SYMBOL_TYPE (var)),
+                    value_from_long (builtin_type_long, addr));
+  }
++ \f
++ findinitialize() {initialize();}
+  
+  static
+  initialize ()
+diff -c ../../gnu/gdb/firstfile.c ./firstfile.c
+*** ../../gnu/gdb/firstfile.c  Sat Apr  4 22:37:06 1987
+--- ./firstfile.c      Mon Apr 27 00:02:06 1987
+***************
+*** 125,130 ****
+--- 125,152 ----
+  static initialize_dummy_1 ();
+  static initialize_dummy_2 ();
+  
++ initialize_all_files() {
++     blockinitialize();
++     breakinitialize();
++     coreinitialize();
++     dbxinitialize();
++     evalinitialize();
++     findinitialize();
++     infcmdinitialize();
++     inflowinitialize();
++     infruninitialize();
++     symmiscinitialize();
++     symtabinitialize();
++     valarithinitialize();
++     valopsinitialize();
++     valprintinitialize();
++     valuesinitialize();
++     printcmdinitialize();
++     sourceinitialize();
++     stackinitialize();
++ }
++ 
++ #if 0
+  initialize_all_files ()
+  {
+    initialize_next_file ((char *) initialize_dummy_2
+***************
+*** 148,153 ****
+--- 170,176 ----
+  initialize_dummy_2 ()
+  {
+  }
++ #endif
+  
+  /* This makes the function initialize_next_file.  */
+  
+diff -c ../../gnu/gdb/frame.h ./frame.h
+*** ../../gnu/gdb/frame.h      Sat Apr  4 22:37:22 1987
+--- ./frame.h  Mon Apr 27 00:02:14 1987
+***************
+*** 20,25 ****
+--- 20,35 ----
+  
+  /* Note that frame.h requires param.h! */
+  
++ #ifdef ibm032
++ struct rt_frame {
++     CORE_ADDR frame;         /* frame address */
++     CORE_ADDR pc;                    /* pc we called from */
++     CORE_ADDR firstRLoc;     /* loc'n of first saved general reg */
++     short nParms;                    /* number of parameters to this frame */
++     short firstReg;                  /* the reg stored at 64(fp) */
++ };
++ #endif
++ 
+  #define FRAME CORE_ADDR
+  
+  struct frame_info
+***************
+*** 62,64 ****
+--- 72,77 ----
+  extern struct block *get_selected_block ();
+  extern struct symbol *get_frame_function ();
+  extern struct symbol *get_pc_function ();
++ #ifdef ibm032
++ extern struct rt_frame *get_cached_frame();
++ #endif
+diff -c ../../gnu/gdb/infcmd.c ./infcmd.c
+*** ../../gnu/gdb/infcmd.c     Sat Apr  4 22:47:22 1987
+--- ./infcmd.c Mon Apr 27 00:07:53 1987
+***************
+*** 39,45 ****
+  /* String containing arguments to give to the program,
+     with a space added at the front.  Just a space means no args.  */
+  
+! static char *inferior_args;
+  
+  /* Pid of our debugged inferior, or 0 if no inferior now.  */
+  
+--- 39,45 ----
+  /* String containing arguments to give to the program,
+     with a space added at the front.  Just a space means no args.  */
+  
+! static char *inferior_args = NULL;
+  
+  /* Pid of our debugged inferior, or 0 if no inferior now.  */
+  
+***************
+*** 112,119 ****
+  set_args_command (args)
+       char *args;
+  {
+!   free (inferior_args);
+!   if (!args) args = "";
+    inferior_args = concat (" ", args, "");
+  }
+  
+--- 112,121 ----
+  set_args_command (args)
+       char *args;
+  {
+!   if (inferior_args != NULL)
+!     free (inferior_args);
+!   if (!args)
+!     args = "";
+    inferior_args = concat (" ", args, "");
+  }
+  
+***************
+*** 171,177 ****
+        signal (SIGINT, SIG_DFL);  */
+  
+        ptrace (0);
+!       execle ("/bin/sh", "sh", "-c", allargs, 0,
+             environ_vector (inferior_environ));
+  
+        fprintf (stderr, "Cannot exec /bin/sh: %s.\n",
+--- 173,180 ----
+        signal (SIGINT, SIG_DFL);  */
+  
+        ptrace (0);
+! 
+!       execle ("/bin/csh", "csh", "-f", "-c", allargs, 0,
+             environ_vector (inferior_environ));
+  
+        fprintf (stderr, "Cannot exec /bin/sh: %s.\n",
+***************
+*** 473,478 ****
+--- 476,482 ----
+  
+        retbuf[0] = stop_r0;
+        retbuf[1] = stop_r1;
++ 
+        val = value_being_returned (value_type, retbuf);
+        printf ("Value returned is $%d = ", record_latest_value (val));
+        value_print (val, stdout);
+***************
+*** 705,710 ****
+--- 709,716 ----
+    printf ("Contents are relative to selected stack frame.\n");
+  }
+  \f
++ infcmdinitialize() {initialize();}
++ 
+  static
+  initialize ()
+  {
+diff -c ../../gnu/gdb/inflow.c ./inflow.c
+*** ../../gnu/gdb/inflow.c     Sat Apr  4 22:56:34 1987
+--- ./inflow.c Mon Apr 27 00:12:10 1987
+***************
+*** 188,194 ****
+    inferior_pid = 0;
+    mark_breakpoints_out ();
+    if (have_core_file_p ())
+!     set_current_frame (read_register (FP_REGNUM));
+  }
+  
+  /* Resume execution of the inferior process.
+--- 188,194 ----
+    inferior_pid = 0;
+    mark_breakpoints_out ();
+    if (have_core_file_p ())
+!     set_current_frame (read_register (FP_REGNUM), 1);
+  }
+  
+  /* Resume execution of the inferior process.
+***************
+*** 266,271 ****
+--- 266,274 ----
+    char buf[MAX_REGISTER_RAW_SIZE];
+    register int i;
+  
++ #ifdef ibm032
++   offset += UPAGES*NBPG - sizeof(u); /* ibm032: ustruct at end of uarea */
++ #endif
+    offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
+    for (regno = 0; regno < NUM_REGS; regno++)
+      {
+***************
+*** 291,296 ****
+--- 294,303 ----
+    register unsigned int regaddr;
+    char buf[80];
+  
++ #ifdef ibm032
++   offset += UPAGES*NBPG - sizeof(u); /* ibm032: ustruct at end of uarea */
++ #endif
++ 
+    offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
+  
+    if (regno >= 0)
+***************
+*** 340,347 ****
+    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);
+--- 347,355 ----
+    register int count
+      = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+    /* Allocate buffer of that many longwords.  */
+!   register int *buffer;
+  
++   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);
+***************
+*** 367,377 ****
+    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]
+--- 375,386 ----
+    register int count
+      = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+    /* Allocate buffer of that many longwords.  */
+!   register int *buffer;
+    extern int errno;
+  
+    /* Fill start and end extra bytes of buffer with existing memory data.  */
+  
++   buffer = (int *) alloca (count * sizeof (int));
+    buffer[0] = ptrace (1, inferior_pid, addr, 0);
+    if (count > 1)
+      buffer[count - 1]
+***************
+*** 388,397 ****
+      {
+        errno = 0;
+        ptrace (4, inferior_pid, addr, buffer[i]);
+!       if (errno)
+       return 1;
+      }
+- 
+    return 0;
+  }
+  \f
+--- 397,406 ----
+      {
+        errno = 0;
+        ptrace (4, inferior_pid, addr, buffer[i]);
+!       if (errno) {
+       return 1;
++      }
+      }
+    return 0;
+  }
+  \f
+***************
+*** 421,426 ****
+--- 430,437 ----
+      }
+  }
+  \f
++ inflowinitialize() {initialize();}
++ 
+  static
+  initialize ()
+  {
+diff -c ../../gnu/gdb/infrun.c ./infrun.c
+*** ../../gnu/gdb/infrun.c     Sat Apr  4 22:57:15 1987
+--- ./infrun.c Mon Apr 27 00:17:40 1987
+***************
+*** 257,263 ****
+        pc_changed = 0;
+        fetch_inferior_registers ();
+        stop_pc = read_pc ();
+!       set_current_frame (read_register (FP_REGNUM));
+        stop_frame = get_current_frame ();
+        stop_sp = read_register (SP_REGNUM);
+        another_trap = 0;
+--- 257,271 ----
+        pc_changed = 0;
+        fetch_inferior_registers ();
+        stop_pc = read_pc ();
+! #ifdef CAMPHOR
+!       /* if we're not going to stop, don't bother with a stack trace */
+!       if (WIFSTOPPED(w) && !signal_stop[WSTOPSIG(w)])
+!        set_current_frame(read_register(FP_REGNUM), 0);
+!       else
+!        set_current_frame(read_register(FP_REGNUM), 1);
+! #else
+!       set_current_frame (read_register (FP_REGNUM), 1);
+! #endif
+        stop_frame = get_current_frame ();
+        stop_sp = read_register (SP_REGNUM);
+        another_trap = 0;
+***************
+*** 688,700 ****
+  
+    /* Save the function value return registers
+       We might be about to restore their previous contents.  */
+!   stop_r0 = read_register (0);
+!   stop_r1 = read_register (1);
+  
+    if (stop_stack_dummy)
+      {
+        /* Pop the empty frame that contains the stack dummy.  */
+        POP_FRAME;
+        select_frame (read_register (FP_REGNUM), 0);
+      }
+  }
+--- 696,717 ----
+  
+    /* Save the function value return registers
+       We might be about to restore their previous contents.  */
+! #ifdef ibm032
+!     stop_r0 = read_register (2);
+!     stop_r1 = read_register (3);
+! #else
+!     stop_r0 = read_register (0);
+!     stop_r1 = read_register (1);
+! #endif
+  
+    if (stop_stack_dummy)
+      {
+        /* Pop the empty frame that contains the stack dummy.  */
++ #ifdef ibm032
++       POP_DUMMY_FRAME;
++ #else
+        POP_FRAME;
++ #endif
+        select_frame (read_register (FP_REGNUM), 0);
+      }
+  }
+***************
+*** 841,846 ****
+--- 858,865 ----
+    printf ("\nUse the \"handle\" command to change these tables.\n");
+  }
+  \f
++ infruninitialize() {initialize();}
++ 
+  static
+  initialize ()
+  {
+diff -c ../../gnu/gdb/initialize.h ./initialize.h
+*** ../../gnu/gdb/initialize.h Sat Apr  4 22:58:27 1987
+--- ./initialize.h     Sun May 24 00:19:21 1987
+***************
+*** 103,109 ****
+--- 103,120 ----
+     of the end of one object file's text to the start of the next
+     object file's text.  */
+  
++ /* Changed to use ifdefs on the machine type.  David Nichols, 11/28/86 */
++ #ifdef ibm032
++ #include "m-ibm032init.h"
++ #endif
++ 
++ #ifdef vax
+  #include "m-vaxinit.h"
++ #endif
++ 
++ #ifdef sun
++ #include "m-suninit.h"
++ #endif
+  
+  /* This is used to make a file's initialization function.
+     It calls another function named `initialize', which must
+diff -c ../../gnu/gdb/main.c ./main.c
+*** ../../gnu/gdb/main.c       Sat Apr  4 23:11:59 1987
+--- ./main.c   Mon Apr 27 00:27:21 1987
+***************
+*** 236,241 ****
+--- 236,243 ----
+    if (*p)
+      {
+        c = lookup_cmd (&p, cmdlist, "", 0);
++       if (c->function == 0)
++      error ("That is not a command, just a help topic.");
+        if (c->class == (int) class_user)
+       {
+         if (*p)
+***************
+*** 457,463 ****
+  \f
+  /* Add an element to the list of commands.  */
+  
+! void
+  add_com (name, class, fun, doc)
+       char *name;
+       int class;
+--- 459,465 ----
+  \f
+  /* Add an element to the list of commands.  */
+  
+! struct cmd_list_element *
+  add_com (name, class, fun, doc)
+       char *name;
+       int class;
+***************
+*** 464,470 ****
+       void (*fun) ();
+       char *doc;
+  {
+!   add_cmd (name, class, fun, doc, &cmdlist);
+  }
+  
+  /* Add an alias or abbreviation command to the list of commands.  */
+--- 466,473 ----
+       void (*fun) ();
+       char *doc;
+  {
+! 
+!   return add_cmd (name, class, fun, doc, &cmdlist);
+  }
+  
+  /* Add an alias or abbreviation command to the list of commands.  */
+***************
+*** 547,552 ****
+--- 550,556 ----
+  
+    if (c && c->class == (int) class_user)
+      free_command_lines (&c->function);
++ 
+  
+    add_com (comname, class_user, cmds,
+          (c && c->class == (int) class_user)
+diff -c ../../gnu/gdb/param.h ./param.h
+*** ../../gnu/gdb/param.h      Sat Apr  4 23:15:44 1987
+--- ./param.h  Mon Apr 27 00:28:17 1987
+***************
+*** 1 ****
+--- 1,19 ----
++ /* Changed to use ifdefs so we don't have to edit it all the time.
++ David Nichols
++ 28 November 1986 */
++ 
++ #ifdef vax
+  #include "m-vax.h"
++ #endif
++ 
++ #ifdef ibm032
++ #include "m-ibm032.h"
++ #endif
++ 
++ #ifdef sun
++ #ifdef mc68020
++ #include "m-sun3.h"
++ #else
++ #include "m-sun2.h"
++ #endif
++ #endif
+diff -c ../../gnu/gdb/pinsn.c ./pinsn.c
+*** ../../gnu/gdb/pinsn.c      Sat Apr  4 23:15:58 1987
+--- ./pinsn.c  Mon Apr 27 00:28:36 1987
+***************
+*** 1 ****
+--- 1,15 ----
++ /* Changed to use ifdefs so we don't have to edit this.
++ David Nichols
++ 28 Nov 1986 */
++ 
++ #ifdef ibm032
++ #include "ibm032-pinsn.c"
++ #endif
++ 
++ #ifdef vax
+  #include "vax-pinsn.c"
++ #endif
++ 
++ #ifdef sun
++ #include "m68k-pinsn.c"
++ #endif
+diff -c ../../gnu/gdb/printcmd.c ./printcmd.c
+*** ../../gnu/gdb/printcmd.c   Sat Apr  4 23:17:03 1987
+--- ./printcmd.c       Mon Apr 27 00:30:52 1987
+***************
+*** 797,804 ****
+       CORE_ADDR frame;
+       FILE *stream;
+  {
+!   char *space = (char *) alloca (TYPE_LENGTH (SYMBOL_TYPE (var)));
+    value val = read_var_value (var, frame);
+    value_print (val, stream);
+  }
+  
+--- 797,805 ----
+       CORE_ADDR frame;
+       FILE *stream;
+  {
+!   char *space;
+    value val = read_var_value (var, frame);
++   space = (char *) alloca (TYPE_LENGTH (SYMBOL_TYPE (var)));
+    value_print (val, stream);
+  }
+  
+***************
+*** 883,888 ****
+--- 884,891 ----
+      }
+  }
+  \f
++ printcmdinitialize() {initialize();}
++ 
+  static
+  initialize ()
+  {
+diff -c ../../gnu/gdb/source.c ./source.c
+*** ../../gnu/gdb/source.c     Sat Apr  4 23:17:55 1987
+--- ./source.c Mon Apr 27 00:31:25 1987
+***************
+*** 276,282 ****
+    if (get_exec_file () != 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, s->filename);
+    end = data + st.st_size;
+    p = data;
+--- 276,283 ----
+    if (get_exec_file () != 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, s->filename);
+    end = data + st.st_size;
+    p = data;
+***************
+*** 530,535 ****
+--- 531,538 ----
+      printf ("Line number %d is out of range for \"%s\".\n",
+           sal.line, sal.symtab->filename);
+  }
++ 
++ sourceinitialize() {initialize();}
+  
+  static
+  initialize ()
+diff -c ../../gnu/gdb/stack.c ./stack.c
+*** ../../gnu/gdb/stack.c      Sun Apr  5 00:28:05 1987
+--- ./stack.c  Mon Apr 27 00:31:50 1987
+***************
+*** 511,516 ****
+--- 511,517 ----
+  
+    print_stack_frame (selected_frame, selected_frame_level, 1);
+  }
++ 
+  \f
+  static void
+  return_command (retval_exp)
+***************
+*** 538,543 ****
+--- 539,546 ----
+    frame_command ("0", 1);
+  }
+  \f
++ stackinitialize() {initialize();}
++ 
+  static
+  initialize ()
+  {
+diff -c ../../gnu/gdb/symmisc.c ./symmisc.c
+*** ../../gnu/gdb/symmisc.c    Sun Apr  5 00:33:16 1987
+--- ./symmisc.c        Mon Apr 27 00:37:46 1987
+***************
+*** 504,509 ****
+--- 504,511 ----
+    return i;
+  }
+  \f
++ symmiscinitialize() {initialize();}
++ 
+  static
+  initialize ()
+  {
+diff -c ../../gnu/gdb/symtab.c ./symtab.c
+*** ../../gnu/gdb/symtab.c     Sun Apr  5 00:35:45 1987
+--- ./symtab.c Mon Apr 27 00:38:19 1987
+***************
+*** 71,78 ****
+    strcpy (copy, name);
+    strcat (copy, ".c");
+    for (s = symtab_list; s; s = s->next)
+!     if (!strcmp (copy, s->filename))
+        return s;
+  
+    return 0;
+  }
+--- 71,79 ----
+    strcpy (copy, name);
+    strcat (copy, ".c");
+    for (s = symtab_list; s; s = s->next)
+!     if (!strcmp (copy, s->filename)) {
+        return s;
++     }
+  
+    return 0;
+  }
+***************
+*** 703,709 ****
+    register struct symbol *sym;
+    register CORE_ADDR pc;
+    register int i;
+!   char *copy;
+  
+    /* Defaults have defaults.  */
+  
+--- 704,710 ----
+    register struct symbol *sym;
+    register CORE_ADDR pc;
+    register int i;
+!   char *copy, *dotcopy;
+  
+    /* Defaults have defaults.  */
+  
+***************
+*** 818,825 ****
+--- 819,847 ----
+    /* Look up that token as a function.
+       If file specified, use that file's per-file block to start with.  */
+  
++ #ifdef ibm032
++   /* RT has stupid dots in front of function names (_.foo), and worse, has bogus _foo
++       symbol to confuse us, too.
++   */
++   if (*copy != '.') {
++       dotcopy = (char *) alloca (strlen(copy)+2);    /* one for the null and one for the dot */
++       dotcopy[0] = '.';
++       strcpy(dotcopy+1, copy);
++       sym = lookup_symbol (dotcopy, s ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 1) : 0,
++                         VAR_NAMESPACE);
++       }
++   else {
++       sym = 0;
++       dotcopy = 0;
++   }
++   if (!sym || SYMBOL_CLASS(sym) != LOC_BLOCK) {
++       sym = lookup_symbol (copy, s ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 1) : 0,
++         VAR_NAMESPACE);
++   }
++ #else
+    sym = lookup_symbol (copy, s ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 1) : 0,
+                      VAR_NAMESPACE);
++ #endif
+  
+    if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+      {
+***************
+*** 835,840 ****
+--- 857,875 ----
+    if (sym)
+      error ("%s is not a function.", copy);
+  
++ #ifdef ibm032
++   /* try the dot version first */
++   if (dotcopy) for (i = 0; i < misc_function_count; i++)
++     if (!strcmp (misc_function_vector[i].name, dotcopy))
++       {
++      value.symtab = 0;
++      value.line = 0;
++      value.pc = misc_function_vector[i].address + FUNCTION_START_OFFSET;
++      if (funfirstline)
++        SKIP_PROLOGUE (value.pc);
++      return value;
++       }
++ #endif
+    for (i = 0; i < misc_function_count; i++)
+      if (!strcmp (misc_function_vector[i].name, copy))
+        {
+***************
+*** 1027,1032 ****
+--- 1062,1069 ----
+  
+    return type;
+  }
++ 
++ symtabinitialize() {initialize();}
+  
+  static
+  initialize ()
+diff -c ../../gnu/gdb/utils.c ./utils.c
+*** ../../gnu/gdb/utils.c      Sun Apr  5 00:40:01 1987
+--- ./utils.c  Mon Apr 27 00:40:01 1987
+***************
+*** 151,156 ****
+--- 151,157 ----
+    else
+      err = "unknown error";
+  
++   /* ibm032: no core leak or other problems 'cause we alway call error -> longjmps away */
+    combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+    strcpy (combined, string);
+    strcat (combined, ": ");
+diff -c ../../gnu/gdb/valarith.c ./valarith.c
+*** ../../gnu/gdb/valarith.c   Sun Apr  5 00:40:44 1987
+--- ./valarith.c       Fri May 22 20:18:46 1987
+***************
+*** 239,245 ****
+    COERCE_ARRAY (arg1);
+  
+    len = TYPE_LENGTH (VALUE_TYPE (arg1));
+!   p = VALUE_CONTENTS (arg1);
+  
+    while (--len >= 0)
+      {
+--- 239,245 ----
+    COERCE_ARRAY (arg1);
+  
+    len = TYPE_LENGTH (VALUE_TYPE (arg1));
+!   p = (char *) VALUE_CONTENTS (arg1);
+  
+    while (--len >= 0)
+      {
+***************
+*** 281,288 ****
+          && ((len = TYPE_LENGTH (VALUE_TYPE (arg1)))
+              == TYPE_LENGTH (VALUE_TYPE (arg2))))
+      {
+!       p1 = VALUE_CONTENTS (arg1);
+!       p2 = VALUE_CONTENTS (arg2);
+        while (--len >= 0)
+       {
+         if (*p1++ != *p2++)
+--- 281,288 ----
+          && ((len = TYPE_LENGTH (VALUE_TYPE (arg1)))
+              == TYPE_LENGTH (VALUE_TYPE (arg2))))
+      {
+!       p1 = (char *) VALUE_CONTENTS (arg1);
+!       p2 = (char *) VALUE_CONTENTS (arg2);
+        while (--len >= 0)
+       {
+         if (*p1++ != *p2++)
+***************
+*** 348,353 ****
+--- 348,355 ----
+    return value_from_long (VALUE_TYPE (arg1), ~ value_as_long (arg1));
+  }
+  \f
++ valarithinitialize() {initialize();}
++ 
+  static
+  initialize ()
+  {
+diff -c ../../gnu/gdb/valops.c ./valops.c
+*** ../../gnu/gdb/valops.c     Sun Apr  5 00:41:32 1987
+--- ./valops.c Fri May 22 20:13:02 1987
+***************
+*** 174,180 ****
+    /* Return a value just like TOVAL except with the contents of FROMVAL.  */
+  
+    val = allocate_value (type);
+!   bcopy (toval, val, VALUE_CONTENTS (val) - (char *) val);
+    bcopy (VALUE_CONTENTS (fromval), VALUE_CONTENTS (val), TYPE_LENGTH (type));
+  
+    return val;
+--- 174,180 ----
+    /* Return a value just like TOVAL except with the contents of FROMVAL.  */
+  
+    val = allocate_value (type);
+!   bcopy (toval, val, (char *) VALUE_CONTENTS (val) - (char *) val);
+    bcopy (VALUE_CONTENTS (fromval), VALUE_CONTENTS (val), TYPE_LENGTH (type));
+  
+    return val;
+***************
+*** 413,419 ****
+--- 413,427 ----
+        }
+      else if (code == TYPE_CODE_PTR)
+        {
++ #ifdef ibm032
++      /* apparently '_a' pseudoprocedure has lval_memory as its lval type */
++      if (VALUE_LVAL(function) == lval_memory) 
++        funaddr = VALUE_ADDRESS(function);
++      else
++           funaddr = value_as_long (function);
++ #else
+       funaddr = value_as_long (function);
++ #endif
+       if (TYPE_CODE (TYPE_TARGET_TYPE (ftype))
+           == TYPE_CODE_FUNC)
+         value_type = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (ftype));
+***************
+*** 429,439 ****
+       else
+         /* Handle integer used as address of a function.  */
+         funaddr = value_as_long (function);
+- 
+       value_type = builtin_type_int;
+        }
+!     else
+        error ("Invalid data type for function to be called.");
+  
+      /* Create a call sequence customized for this function
+         and the number of arguments for it.  */
+--- 437,447 ----
+       else
+         /* Handle integer used as address of a function.  */
+         funaddr = value_as_long (function);
+       value_type = builtin_type_int;
+        }
+!     else {
+        error ("Invalid data type for function to be called.");
++     }
+  
+      /* Create a call sequence customized for this function
+         and the number of arguments for it.  */
+***************
+*** 590,595 ****
+--- 598,605 ----
+    return value_field (arg1, i);
+  }
+  \f
++ valopsinitialize() {initialize();}
++ 
+  static
+  initialize ()
+  { }
+diff -c ../../gnu/gdb/valprint.c ./valprint.c
+*** ../../gnu/gdb/valprint.c   Sun Apr  5 00:42:28 1987
+--- ./valprint.c       Mon Apr 27 00:40:56 1987
+***************
+*** 529,534 ****
+--- 529,536 ----
+    print_max = atoi (arg);
+  }
+  
++ valprintinitialize() {initialize();}
++ 
+  static
+  initialize ()
+  {
+diff -c ../../gnu/gdb/value.h ./value.h
+*** ../../gnu/gdb/value.h      Sun Apr  5 00:43:44 1987
+--- ./value.h  Fri May 22 20:03:32 1987
+***************
+*** 37,43 ****
+      short repeated;
+      short repetitions;
+      short regno;
+!     char contents[1];
+    };
+  
+  typedef struct value *value;
+--- 37,43 ----
+      short repeated;
+      short repetitions;
+      short regno;
+!     long contents[1]; /* Forces alignment... */
+    };
+  
+  typedef struct value *value;
+diff -c ../../gnu/gdb/values.c ./values.c
+*** ../../gnu/gdb/values.c     Sun Apr  5 00:45:14 1987
+--- ./values.c Fri May 22 20:12:40 1987
+***************
+*** 338,344 ****
+       int offset, bitpos, bitsize;
+       value newval;
+  {
+!   register char *addr = VALUE_CONTENTS (var->value) + offset;
+    if (bitsize)
+      modify_field (addr, value_as_long (newval),
+                 bitpos, bitsize);
+--- 338,344 ----
+       int offset, bitpos, bitsize;
+       value newval;
+  {
+!   register char *addr = (char *) VALUE_CONTENTS (var->value) + offset;
+    if (bitsize)
+      modify_field (addr, value_as_long (newval),
+                 bitpos, bitsize);
+***************
+*** 733,738 ****
+--- 733,740 ----
+    write_register (1, retbuf[1]);
+  }
+  \f
++ valuesinitialize() {initialize();}
++ 
+  static
+  initialize ()
+  {
+
diff --git a/gdb/=rt-extra b/gdb/=rt-extra
new file mode 100644 (file)
index 0000000..827e1a1
--- /dev/null
@@ -0,0 +1,84 @@
+BABYL OPTIONS:
+Version: 5
+Labels:
+Note:   This is the header of an rmail file.
+Note:   If you are seeing it in rmail,
+Note:    it means the file has no messages in it.
+\1f\f
+1,,
+Received: by PREP.AI.MIT.EDU; Mon, 25 May 87 04:03:20 EDT
+Message-Id: <8705250803.AA14993@prep.ai.mit.edu>
+Received: by po2.andrew.cmu.edu (5.54/3.15) id <AA00199> for rms@prep.ai.mit.edu; Mon, 25 May 87 04:02:41 EDT
+Received: via switchmail; Mon, 25 May 87 04:02:29 edt
+Received: FROM z.itc.cmu.edu VIA qmail
+          ID </cmu/common/mailqs/q004/QF.z.itc.cmu.edu.20b7fa53.6bb39>;
+          Mon, 25 May 87 04:01:27 edt
+Received: FROM z.itc.cmu.edu VIA qmail
+          ID </cmu/itc/zs01/.Outgoing/QF.z.itc.cmu.edu.20b7fa49.a49502>;
+          Mon, 25 May 87 04:01:15 edt
+From: zs01#@andrew.cmu.edu (Zalman Stern)
+Date: Mon, 25 May 87 04:01:13 edt
+To: rms@prep.ai.mit.edu
+Subject: Small diff to yesterdays gdb diffs.
+
+*** EOOH ***
+From: zs01#@andrew.cmu.edu (Zalman Stern)
+Date: Mon, 25 May 87 04:01:13 edt
+To: rms@prep.ai.mit.edu
+Subject: Small diff to yesterdays gdb diffs.
+
+Richard,
+
+Here is another minor diff to the diassembler to get certain conditional
+branches instructions correct...
+
+Also, I noticed that gcc.tar.Z is out of date with respect to gcc.tar .
+When I go to get these files, should I go ahead and replace the compressed
+version with a newer one or should I leave it alone? Likewise, should I try and
+make a split version on prep?
+
+-Z-
+
+*** ibm032-pinsn.c.old Mon May 25 03:31:04 1987
+--- ibm032-pinsn.c     Mon May 25 03:47:12 1987
+***************
+*** 101,112 ****
+      }
+    }
+    else { /* Conditional branches are hacked. */
+!     switch (type & 0x0f) {
+  
+        int displacement;
+  
+        case ibm032_JI:
+!         fprintf(stream, ibm032_opcodes[opcodeIndex].mnemonic, mapCondition(type & ibm032_negative, buffer[0] & LOW4));
+        putc('\t', stream);
+        print_address((buffer[1] << 1) + memaddr, stream);
+        return 2;
+--- 101,112 ----
+      }
+    }
+    else { /* Conditional branches are hacked. */
+!     switch (type & LOW4) {
+  
+        int displacement;
+  
+        case ibm032_JI:
+!         fprintf(stream, ibm032_opcodes[opcodeIndex].mnemonic, mapCondition(type & ibm032_negative, (buffer[0] & LOW3) + 8));
+        putc('\t', stream);
+        print_address((buffer[1] << 1) + memaddr, stream);
+        return 2;
+*** ibm032-opcode.h.old        Mon May 25 03:33:19 1987
+--- ibm032-opcode.h    Mon May 25 03:33:24 1987
+***************
+*** 11,16 ****
+--- 11,17 ----
+  
+  /* Various useful bit masks. */
+  #define ibm032_typeMask              0x0f /* Mask to get actual type info out of instruction type. */
++ #define LOW3                 0x07
+  #define LOW4                 0x0f
+  #define HIGH4                        0xf0
+  #define LOW16                        0x0000ffff
+
+\1f
\ No newline at end of file
diff --git a/gdb/=xgdb.msg b/gdb/=xgdb.msg
new file mode 100644 (file)
index 0000000..ac32300
--- /dev/null
@@ -0,0 +1,997 @@
+From beatty@unh.cs.cmu.edu Sat Jul  4 12:04:01 1987
+Received: by PREP.AI.MIT.EDU; Sat, 4 Jul 87 12:03:37 EDT
+Message-Id: <8707041603.AA08600@prep.ai.mit.edu>
+To: phr@prep.ai.mit.edu (Paul Rubin)
+Date: Sat, 4 Jul 87 12:03:01 EDT
+From: Derek Beatty <beatty@unh.cs.cmu.edu>
+Subject: Re: gdb and X (msg 1 of 3)
+Status: R
+
+This is part 1 of 3 parts.  It consists of the cursor I used, and a message
+I sent to Zalman Stern at Andrew regarding what I did, and why.  The
+code and context diffs will follow in other messages.
+
+#define gdb_width 16
+#define gdb_height 16
+#define gdb_x_hot 7
+#define gdb_y_hot 0
+static short gdb_bits[] = {
+   0x0000, 0x0140, 0x0220, 0x0220,
+   0x23e2, 0x13e4, 0x09c8, 0x0ff8,
+   0x0220, 0x3ffe, 0x0630, 0x03e0,
+   0x0220, 0x1ffc, 0x2632, 0x01c0};
+
+#define gdb_mask_width 16
+#define gdb_mask_height 16
+#define gdb_mask_x_hot 7
+#define gdb_mask_y_hot 0
+static short gdb_mask_bits[] = {
+   0x0360, 0x07f0, 0x07f0, 0x77f7,
+   0x7fff, 0x7fff, 0x1ffc, 0x1ffc,
+   0x7fff, 0x7fff, 0x7fff, 0x0ff8,
+   0x3ffe, 0x7fff, 0x7fff, 0x7fff};
+
+> 
+> The X support I added is minimal; it was inspired by Suntools' dbxtool,
+> together with the availability of the V10 implementation of the X V11
+> toolkit specification.  Design was guided by simplicity and the facilities
+> of the toolkit.  The debugger window provides a view into the code 
+> corresponding to the current stack frame, and several buttons for the
+> breakpoint, print, step, next, continue, finish, up, and down commands.
+> The standard gdb command interface remains available in the tty window from
+> which gdb was started.  The breakpoint and print buttons make use of the
+> current selection, so you can do simple things like click at text in the
+> source window, then click the "Go 'til" button to continue until that
+> point.  
+> 
+> Such an interface is simple to program ( ~ 20 hours, about 700 lines), 
+> but it has some drawbacks.  First, I didn't take the time to understand
+> the longjmp's in gdb, and I'm not exactly happy with the idea of them
+> jumping out of my callback procedures that were invoked by toolkit routines. 
+> There's one core dump bug (it shows up when gdb can't find a source
+> file) that I haven't tracked down, and it may be related to this.  Second,
+> selection in the text window is not particularly graceful: double-clicking
+> highlights one word of text, as the toolkit defines a word.  It would
+> be much more graceful were double-clicking to highlight a C identifier. 
+> Finally, and most seriously, most buttons operate by building textual
+> command lines and passing them to gdb's execute_command function.  This
+> means that all selected expressions are evaluated and printed in the
+> lexical scope corresponding to the current stack frame, although the
+> selected text may be in a different lexical scope.  This serious bug would
+> require work to fix.
+> 
+> I wrote the X support out of frustration at not having dbxtool available
+> when I work on a vax.  The hope of portability to V11 via the toolkit
+> also helped motivate me to write V10 code at this late date.  Finally,
+> I'd never written any nontrivial code that ran on a windowing system
+> (although that turns out still to be the case). Were I to make a more
+> serious effort at this project, I would probably add a general "define-button"
+> command akin to gdb's "define" command.
+> 
+> Look in /usr/beatty/gnu/gdb on vlsi.cs.cmu.edu.  All files I have modified
+> are marked, and also have associated backups (.B extensions). Bennet
+> Yee has a copy of the toolkit library; see /usr/bsy/Xtlib on f.gp.cs.cmu.edu.
+> 
+>  -- Derek
+> 
+
+ -- Derek Beatty
+
+From beatty@unh.cs.cmu.edu Sat Jul  4 12:12:47 1987
+Received: by PREP.AI.MIT.EDU; Sat, 4 Jul 87 12:09:20 EDT
+Message-Id: <8707041609.AA08643@prep.ai.mit.edu>
+To: phr@PREP.AI.MIT.EDU (Paul Rubin)
+Date: Sat, 4 Jul 87 12:07:25 EDT
+From: Derek Beatty <beatty@unh.cs.cmu.edu>
+Subject: Re: gdb and X (msg 2 of 3)
+In-Reply-To: Message from "Paul Rubin" of Jul 4, 87 at 1:22 am
+Status: R
+
+The following is "tool.c".  I hereby grant permission to do anything you
+like with it.
+
+ -- Derek Beatty
+
+[nosave]
+/* 
+ * gdb tool for X V10R4 (using V11-compatible toolkit).
+ * Derek Beatty 30 June 87.
+ */
+#include <X/Xlib.h>
+#include <X/Xt/Xtlib.h>
+#include <stdio.h>
+
+#include "defs.h"
+#include "symtab.h"
+
+#include "gdb.cursor"
+#include "gdb_mask.cursor"
+
+
+
+/* forward refs */
+
+static Window createFileText();
+/* 
+ * Windows manipulated by this package.
+ */
+
+static Window 
+  icon,
+  frame, 
+  srcLabelStrip,
+  srcText,
+  ctlPanel,
+  execLabelStrip;
+
+static Cursor curse;
+
+/*
+ * Source text display.
+ */
+
+static struct symtab *displayedSymtab= 0;
+
+extern struct symtab *current_source_symtab;
+extern int current_source_line;
+
+toolDisplaySource()
+{
+  char *fullName;
+  static Arg labelArgs[1];
+  int linenumbers_changed= 0;
+  static int newWidget= 1;
+
+  struct symtab_and_line get_selected_frame_sal();
+  struct symtab_and_line sal;
+
+  /* we could be called before we are initialized */
+  if (!frame) return;
+  
+  sal= get_selected_frame_sal();
+
+  /* strictly this is wrong, but better than a blank display */
+  if (sal.symtab==NULL) {
+    sal.symtab= current_source_symtab;
+    /* current_source_line may be off by a small number like 4 */
+    sal.line= current_source_line;
+  }
+
+  /*
+   * Switch to a new file if necessary.
+   */
+
+  if (sal.symtab)
+    linenumbers_changed= get_filename_and_charpos(sal.symtab, 
+                                               sal.line,
+                                               &fullName);
+  if (!fullName) sal.symtab= NULL;
+  /* if the display may be wrong, destroy it */
+  if (linenumbers_changed || displayedSymtab != sal.symtab) {
+    XtVPanedWindowDeletePane( srcText);
+    XtSendDestroyNotify( srcText);
+    XDestroyWindow( srcText);
+    srcText= 0;
+  }
+  /* if there's no display, create one */
+  if (!srcText) {
+    newWidget= 1;
+    /* if there's no valid display, create a dummy display */
+    if (!sal.symtab ) {
+      displayedSymtab= NULL;
+      srcText= createFileText(frame, "/dev/null");
+      XtVPanedWindowAddPane(frame, srcText, 1, 20, 1000, 1);
+      /* create /dev/null text widget */
+      XtSetArg(labelArgs[0], XtNlabel, "No source displayed.");
+      XtLabelSetValues(srcLabelStrip, labelArgs, XtNumber(labelArgs));
+     } else {
+      displayedSymtab= sal.symtab;
+      srcText= createFileText(frame, fullName);
+      XtVPanedWindowAddPane(frame, srcText, 1, 20, 1000, 1);
+      XtSetArg(labelArgs[0], XtNlabel, fullName);
+      XtLabelSetValues(srcLabelStrip, labelArgs, XtNumber(labelArgs));
+      /* free filename (maybe: check gdb code!) */
+    }
+  }
+
+  /*
+   * Update display and cursor positions as necessary.
+   * Cursor should be placed on line sal.line.
+   */
+
+  {
+    static int prevTop= 0, highWaterMark= 0;
+    int currentTop;
+    Arg textArgs[1];
+
+    /* get positions of start of display, and caret */
+    XtSetArg(textArgs[0], XtNdisplayPosition, NULL);
+    XtTextGetValues(srcText, textArgs, XtNumber(textArgs));
+    currentTop= cvtCharToLine(displayedSymtab,
+                             (int) textArgs[0].value);
+    
+    highWaterMark += currentTop - prevTop;
+
+    if (    sal.line < currentTop
+        || sal.line > highWaterMark
+         || newWidget) {
+    
+      /* warp the display */
+
+      newWidget= 0;
+
+       /* yes, these magic numbers are ugly, but I don't know how
+        * to get the height of a text widget in a V11-portable way
+        */
+      currentTop= (sal.line > 15) ? sal.line - 15 : 0;
+      highWaterMark= currentTop + 35;
+      
+      XtSetArg(textArgs[0], XtNdisplayPosition,
+              cvtLineToChar(displayedSymtab, currentTop));
+      XtTextSetValues(srcText, textArgs, XtNumber(textArgs));
+    }
+    XtSetArg(textArgs[0], XtNinsertPosition, 
+            cvtLineToChar(displayedSymtab, sal.line));
+    XtTextSetValues(srcText, textArgs, XtNumber(textArgs));
+
+    prevTop=  currentTop;
+  }
+}
+
+/* return the character position of a line */
+int
+cvtLineToChar( s, line)
+  struct symtab *s;
+  int line;
+{
+  if (!s) return 0;
+  if (!s->line_charpos) return 0;
+  if (line < 0) line= 0;
+  if (line > s->nlines) line= s->nlines;
+  return *(s->line_charpos + line-1);
+}
+
+/* return the line position of a character */
+int
+cvtCharToLine( s, chr)
+    register struct symtab *s;
+    register int chr;
+{
+    register int lineNumber= 0;
+    register int *lnp;
+    
+    if (!s) return 0;
+    lnp= s->line_charpos;
+    /* files are usually short, so sequential search is Ok */
+    while ( lineNumber < s->nlines  && *lnp <= chr) {
+       lineNumber++;
+       lnp++;
+    }
+    if (lineNumber >= s->nlines)
+       lineNumber= s->nlines;
+    return lineNumber;
+}
+
+/* 
+ * title bar at bottom
+ */
+
+static char *execFileName;
+
+toolSetExecFile(s)
+  char *s;
+{
+  execFileName= s;
+  if (execLabelStrip) {
+    static Arg labelArgs[1];
+
+    XtSetArg(labelArgs[0], XtNlabel, execFileName);
+    XtLabelSetValues(execLabelStrip, labelArgs, XtNumber(labelArgs));
+  }
+}
+
+/*
+ * Command line into which command are placed for execution.
+ * There's some ugly interaction between this and readline in main.c.
+ */
+extern char *line;
+extern int linesize;
+
+/*
+ * Do any necessary prompting, etc.
+ */
+static char *gdbPrompt;
+
+static void
+printPrompt()
+{
+  if (gdbPrompt) {
+    printf("%s", gdbPrompt);
+    fflush(stdout);
+  }
+}
+
+/*
+ * Callback procedures for control panel.
+ */
+
+/* used by "print" and "print*" buttons */
+static void printButnProc_1( starflag)
+  int starflag;
+{
+  int selnLen;
+  char *seln;
+
+  char *cmd= starflag ? "print * " : "print ";
+  register int cmdlen= strlen(cmd);
+  
+  seln= XFetchBytes(&selnLen);
+  if (selnLen) {
+    if (selnLen+cmdlen >= linesize-1) {
+     linesize= (selnLen+cmdlen > linesize*2-1) ? selnLen+cmdlen+1 : linesize*2;
+     line= (char *) xrealloc(line, linesize);
+    }
+    strcpy(line, cmd);
+    strncpy(line+cmdlen, seln, selnLen);
+    *(line+cmdlen+selnLen)= '\0';
+    execute_command(line, 0);
+    free(seln);
+  }
+  printPrompt();
+}
+
+static void printButnProc() 
+{
+  printButnProc_1( 0);
+}
+
+static void printStarButnProc() 
+{
+  printButnProc_1( 1);
+}
+
+static void nextButnProc()
+{
+  strcpy(line, "next");
+  execute_command(line, 0);
+  toolDisplaySource();
+  printPrompt();
+}
+
+static void stepButnProc()
+{
+  strcpy(line, "step");
+  execute_command(line, 0);
+  toolDisplaySource();
+  printPrompt();
+}
+
+static void contButnProc()
+{
+  strcpy(line, "cont");
+  execute_command(line, 0);
+  toolDisplaySource();
+  printPrompt();
+}
+
+static void finButnProc()
+{
+  strcpy(line, "finish");
+  execute_command(line, 0);
+  toolDisplaySource();
+  printPrompt();
+}
+
+/* used by "stop at" and "go till" buttons */
+static void stopAtButnProc_1( gotillFlag)
+  int gotillFlag;
+{
+  XtTextPosition start, finish;
+  static int lineNumber; 
+  
+  XtTextGetSelectionPos(srcText, &start, &finish);
+  if (!displayedSymtab)
+    printf("No source file displayed.\n");
+  else {
+    break_command_for_tool( displayedSymtab, 
+                           cvtCharToLine(displayedSymtab, start),
+                           gotillFlag);
+    if (gotillFlag) {
+      strcpy(line, "cont");
+      execute_command(line, 0);
+      toolDisplaySource();
+    }
+  }
+  printPrompt();
+}
+
+static void stopAtButnProc()
+{
+  stopAtButnProc_1( 0);
+}
+
+static void untilButnProc()
+{
+  stopAtButnProc_1( 1);
+}
+
+/* decide if a character is trash */
+static int
+garbage(c)
+  char c;
+{
+  if ('a' <= c && c <= 'z') return 0;
+  if ('A' <= c && c <= 'Z') return 0;
+  if ('0' <= c && c <= '9') return 0;
+  if (c == '_') return 0;
+  return 1;
+}
+
+static void stopInButnProc()
+{
+  static int selnLen;
+  static char *seln;
+  char *sp, *selnp;
+
+  seln= XFetchBytes(&selnLen);
+  if (selnLen) {
+    if (selnLen+6 >= linesize-1) {
+      linesize= (selnLen+6 > linesize*2-1) ? selnLen+7 : linesize*2;
+      line= (char *) xrealloc(line, linesize);
+    }
+    strcpy(line, "break ");
+    /* copy selection but not garbage */
+    selnp= seln;
+    sp= line+strlen(line);
+    while (garbage(*selnp) && selnLen) selnp++, selnLen--;
+    while (!garbage(*selnp) && selnLen) {
+      *sp++= *selnp++;
+      selnLen--;
+    }
+    *sp= '\0';
+    execute_command(line, 0);
+    free(seln);
+  }
+  printPrompt();
+}
+
+static void deIconifyButnProc()
+{
+  XUnmapWindow(icon);
+  XMapWindow(frame);
+}
+
+static void iconifyButnProc()
+{
+  static Arg iconArgs[1];
+  XtSetArg(iconArgs[0], XtNlabel, gdbPrompt);
+  XtCommandSetValues(icon, iconArgs, XtNumber(iconArgs));
+  XUnmapWindow(frame);
+  XMapWindow(icon);
+}
+
+static void upButnProc()
+{
+  strcpy(line, "up");
+  execute_command(line, 0);
+  toolDisplaySource();
+  printPrompt();
+}
+
+static void downButnProc()
+{
+  strcpy(line, "down");
+  execute_command(line, 0);
+  toolDisplaySource();
+  printPrompt();
+}
+
+#define addbutton(w) XtSetArg(buttons[buttoncount], XtNwindow, w); \
+                    buttoncount++;
+static Arg buttons[20];
+static int buttoncount= 0;
+
+/*
+ * Create control panel buttons.
+ */
+static createButtons(parent)
+  Window parent;
+{
+  static Window button;
+  static Arg commandArgs[2];
+
+#define crButn(label,fn)       \
+       XtSetArg(commandArgs[0], XtNlabel, label);\
+       XtSetArg(commandArgs[1], XtNfunction, fn);\
+       button= XtCommandCreate(parent, commandArgs, XtNumber(commandArgs));\
+       addbutton(button);
+
+  crButn("Brk At", stopAtButnProc);
+  crButn("Brk In", stopInButnProc);
+  crButn("Go 'til", untilButnProc);
+
+  crButn("Print", printButnProc);
+  crButn("Print*", printStarButnProc);
+
+  crButn("Next", nextButnProc);
+  crButn("Step", stepButnProc);
+  crButn("Cont", contButnProc);
+  crButn("Finish", finButnProc);
+  
+  crButn("Up", upButnProc);
+  crButn("Down", downButnProc);
+
+  crButn("Iconify", iconifyButnProc);
+#undef crButn
+}
+
+static Window createLabel(parent, name, label)
+  Window parent;
+  char *name, *label;
+{
+  static Arg labelArgs[2];
+  
+  XtSetArg(labelArgs[0], XtNname, name);
+  XtSetArg(labelArgs[1], XtNlabel, label);
+  return XtLabelCreate(frame, labelArgs, XtNumber(labelArgs));
+}
+
+static Window createFileText( parent, filename)
+  Window parent;
+  char *filename;
+{
+  static Arg fileArgs[2];
+  
+  XtSetArg(fileArgs[0], XtNfile, filename);
+  XtSetArg(fileArgs[1], XtNtextOptions, scrollVertical);
+  return XtTextDiskCreate(parent, fileArgs, XtNumber(fileArgs));
+}
+
+/***************** Externally referenced routine **************/
+int createTool()
+{
+  static Arg frameArgs[]= {
+      {XtNwidth, (XtArgVal) 600},
+      {XtNheight, (XtArgVal) 700},
+  };
+  
+  ResourceDataBase db;
+  FILE *rdbFile;
+  
+  /*
+   * init and database stuff... this is wrong but what the heck
+   */
+  if (XOpenDisplay("") == NULL)
+    return 0;
+  printf("Initializing tool..."); fflush(stdout);
+  XtInitialize();
+  /* should be checking .Xdefaults in $HOME */
+  if ((rdbFile= fopen(".Xresources", "r")) != NULL) {
+    XtGetDataBase(rdbFile, &db);
+    XtSetCurrentDataBase(db);
+    fclose(rdbFile);
+  }
+  
+  /*
+   * create the frame
+   */
+  frame= XtVPanedWindowCreate(RootWindow, frameArgs, XtNumber(frameArgs));
+  
+  /* create source label strip and add to frame */
+  srcLabelStrip= createLabel(frame, "Source File", "No source file yet.");
+  XtVPanedWindowAddPane(frame, srcLabelStrip, 0, 15, 15, 0);
+
+  /* create text widget and add to frame */
+  srcText= createFileText(frame, "/dev/null");
+  XtVPanedWindowAddPane(frame, srcText, 1, 20, 1000, 1);
+
+  /* create button box */
+  ctlPanel= XtButtonBoxCreate(frame, NULL, 0);
+  createButtons( ctlPanel);
+  XtButtonBoxAddButton(ctlPanel, buttons, buttoncount);
+  XtVPanedWindowAddPane(frame, ctlPanel, 2, 30, 30, 0);
+
+  /* create exec label strip and add */
+  execLabelStrip= createLabel(frame, "Executable", 
+     execFileName ? execFileName : "No executable specified.");
+  XtVPanedWindowAddPane(frame, execLabelStrip, 3, 15, 15, 0);
+  
+  
+  /* create icon */
+  {
+    static Arg iconArgs[2];
+    XtSetArg(iconArgs[0], XtNlabel, "(gdb)");
+    XtSetArg(iconArgs[1], XtNfunction, deIconifyButnProc);
+    icon= XtCommandCreate(RootWindow, iconArgs, XtNumber(iconArgs));
+    XMoveWindow(icon, 100, 100);       /* HACK */
+    XSetIconWindow(frame, icon);
+  }
+  
+  /* throw it onto the display */
+  curse= XCreateCursor(gdb_width, gdb_height, gdb_bits, gdb_mask_bits,
+               gdb_x_hot, gdb_y_hot,
+               BlackPixel, WhitePixel, GXcopy);
+  XDefineCursor(frame, curse);
+  XDefineCursor(icon, curse);
+  XMapWindow(frame);
+  XMapSubwindows(frame);
+  XFlush();
+  printf("done\n");
+  return 1;
+}
+
+/**************** Externally referenced routine. ***********/
+/* toolDispatcher -- dispatch events until data is available on fp */
+toolDispatcher(fp, prompt)
+  FILE *fp;
+  char *prompt;
+{
+  int inMask= 1 << fileno(fp);
+  int xMask= 1 << dpyno();
+  int rfds= 0;
+  int nfds;
+  XEvent ev;
+  int pend;
+  
+  gdbPrompt= prompt;
+  
+  while (! (rfds & inMask)) {
+    pend= XPending();
+    if (!pend) {
+      rfds= inMask | xMask;
+      /* this isn't right for 4.3 but it works 'cuz of 4.2 compatibility */
+      nfds= select( 32, &rfds, 0, 0, (struct timeval *) 0);
+    }
+    if (pend || rfds & xMask) {
+      XNextEvent(&ev);
+      XtDispatchEvent(&ev);
+    }
+  }
+}  
+
+From beatty@unh.cs.cmu.edu Sat Jul  4 12:17:44 1987
+Received: by PREP.AI.MIT.EDU; Sat, 4 Jul 87 12:15:18 EDT
+Message-Id: <8707041615.AA08691@prep.ai.mit.edu>
+To: phr@PREP.AI.MIT.EDU (Paul Rubin)
+Date: Sat, 4 Jul 87 12:14:08 EDT
+From: Derek Beatty <beatty@unh.cs.cmu.edu>
+Subject: Re: gdb and X (msg 3 of 3)
+In-Reply-To: Message from "Paul Rubin" of Jul 4, 87 at 1:22 am
+Status: R
+
+Context diffs follow.  The original files are from GDB 2.1 (emacs distribution
+18.40).
+
+ -- Derek Beatty
+[nosave]
+*** /usr/misc/.gdb/src/core.c  Fri Mar 27 12:20:14 1987
+--- core.c     Sat Jul  4 11:12:16 1987
+***************
+*** 1,3
+  /* Work with core dump and executable files, for GDB.
+     Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+  
+
+--- 1,5 -----
++ /* modified by Beatty 1 Jul 87 for gdb tool. */
++ 
+  /* Work with core dump and executable files, for GDB.
+     Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+  
+***************
+*** 257,262
+      }
+    else if (from_tty)
+      printf ("No exec file now.\n");
+  }
+  \f
+  /* If we have both a core file and an exec file,
+
+--- 259,267 -----
+      }
+    else if (from_tty)
+      printf ("No exec file now.\n");
++ #ifdef TOOL
++     toolSetExecFile( filename ? filename : "No executable specified.\n");
++ #endif /* def TOOL */
+  }
+  \f
+  /* If we have both a core file and an exec file,
+*** /usr/misc/.gdb/src/breakpoint.c    Fri Mar 27 12:20:11 1987
+--- breakpoint.c       Wed Jul  1 11:27:31 1987
+***************
+*** 1,3
+  /* Everything about breakpoints, for GDB.
+     Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+  
+
+--- 1,5 -----
++ /* modified by Beatty 1 Jul 87 for gdbtool */
++ 
+  /* Everything about breakpoints, for GDB.
+     Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+  
+***************
+*** 513,518
+       break;
+        }
+  }
+  \f
+  /* Set a breakpoint according to ARG (function, linenum or *address)
+     and make it temporary if TEMPFLAG is nonzero.  */
+
+--- 515,571 -----
+       break;
+        }
+  }
++ 
++ #ifdef TOOL
++ /* set a breakpoint from a symtab and line */
++ void break_command_for_tool( s, line, tempflag)
++   struct symtab *s;
++   int line;
++   int tempflag;
++ {
++   register struct breakpoint *b;
++   struct symtab_and_line sal;
++   
++   sal.symtab= s;
++   sal.line= line;
++   sal.pc= find_line_pc( sal.symtab, sal.line);
++   if (sal.pc==0) {
++     error("No line %d in file \"%s\".\n", sal.line, sal.symtab->filename);
++   } else {
++     b= set_raw_breakpoint( sal);
++     b->number= ++breakpoint_count;
++     b->cond= 0;
++     if (tempflag)
++       b->enable= temporary;
++ 
++   printf ("Breakpoint %d at 0x%x", b->number, b->address);
++   if (b->symtab)
++     printf (": file %s, line %d.", b->symtab->filename, b->line_number);
++   printf ("\n");
++ 
++     {
++       int others = 0;
++       ALL_BREAKPOINTS (b)
++      if (b->address == sal.pc && b->number != breakpoint_count)
++        others++;
++       if (others > 0)
++      {
++        printf ("Note: breakpoint%s ", (others > 1) ? "s" : "");
++        ALL_BREAKPOINTS (b)
++          if (b->address == sal.pc && b->number != breakpoint_count)
++            {
++              others--;
++              printf ("%d%s%s ",
++                      b->number,
++                      (b->enable == disabled) ? " (disabled)" : "",
++                      (others > 1) ? "," : ((others == 1) ? " and" : ""));
++            }
++        printf (" also set at pc 0x%x\n", sal.pc);
++      }
++     }
++   }
++ }
++ #endif /* def TOOL */
+  \f
+  /* Set a breakpoint according to ARG (function, linenum or *address)
+     and make it temporary if TEMPFLAG is nonzero.  */
+*** /usr/misc/.gdb/src/main.c  Fri Mar 27 12:20:45 1987
+--- main.c     Sat Jul  4 11:13:32 1987
+***************
+*** 1,3
+  /* Top level for GDB, the GNU debugger.
+     Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+  
+
+--- 1,5 -----
++ /* modified by Beatty 30 june 87 for gdb tool */
++ 
+  /* Top level for GDB, the GNU debugger.
+     Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+  
+***************
+*** 42,47
+  
+  FILE *instream;
+  
+  void free_command_lines ();
+  char *read_line ();
+  static void initialize_main ();
+
+--- 44,54 -----
+  
+  FILE *instream;
+  
++ #ifdef TOOL
++ /* flag indicating whether we are running in a window system */
++ int isaTool= 0;
++ #endif /* def TOOL */
++ 
+  void free_command_lines ();
+  char *read_line ();
+  static void initialize_main ();
+***************
+*** 214,219
+  
+    while (1)
+      {
+        if (!setjmp (to_top_level))
+       command_loop ();
+        clearerr (stdin);              /* Don't get hung if C-d is typed.  */
+
+--- 221,232 -----
+  
+    while (1)
+      {
++ 
++ #ifdef TOOL
++       if (!isaTool)
++         isaTool= createTool();
++ #endif /* def TOOL */
++ 
+        if (!setjmp (to_top_level))
+       command_loop ();
+        clearerr (stdin);              /* Don't get hung if C-d is typed.  */
+***************
+*** 270,275
+       printf ("%s", prompt);
+        fflush (stdout);
+  
+        quit_flag = 0;
+        execute_command (read_line (instream == stdin), instream == stdin);
+        /* Do any commands attached to breakpoint we stopped at.  */
+
+--- 283,294 -----
+       printf ("%s", prompt);
+        fflush (stdout);
+  
++ #ifdef TOOL
++       toolDisplaySource();
++       if (isaTool) toolDispatcher(instream, 
++                                        instream==stdin ? prompt : NULL);
++ #endif /* def TOOL */
++ 
+        quit_flag = 0;
+        execute_command (read_line (instream == stdin), instream == stdin);
+        /* Do any commands attached to breakpoint we stopped at.  */
+***************
+*** 320,325
+  
+    while (1)
+      {
+        c = fgetc (instream);
+        if (c == -1 || c == '\n')
+       break;
+
+--- 339,345 -----
+  
+    while (1)
+      {
++ 
+        c = fgetc (instream);
+        if (c == -1 || c == '\n')
+       break;
+***************
+*** 765,770
+  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
+
+--- 785,793 -----
+  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);
++ #ifdef TOOL
++   printf( "(CMU X support is available in this version.)\n");
++ #endif
+  }
+  
+  static void
+*** /usr/misc/.gdb/src/source.c        Fri Mar 27 12:20:50 1987
+--- source.c   Wed Jul  1 17:56:58 1987
+***************
+*** 1,3
+  /* List lines of source files for GDB, the GNU debugger.
+     Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+  
+
+--- 1,5 -----
++ /* modified 1 July 87 by Beatty for gdbtool */
++ 
+  /* List lines of source files for GDB, the GNU debugger.
+     Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+  
+***************
+*** 295,300
+    s->nlines = nlines;
+    s->line_charpos = (int *) xrealloc (line_charpos, nlines * sizeof (int));
+  }
+  \f
+  /* Print source lines from the file of symtab S,
+     starting with line number LINE and stopping before line number STOPLINE.  */
+
+--- 297,328 -----
+    s->nlines = nlines;
+    s->line_charpos = (int *) xrealloc (line_charpos, nlines * sizeof (int));
+  }
++ 
++ #ifdef TOOL
++ /* Get full pathname and line number positions for a symtab 
++  *   return nonzero if line numbers may have changed
++  *   set full pathname to NULL if no file 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, fullname);
++   if (desc < 0) {
++     *fullname= NULL;
++     return 0;
++   }  
++   if (s->line_charpos==0) linenums_changed= 1;
++   if (linenums_changed) find_source_lines(s, desc);
++   close(desc);
++   return linenums_changed;
++ }
++ #endif /* def TOOL */
++ 
+  \f
+  /* Print source lines from the file of symtab S,
+     starting with line number LINE and stopping before line number STOPLINE.  */
+*** /usr/misc/.gdb/src/stack.c Fri Mar 27 12:20:51 1987
+--- stack.c    Wed Jul  1 17:27:34 1987
+***************
+*** 1,3
+  /* Print and select stack frames for GDB, the GNU debugger.
+     Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+  
+
+--- 1,5 -----
++ /* modified by Beatty 1 Jul 87 for gdbtool */
++ 
+  /* Print and select stack frames for GDB, the GNU debugger.
+     Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+  
+***************
+*** 42,47
+  static void select_calling_frame ();
+  
+  void print_frame_info ();
+  \f
+  /* 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).
+
+--- 44,62 -----
+  static void select_calling_frame ();
+  
+  void print_frame_info ();
++ 
++ #ifdef TOOL
++ /* get symtab and line of selected frame, for tool display */
++ struct symtab_and_line
++ get_selected_frame_sal()
++ {
++   struct frame_info fi;
++ 
++   fi= get_frame_info( selected_frame);
++   return find_pc_line(fi.pc, fi.next_frame);
++ }
++ 
++ #endif /* TOOL */
+  \f
+  /* 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).
+End of context diffs.  The presence of this line verifies that this message
+has not been truncated.
+
diff --git a/gdb/COPYING b/gdb/COPYING
new file mode 100644 (file)
index 0000000..9f3a6dc
--- /dev/null
@@ -0,0 +1,138 @@
+
+                   GDB GENERAL PUBLIC LICENSE
+                   (Clarified 20 March 1987)
+
+ Copyright (C) 1986 Richard M. Stallman
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license, but changing it is not allowed.
+
+  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.
+
+
+                       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) 1986 Free Software Foundation, Inc." (or with the year updated if
+that 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) 1986 Free Software Foundation, Inc." (or with
+    the year updated if 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.
+
+  3. You may copy and distribute GDB 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) cause each such copy to be accompanied by the
+    corresponding machine-readable source code, which must
+    be distributed under the terms of Paragraphs 1 and 2 above; or,
+
+    b) cause each such copy to be accompanied by a
+    written offer, with no time limit, to give any third party
+    free (except for a nominal shipping charge) a machine readable
+    copy of the corresponding source code, to be distributed
+    under the terms of Paragraphs 1 and 2 above; or,
+
+    c) in the case of a recipient of GDB in compiled, executable
+    or object code form (without the corresponding source code) you
+    shall cause copies you distribute to be accompanied by a copy
+    of the written offer of source code which you received along
+    with the copy you received.
+
+  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.
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
new file mode 100644 (file)
index 0000000..301bdac
--- /dev/null
@@ -0,0 +1,1025 @@
+Fri Jan 15 05:09:18 1988  Richard Stallman  (rms at frosted-flakes)
+
+       * valprint.c [IEEE_FLOAT]: New function `is_nan' checks
+       whether a double is a nan.
+
+       * printcmd.c (print_formatted) [IEEE_FLOAT]:
+       Detect nans and print specially.
+       * valprint.c (val_print) [IEEE_FLOAT]: Same thing.
+
+       * m68k-pinsn.c (convert_{to,from}_68881): Hand-assemble
+       all the assembler code.
+
+       * m-newsinit.h, m-news800.h: Two new files.
+
+Thu Jan  7 22:25:16 1988  Richard Stallman  (rms at frosted-flakes)
+
+       * valops.c (value_assign): Don't coerce the arg being stored in.
+       Coercion is not right either for an array or for an enum.
+
+Tue Jan  5 00:59:29 1988  Richard Stallman  (rms at frosted-flakes)
+
+       * symtab.c (decode_line_1): Don't complain about no symtabs loaded
+       until after trying the misc function table.
+
+Sat Jan  2 13:16:08 1988  Richard Stallman  (rms at frosted-flakes)
+
+       * stack.c (record_selected_frame): New fn to access
+       the selected frame and its level.
+       * infcmd.c (run_stack_dummy): Save and restore the selected
+       frame and its level.
+
+Wed Dec 30 18:44:41 1987  Richard Stallman  (rms at frosted-flakes)
+
+       * valprint.c (type_print_varspec_prefix):
+       Treat arrays just like functions.
+       * valprint.c (type_print_varspec_{prefix,suffix}):
+       When passed_a_ptr is handled, pass 0 for it in the recursive call.
+
+Fri Dec 18 10:24:14 1987  Richard Stallman  (rms at frosted-flakes)
+
+       * findvar.c (read_var_value): Share code between values really
+       in registers and values in saved registers.
+       Register short on a big-endian machine needs a VALUE_OFFSET.
+
+       * findvar.c (locate_var_value): Offset the address of a
+       saved register variable that's shorter than the register.
+
+Thu Dec 17 08:26:31 1987  Richard Stallman  (rms at lucky-charms)
+
+       * valprint.c (type_print_base): Print nameless bit fields
+       to indicate gaps before bit fields.
+
+       * source.c (select_source_symtab): Ignore .h files.
+       Also, if a function `main' exists, make the default listing line
+       the beginning of `main'.
+
+       * breakpoint.c ({get,set}_breakpoint_commands):
+       Commands to examine or set the pending breakpoint-commands.
+
+       * infcmd.c (run_stack_dummy): Save and restore the breakpoint
+       commands around the function call.
+
+       * stack.c (return_command): Don't query or print if not interactive.
+
+       * value.h (COERCE_ENUM): New macro: if arg is enum, convert to int.
+       * value.h (COERCE_ARRAY): Do that, as well as old job.
+
+       * valarith.c (value_binop, value_neg, value_lognot):
+       Use COERCE_ENUM on the arguments.
+       * valops.c (value_arg_coerce): Likewise.
+       * valops.c (value_cast): AVOID coercing enums when arrays are.
+
+       * eval.c (evaluate_subexp): In the BINOP_SUB case,
+       use evaluate_subexp_with_coercion.
+
+       * inflow.c (terminal_ours_1, terminal_inferior):
+       Ignore inferior_thisrun_terminal since our terminal
+       is the inferior's controlling terminal regardless.
+
+       * m-sun3.h: Fix assembler syntax for kdb macros.
+
+       * infcmd.c ({attach,detach}_command): New functions from Dave Taylor.
+       * inflow.c (attach, detach): New functions from Dave Taylor.
+       * infrun.c (attach_process): New function, middle-level.
+       Does all the work of attaching a process, assuming there is no
+       inferior yet, except for printing and querying.
+
+       * infrun.c (clear_proceed_status): Clear `stop_after_attach'.
+       * infrun.c (wait_for_inferior): Handle `stop_after_attach'.
+
+Sat Dec 12 04:36:39 1987  Richard Stallman  (rms at corn-chex)
+
+       * dbxread.c (end_symtab): The free_code for a symseg got
+       from a file should be free_linetable.
+
+       * dbxread.c: Allocate blockvector, blocks, symbols and symbol names
+       from the symbol-obstack, and use free_linetable for all files.
+       The typevector is still malloc'd, so put it in the free_ptr
+       to get it freed.
+
+       * symmisc.c (free_symtab): Always free the `free_ptr' if nonzero.
+       `free_explicit' therefore now the same as `free_nothing'.
+
+       * dbxread.c (define_symbol): Handle defn code 'c', used by
+       fortran, which defines integer and real constant symbols.
+
+       * symseg.h: Define LOC_CONST_BYTES for constants longer than a
+       word.  New `bytes' alternative for the value of a symbol.
+
+       * symtab.h (SYMBOL_VALUE_BYTES): Macro to access `bytes'.
+
+       * findvar.c ({read,locate}_var_value): Handle LOC_CONST_BYTES.
+       * printcmd.c (address_info): Handle LOC_CONST_BYTES.
+       * symmisc.c (print_symbol): Handle LOC_CONST_BYTES.
+
+Tue Dec  8 20:26:37 1987  Richard Stallman  (rms at frosted-flakes)
+
+       * symtab.c (find_line_pc_range): Detection of last line in file
+       was erroneous.
+
+Fri Dec  4 21:52:52 1987  Richard Stallman  (rms at frosted-flakes)
+
+       * dbxread.c (read_range_type): Accept the typenums as argument.
+       Use read_type_number to read the subrange-of type.
+       A type defined as a subrange of itself is void.
+
+Thu Dec  3 12:45:10 1987  Richard Stallman  (rms at frosted-flakes)
+
+       * inflow.c ({fetch,store}_inferior_registers): Support UMAX_PTRACE.
+
+       * m-umax.h: New file, for Encore machines.
+
+       * core.c (exec_file_command, etc): Decode COFF files.
+       * core.c (core_file_command): Support UMAX_CORE format.
+       * core.c (validate_files, exec_file_command):
+       Set exec_mtime in exec_file_command so that COFF vs non-COFF
+       differences appear all in one place.
+
+       * coffread.c: New file from Dave Johnson.
+
+       * core.c (specify_exec_file_hook): New function to specify
+       a hook to be called by exec_file_command.  Last #ifdef X_WINDOWS gone.
+       * xgdb.c (initialize): Specify a hook.
+
+       * infrun.c, inferior.h: Replace stop_r0 and stop_r1 with an array
+       `stop_registers' that will hold ALL the registers.
+       * infcmd.c (run_stack_dummy): Get the value from `stop_registers'
+       and copy all of that into BUFFER.
+       * infcmd.c (finish_command): Specify `stop_registers'
+       to `value_being_returned'.
+       * values.c (value_being_returned): Use the new EXTRACT... macros.
+       * values.c (set_return_value): Use new STORE_RETURN_VALUE macro.
+       * valops.c (call_function): Allocate retbuf long enough for all regs.
+       * m-*.h: New macros EXTRACT_RETURN_VALUE, STORE_RETURN_VALUE and
+       EXTRACT_STRUCT_VALUE_ADDRESS that express machine-dependencies
+       in where return values are stored.
+
+       * valops.c (call_function): Flush default for CALL_DUMMY_START_OFFSET.
+       Assume it is defined.
+       * m-vax.h: Define CALL_DUMMY_START_OFFSET.
+
+       * ns32k-pinsn.c (ns32k-localcount): Fix decoding of `enter' insn.
+       * ns32k-pinsn.c (n32k_get_enter_addr): New fn used from m-umax.h.
+
+       * m-*.h: Change INVALID_FLOAT to accept 2nd arg which is length
+       of the float.
+       * values.c (unpack_double): Pass the 2nd arg.
+       * vax-pinsn.c (print_insn_arg): Pass the 2nd arg.
+       * infcmd.c (registers_info): Pass the 2nd arg.
+
+Wed Nov 25 15:06:55 1987  Richard Stallman  (rms at frosted-flakes)
+
+       * Bug fixes by David Johnson (ddj%cs.brown.edu@relay.cs.net).
+
+       * symtab.c (list_symbols): Print typedef names, and don't call
+       them `static'.
+
+       * symmisc.c (print_symtabs): Allow immediate quit, and close the
+       output file if that happens.
+
+       * stack.c (frame_command): Declare args `unsigned' so a negative
+       number is a frame address, not a level number.
+
+       * source.c: Check for error-return from calls to `getwd'.
+
+       * printcmd.c (address_info): Fix error in case of a function name.
+
+       * inflow.c (create_inferior): Return the inferior pid properly.
+
+       * inferior.h: Define `inferior_io_terminal'.
+       * infrun.c (tty_command): New command to specify inferior_io_terminal.
+       * inflow.c (new_tty): Open specified terminal for the inferior.
+       * inflow.c (terminal_{ours,inferior}): Do nothing if inferior was
+       started with its own terminal.
+       * main.c (main): -t switch calls `tty_command'.
+
+       * expread.y (rule for `block'): `copy_name' was called in wrong
+       place and with wrong args.
+
+       * dbxread.c: Entire file #ifdef READ_DBX_FORMAT.
+       * m-*.h: Define READ_DBX_FORMAT.
+
+       * breakpoint.c (initialize): Error in doc string of `info breakpoints'.
+
+Wed Nov 11 12:57:28 1987  Richard Stallman  (rms at frosted-flakes)
+
+       * ns32k-opcode.h, ns32k-pinsn.c: Two new files.
+       * m-merlin.h: New file, for one 32000 box.
+
+Mon Nov  9 10:31:42 1987  Brian Fox  (bfox at sugar-smacks)
+
+       * eval.c (evaluate_subexp): Made the case of OP_FUNCALL use
+       evaluate_subexp_with_coercion, so that array references would
+       get converted into pointer references.
+
+Mon Nov  9 05:50:24 1987  Richard Stallman  (rms at sugar-smacks)
+
+       * breakpoint.c (ignore_command): Error if no arg.
+
+Sat Nov  7 13:57:40 1987  Richard Stallman  (rms at frosted-flakes)
+
+       * main.c (quit_command): Get rid of execfile before the kill_inferior.
+
+       * xgdb.c: New file, interface to X windows.
+
+       * main.c (main): Look for flag arguments before
+       calling the initialization functions.  -nw switch sets
+       `inhibit_windows' which xgdb.c looks at.
+       * main.c (command_loop): Call the window hook function, if any.
+
+       * source.c (get_filename_and_charpos): New function
+       that interfaces to find_source_lines.
+       * source.c (source_line_charpos, source_charpos_line):
+       New functions translate source line number to char pos and vice versa.
+
+       * breakpoint.c (describe_other_breakpoints): New subroutine
+       to list all breakpoints at PC in a message about "other
+       breakpoints".
+       * breakpoint.c (break_command_1): Use describe_other_breakpoints.
+       * breakpoint.c (set_breakpoint): Like break_command_1
+       but takes arg predecoded into symtab and line.
+
+       * core.c (exec_file_command): Call xgdb_display_exec_file.
+
+       * valprint.c (type_print_base): For struct bitfields,
+       print the bit size.
+
+Thu Aug 20 02:46:47 1987  Richard M. Stallman  (rms at prep)
+
+       * Version 2.4.
+
+       * m68k-pinsn.c (print_insn_arg): Implement place = '3'.
+
+       * findvar.c (write_register_bytes): Arg to
+       store_inferior_registers should be -1: write all registers.
+
+       * dbxread.c (symbol_file_command): If no arg,
+       just discard all symbols.
+
+       * core.c (myread): Flush the 4th arg (filename).
+       * source.c (find_source_lines): Don't pass 4th arg.
+       * symmisc.c (read_symsegs): Ditto.
+
+       * dbxread.c (process_one_symbol): One call to `define_symbol'
+       lacked 3rd arg.
+
+       * inflow.c (write_inferior_memory): On failure, return the errno value.
+       * core.c (write_memory): ditto.
+       * breakpoint.c ({insert,remove}_breakpoints): ditto.
+       * utils.c (print_sys_errmsg): Like perror_with_name but don't
+       signal an error; also, the error code is an arg instead of from
+       `errno'.
+       * infrun.c : Save the value from insert_breakpoints and pass it to
+       print_sys_errmsg.
+
+       * main.c (input_from_terminal_p): Put in omitted `return'.
+
+       * Makefile (expread.o): Use $(CC).
+
+Sun Jun  7 04:42:51 1987  Richard M. Stallman  (rms at prep)
+
+       * version.c: Version 2.3.
+
+       * inflow.c (terminal_ours): Save fcntl flags correctly.
+       * inflow.c (term_status_command):
+       Print the tchars and ltchars structures, byte by byte.
+
+Mon May 25 14:37:14 1987  Richard M. Stallman  (rms at prep)
+
+       * version.c: Version 2.2.
+
+       * breakpoint.c (do_breakpoint_commands):
+       Advance breakpoint_commands before executing the command,
+       in case command is `cont' and it hits another bpt with commands.
+
+Sun May 24 20:45:04 1987  Richard M. Stallman  (rms at prep)
+
+       * value.h: Declare `contents' long and cast its address to char *.
+
+       * expread.y (prefixify_expression): Don't call alloca among the decls.
+
+       * printcmd.c (print_variable_value): Flush unused local `space'.
+
+       * main.c (execute_command): Barf on "user" like other class names.
+
+Fri May 22 01:34:37 1987  Richard M. Stallman  (rms at prep)
+
+       * m68k-pinsn.c (fetch_arg): New arg position 'j', for movec.
+       (print_insn_arg): New arg syntax 'J', for movec.
+       * m68k-opcode.h: movec uses 'Jj'.  Everything reformatted.
+       bf... and cas... insns were corrected.
+
+       * inflow.c (create_inferior): Fork and exec with given args and env.
+       Call close_exec_file.
+       (inferior_died): Record the fact that the inferior no longer exists.
+       Call reopen_exec_file.
+
+       * core.c (close_exec_file): New fn: Close the execchan if it's open.
+       (reopen_exec_file): New fn: Reopen execchan if not currently open.
+
+       * infrun.c (wait_for_inferior): Call inferior_died if it exits.
+
+       * infcmd.c (run_command): Don't fork and exec; call create_inferior.
+
+       * findvar.c (read_var_value): For reg var in a convertable reg,
+       fetch reg in its own virtual type and then cast to variable's type.
+
+       * symtab.h: Declare xmalloc to return char *.
+
+       * dbxread.c (read_dbx_symtab): Record static text syms as
+       misc-functions.  But if an assembler symbol supplies the address
+       for a debugger symbol, don't record it as a misc-function.
+
+       * utils.c (query): Do clearerr (stdin) frequently in case of C-d.
+
+       * dbxread.c (process_one_symbol, define_symbol):
+       Pass the stab's DESC down to define_symbol.
+       DESC = 0 means GCC output: if type is "short", believe it.
+
+       * dbxread.c (read_enum_type): Don't allocate the type here;
+       take it as an argument.  (Like read_struct_type.)
+       (read_type)): Before call to read_enum_type, allocate the type
+       or get the one already allocated.
+
+       * printcmd.c (print_frame_args): Print a comma before
+       every arg except the first.
+
+Wed May 13 00:36:00 1987  Richard M. Stallman  (rms at prep)
+
+       * m68k-pinsn.c (convert_{to,from}_68881):
+       Hand-assemble the fmoved and fmovex insns.
+
+       * dbxread.c (define_symbol): For case 'p', a parameter,
+       if specified type is short or char, change it to int.
+       This is for how PCC handles arguments.
+       Define new case 'P' that does what 'p' used to do.
+       Maybe GCC will use this.
+
+Mon May  4 21:52:44 1987  Richard M. Stallman  (rms at prep)
+
+       * main.c (main): If SET_STACK_LIMIT_HUGE, set the
+       run-time stack limit as high as it can go.
+       * m-sun3.h, m-vax.h: define SET_STACK_LIMIT_HUGE.
+
+Sun May  3 08:46:23 1987  Richard Mlynarik  (mly at prep)
+
+       * command.c, expread.y, findvar.c, infcmd.c, inflow.c, utils.c,
+       values.c, defs.h:  Various ANSI C compatibility changes
+       (fouts@wilbur.arpa <8705010117.AA13112@wilbur.arpa>)
+
+       * core.c, inflow.c: Fix calls to supply_register.
+       * findvar.c (supply_register): Instead of register value as int,
+       pass address of buffer in core containing contents in raw form.
+
+Sat Apr 18 17:09:42 1987  Richard Mlynarik  (mly at prep)
+
+       * main.c (command_loop):
+       Do any cleanups made by a executing a command each time around.
+
+       * source.c (directory_command):
+       make_cleanup (free, dirname), not
+       make_cleanup (free_current_contents, &dirname)
+       (rlk <8704180416.AA29572@PARIS.MIT.EDU>)
+
+Mon Apr 13 20:28:26 1987  Leonard H. Tower Jr.  (tower at prep)
+
+       * gdb.1: fixed typo and italicization errors.
+       (<kgk%cs.brown.edu@RELAY.CS.NET> id AA16470;Sun,12 Apr 87 14:30:07 EST)
+
+Sat Apr 11 15:41:01 1987  Richard Mlynarik  (mly at prep)
+
+       * dbxread.c (read_dbx_symtab):
+       No name for symbol => "" not 0 (avoid referencing memory 0)
+       (tower <8704081854.AA00135@buit3.bu.edu>)
+
+Mon Mar 30 22:24:07 1987  Leonard H. Tower Jr.  (tower at prep)
+
+       * gdb.1: Unix style manual page pointing at internal gdb
+       documentation, and info sub-system in GNU Emacs.
+
+Fri Mar 20 12:07:15 1987  Richard M. Stallman  (rms at prep)
+
+       * COPYING: Clarifications about distribution fees and mixing.
+       * main.c (copying_info): Same changes.
+
+Tue Mar 17 17:40:14 1987  Richard M. Stallman  (rms at prep)
+
+       * values.c (unpack_field_as_long): Avoid >>= operator
+       since ISI compiler has a bug.
+
+Sat Mar  7 12:19:35 1987  Richard M. Stallman  (rms at prep)
+
+       * GDB version 2.1.
+
+       * values.c (unpack-field-as-long): Tests for endianness were broken.
+       * findvar.c (read_var_value):
+       Now we initialize the union as an int and test it as a char.
+
+Sun Mar  1 16:16:20 1987  Richard M. Stallman  (rms at prep)
+
+       * main.c (define_command): Command class symbols
+       must be cast to int.
+
+Mon Feb 23 02:47:44 1987  Richard M. Stallman  (rms at prep)
+
+       * source.c (list_command): Reword error messages.
+       New message for case of first arg not just a line-number
+       and no symtab specified by it.
+
+Sun Feb 22 21:15:19 1987  Richard M. Stallman  (rms at prep)
+
+       * dbxread.c (compare_misc_functions):
+       Compare the addresses as unsigned numbers.
+
+Sun Feb 22 13:11:45 1987  Richard Mlynarik  (mly at prep)
+
+       * main.c (define_command, document_command):
+       Stuff was being unnecessarily malloced (-and- not freed!)
+
+       * main.c (execute_command):
+       User-defined commands don't take args.
+       Don't confuse empty user command with no command.
+       Replace bogus `etext' test with a comparison against
+       class_user.
+
+       * main.c (define_command):
+       If the command of the specified name is built-in, note that when
+       asking whether to redefine it (this is suppressed for class_alias
+       -- should it not be?)
+
+       * main.c (define_command):
+       If command was previously built-in, don't preserve its
+       documentation (otherwise could get error later when trying to free
+       the non-malloced text of built-in documentation strings)
+
+Tue Feb 17 16:23:57 1987  Richard Mlynarik  (mly at prep)
+
+       * main.c (echo_command): Don't die if not given any arg.
+       * main.c (cd_command):  Echo new cwd if interactive.
+
+Thu Feb 12 11:22:56 1987  Richard M. Stallman  (rms at prep)
+
+       * stack.c (initialize): "bt" now appears in help aliases.
+
+       * Version 2.0 released.
+
+Wed Feb 11 17:45:45 1987  Richard M. Stallman  (rms at prep)
+
+       * m68k-opcode.h: Errors corrected in several instructions
+       and reordering done for assembler's sake.
+
+       * m-vax.h (POP_FRAME): End with call to set_current_frame.
+
+Tue Feb 10 15:06:07 1987  Richard M. Stallman  (rms at prep)
+
+       * infrun.c (wait_for_inferior): Set stop_print_frame to 1
+       after checking breakpoint condition.
+
+       * infcmd.c (run_stack_dummy): Save many flags.
+
+Thu Feb  5 07:12:20 1987  Richard Mlynarik  (mly at prep)
+
+       * source.c (directory_command):
+       Step over `:'
+
+Mon Feb  2 23:40:32 1987  Richard M. Stallman  (rms at prep)
+
+       * infcmd.c (set_environment_command): Fix stupid error
+       for case where no "=" appears in the string.
+
+Mon Jan 26 13:46:52 1987  Richard M. Stallman  (rms at prep)
+
+       * printcmd.c (print_frame_args): Round end-of-arg offset
+       up rather than down to multiple of int.
+
+Fri Jan 23 15:11:50 1987  Richard M. Stallman  (rms at prep)
+
+       * source.c (directory_command): If dir is not added cause already
+       present, print explanation.
+
+       * infrun.c (proceed): Use read_pc (), not stop_pc,
+       to get current pc to think about.  stop_pc could have been
+       clobbered by call_function.
+
+Fri Jan 23 15:00:55 1987  Richard Mlynarik  (mly at prep)
+
+       * source.c (directory_command):
+       If dir is already in source_path, don't append another copy of it.
+
+Thu Jan 22 00:31:03 1987  Richard M. Stallman  (rms at prep)
+
+       * Version 2.0.
+
+       * blockframe.c (get_pc_function_start):
+       Understand misc functions.
+
+       * core.c (core_file_command):
+       Copy all register contents into the array `registers'
+       Save a.out header of executable file in core_aouthdr.
+       Print name of executable file that was running, if we know
+       where to find it.
+
+       * core.c (exec_file_command):
+       Save a.out header in exec_aouthdr and file's mtime
+       in exec_mtime.
+
+       * core.c (validate_files): Check that core file's a.out hdr
+       matches exec file's.
+
+       * New handling of registers:
+       Now all registers are fetched once when the program stops or
+       when a core file is selected.  Their contents are kept in
+       `registers', an array of bytes.  This is done by
+       `fetch_inferior_registers'.  `read_register', etc., just look
+       there.  Writing a register works through
+       `store_inferior_registers' which writes one or all registers
+       from `registers' back to the inferior.
+
+       A register now can have a "raw" data format and a "virtual"
+       data format, which may require conversion or even be different sizes.
+       The conversion can be different for different registers.
+       For example, the 68000 cpu registers need no conversion
+       and both raw and virtual size is 4, but the 68881 floating point
+       registers have raw size 12 (for extended fmt) and virtual size 8
+       (for double).  Macros in the m- file such as REGISTER_BYTES,
+       REGISTER_BYTE, REGISTER_{RAW,VIRTUAL}_SIZE, and
+       REGISTER_CONVERT_TO_{RAW,VIRTUAL} control these things.
+
+       `read_register' and `write_register' are usable only on registers
+       which hold an int and need no conversion (raw fmt = virtual fmt).
+       For other registers, `read_register_bytes' is used, or
+       `read_relative_register_raw_bytes'.
+
+       * m-sun3.h: Define the 68881 fp registers.
+       Know how to recognize insns that save them.
+       Make dummy frames save them.
+
+       * core.c (read_register, write_registers): Functions deleted.
+       * findvar.c (read_register, write_registers): New functions,
+       not the same as the old ones of the same name.
+
+       * findvar.c (supply_register): Function used by
+       fetch_inferior_registers, etc., to install the register
+       values fetched from the inferior.
+
+       * findvar.c (read_register_bytes, write_register_bytes):
+       Read spec'd number of bytes from the byte-array `registers'.
+
+       * findvar.c (read_relative_register_raw_bytes):
+       Replaces old function `read_relative_register'; accepts
+       address of where to store the contents; # bytes stored is size
+       of the specified register in raw format.
+
+       * findvar.c (value_of_register, read_var_value):
+       Convert register values and values of register variables
+       from raw format to virtual format.
+
+       * findvar.c (locate_var_value): Like `read_var_value' but
+       returns value for variable's address.
+
+       * value.h: Add new field VALUE_REGNO to each value.  It holds
+       register number to control virtual-to-raw conversion
+       for assignments to the value.
+
+       * valops.c (value_assign): Convert data from virtual to raw format
+       if value came from a register variable.
+       Use read_register_bytes and write_register_bytes.
+
+
+       * infcmd.c (continue_command): Subtract 1 from arg
+       before setting breakpoint's ignore-count.
+
+       * infcmd.c (jump_command): Query if spec'd line is outside
+       of the current function.
+
+       * infcmd.c (finish_command): Now finish the selected frame,
+       and no arg required.
+
+       * infcmd.c (set_environment_command): Allow space to separate
+       varname and value.
+
+       * infcmd.c (registers_info): Print both raw and virtual data
+       format if they differ.  Allow register name as arg.
+       Ask for a Newline each 16 registers.
+
+       * inflow.c (kill_inferior): call mark_breakpoints_out.
+       * inflow.c ({fetch,store}_inferior_registers for Sun):
+       Get the fp registers and store them in right places in
+       `registers'.
+       * inflow.c ({read,write}_inferior_register): Deleted.
+
+       * infrun.c (wait_for_inferior): Single-stepping is not considered
+       to have hit a breakpoint unless the pc before the step matches the
+       address of the breakpoint.  Necessary on machines where
+       breakpoints leave the pc incremented.
+
+       If shell gets SIGSEGV, pass the signal silently to it.
+
+       * m68k-pinsn.c, m68k-opcode.h:
+       Add the 68881 instructions.  New operand codes `F', `I', `s'
+       and `k' are needed for them.  New place codes `78tcik'.
+       NEXTBYTE now skips a word but fetches just a byte.
+       Explicit sign-extension removed from NEXTBYTE and NEXTWORD.
+       NEXTSINGLE, NEXTDOUBLE, NEXTEXTEND and NEXTPACKED defined.
+       Various changes to implement the new operand and place codes.
+       print_index changed because displacement-size codes for
+       word and long displacement were interchanged.
+
+       * m68k-pinsn.c (convert_{from,to}_68881): Functions added
+       to support REGISTER_CONVERT_TO_{RAW,VIRTUAL} on 68000.
+
+       * main.c (main): Move around calls to setjmp.
+       * main.c (define_command, document_command):
+       Accept a from_tty argument instead of calling input_from_terminal_p.
+
+       * printcmd.c (address_info): Print info on class and address
+       of a specified symbol.  For register symbols, gives name of register.
+
+       * printcmd.c (print_command): Remember explicitly whether
+       `make_cleanup' was called.
+
+       * printcmd.c (print_frame_args): Know how arg-addresses vary with
+       data type on big-endian machines.
+
+       * source.c (directory_command): Detect `:' in arg and reject it.
+       Free the old directory-path.  Simplify things like `/.' in
+       dirname.
+
+       * source.c (openp): Simplify `./' in specified name.
+
+       * source.c (find_source_lines): Compare source mtime against
+       `exec_mtime' and warn if source is newer.
+
+       * source.c (line_info): No arg means use last line listed
+       or line following last one this command was used on.
+       If from tty, clear out argument so Return is like `i li' without
+       arg.
+
+       * stack.c (frame_info): Print addresses registers are saved at.
+
+       * stack.c (return_command): When asking for confirmation, give
+       name of function that will be made to return.
+
+       * valops.c (call_function): If function type is
+       pointer-to-function, dereference it to compute return type.
+       If pointer-to-object, assume function returns int.
+       If char, assume that the value's address is the function address
+       (because it's a misc functon).  If int, the value itself is the
+       function address.
+
+       * dbxread.c (compare_symbols): Sort register symbols
+       before all others.
+
+       * eval.c (evaluate_subexp_for_address): New function like
+       `evaluate_subexp' but returns a value for the address where
+       the subexpression's value would be located.
+
+       * eval.c (evaluate_subexp_for_sizeof): New function like
+       `evaluate_subexp' but returns a value for the size of the subexp.
+
+       * eval.c (evaluate_subexp_with_coercion): Like `evaluate_subexp'
+       but coerces arrays to pointers (without taking the time to
+       read the array contents).
+
+       * eval.c (evaluate_subexp): Use the three new functions above
+       when appropriate instead of calling self recursively.
+
+Wed Jan 14 17:00:03 1987  Richard Mlynarik  (mly at prep)
+
+       * core.c (core_file_command):
+       Use correct file in calls to perror_with_name
+
+Mon Jan 12 03:34:35 1987  Richard Mlynarik  (mly at prep)
+
+       * breakpoint.c (map_breakpoint_numbers):
+       Err if no args not supplied, otherwise would get mpv.
+
+       * main.c (main):
+       Command-line arg "-d dir" adds dir to source-file directory
+       search-list.
+
+Sun Jan 11 19:19:52 1987  Richard Mlynarik  (mly at prep)
+
+       * symmisc.c (free_all_symtabs):
+       Don't call free on 0.
+
+       * core.c (exec_file_command):
+       Use correct name in call to perror_with_name.
+       Record absolute pathname.
+       Don't savestring an arg to concat.
+
+       * dbxread.c (symbol_file_command):
+       Record absolute name of pathname opened.
+       Print a message if file doesn't have a symbol-table.
+       Don't savestring an arg to concat.
+
+       * source.c (openp):
+       Add new arg filename_opened, which if non-zero will be set to a
+       malloced string of the absolute name of the actual filename opened.
+
+       * breakpoint.c (clear_command):
+       If from_tty or cleared more than one breakpoint at location,
+       print which bpts were deleted.
+
+       * breakpoint.c (break_command_1, break_command, tbreak_command):
+       If from_tty, mention any other breakpoints set at same location.
+
+       * symtab.c (decode_line_1):
+       If no symtabs, err mentioning `symbol-file' command rather than
+       saying "function foo not defined"
+
+Fri Jan  9 01:25:19 1987 Richard Mlynarik  (mly at prep)
+
+       * main.c (set_prompt_command):
+       Add support command "set-prompt"
+
+       * printcmd.c (undisplay_command):
+       Fix paren error to make "undisplay <number>" work.
+
+Wed Jan  7 12:06:09 1987  Richard Mlynarik  (mly at prep)
+
+       * main.c (print_gdb_version, gdb_version_info):
+       Add command "info version" to report the version
+       of gdb for use in bug reports.
+
+       * infcmd.c:
+       Ensure inferior_args always points to string starting with a space
+       and is never 0. 
+
+       * printcmd.c: (clear_displays, undisplay_command):
+       Fix bug in clear_displays which led to looping.
+       Make undisplay_command call it instead of wrong-looking code which
+       looked at (display->number == 0) instead of (display == 0) to
+       determine if it were at the end of the chain.
+
+Mon Dec 15 20:57:06 1986  Richard M. Stallman  (rms at prep)
+
+       * utils.c (query): Don't ignore a second line if given a null line.
+
+       * infrun.c (normal_stop): Print "bug in shell" message
+       only for a segmentation fault.
+
+       * main.c (main): Read init file from home directory if any,
+       before init file from current directory.
+
+Thu Dec  4 09:05:35 1986  Richard M. Stallman  (rms at prep)
+
+       * source.c (select_source_symtab): Don't ref thru arg if null.
+
+       * m68k.opcode.h: For trap instruction code, use type T.
+       * m68k-pinsn.c (print_insn_arg): Recognize new arg-code T
+       and print the trap vector properly.
+
+       * m-sun[23].h (FRAME_FIND_SAVED_REGS): Recognize a movl REG,-(sp)
+       as a way to save one register.  Recognize clrw -(sp); movw -(sp)
+       after saving regs as a way to save the PS register.  Adjust the
+       way to find the starting pc of a stack dummy frame for the fact
+       that these frames now save the PS.
+
+       * m-sun[23].h (POP_FRAME): Restore PS register if frame saved it.
+
+       * m-sun[23].h (PUSH_DUMMY_FRAME): Push the old PS register.
+
+       * m-sun[23].h (CALL_DUMMY, etc.): Fix erroneous binary code for
+       the addl #nnn,sp instruction.  Insert clrw -(sp); movw -(sp)
+       to indicate that the PS has been saved.
+
+       * infrun.c (wait_for_inferior): If inferior exits, call
+       mark_breakpoints_out so it works to delete breakpoints afterward.
+
+       * infrun.c (normal_stop): After popping a stack dummy frame,
+       select the frame that we get to.
+
+       * dbxread.c (process_one_symbol): Store new `depth' field
+       in all context_stack elements created.  For N_RBRAC, test
+       that depth matches that in the context_stack; if not, error.
+
+       * dbxread.c (all callers of error): Make all error messages
+       start "Invalid symbol data: " and end with value of symnum.
+       Also change a few aborts to errors.
+
+Mon Dec  1 20:20:37 1986  Richard M. Stallman  (rms at prep)
+
+       * version.c: Version 1.11.
+
+       * breakpoint.c (condition_command): If no condition spec'd,
+       print "breakpoint N now unconditional".
+
+       * breakpoint.c (commands_command): Give different error messages
+       for cases of args not containing a breakpoint number
+       and args containing anything after the breakpoint number.
+
+       * commands.c (lookup_command): Don't store a zero in *p
+       if have an undefined subcommand that is not an error.
+
+       * commands.c (lookup_command): For recursive call,
+       pass subcommand list properly.  Was passing the address
+       of the word containing the list.
+
+       * core.c ({core,exec}_file_name): If no arg, tell user
+       what the effect is.
+
+       * dbxread.c (define_symbol): Accept class code 'v'
+       for static variable within a function.
+
+       * dbxread.c (read_type): Now allow any plain number or
+       pair of numbers in parens, with no code letter.  This means
+       define new type same as type with specified number, or define
+       it as void if specified number's type is not yet mentioned.
+
+       * m68k-pinsn.c (print_insn_arg): Case of general operand
+       in byte insn that happened to be immediate used wrong arg-size.
+
+       * printcmd.c (set_next_address): Set next_address from arg
+       and also set value of `$_' from it.
+
+       * printcmd.c (do_examine): Save address in last_examine_address
+       and value fetched to examine in last_examine_value.
+
+       * printcmd.c (x_command): Copy last_examine_{address,value}
+       into values of `$_' and `$__'.  Change `x' documentation string.
+
+       * source.c (directory_command): Query when no args now says
+       what new value it wants use for the path.
+
+       * source.c (list_command): Don't die in cases like `list ,+30'.
+
+       * source.c (line_info): Call `set_next_address' to make `x'
+       display the text of the line.  Change `info list' doc string.
+
+Sat Nov 29 07:59:29 1986  Richard M. Stallman  (rms at prep)
+
+       * printcmd.c (undisplay_command): If get no arg,
+       rather than crashing, query and then delete undisplay everything.
+
+Fri Nov 28 15:43:52 1986  Richard M. Stallman  (rms at prep)
+
+       * dbxread.c (process_one_symbol): If N_LBRAC sym
+       has a greater value that N_RBRAC, ignore the
+       N_LBRAC value and give the block zero length.
+
+Tue Nov 25 03:10:12 1986  Richard M. Stallman  (rms at prep)
+
+       * dbxread.c (process_one_symbol): Ignore N_NSYMS symbols
+       that appear in Ultrix.
+
+Sat Nov 22 22:49:06 1986  Richard M. Stallman  (rms at prep)
+
+       * version.c: version 1.10.
+
+       * valprint.c (type_print*):
+       SHOW < 0 now means abbreviate struct/union members
+       or enum values with `...'.  SHOW now decremented on
+       each recursion in type_print_base.  Several places
+       that used to check !show now check show <= 0.
+
+       * valprint.c (val_print): Pass -1 for SHOW to type_print
+       when printing typename inside parens or braces.
+
+       * printcmd.c (print_command): If no value specified to print,
+       print the value of $.
+
+       * expression.h, expread.y, eval.c, expprint.c:
+       OP_MEMVAL renamed UNOP_MEMVAL
+       and now allows any expression, not just an integer address.
+       It now has same format as UNOP_CAST and works almost like it.
+       Each place that referred to it has been rewritten
+       starting with a copy of the code that handles UNOP_CAST.
+       Doc for `print' command changed for this.
+
+       * source.c (init_source_path):
+       Free and zero out any line_charpos's saved in source symtabs.
+
+       * breakpoint.c (condition_command):
+       Parse the condition in the environment of the code where the
+       breakpoint is set.  This requires finding the breakpoint
+       before parsing, so code is rearranged.
+
+       * dbxread.c (dbx_alloc_type):
+       New function given typenums returns the type for those typenums
+       or allocates a new, empty type for those typenums and returns it.
+
+       * symtab.c (smash_type_to_{pointer,function}):
+       New functions modify an already-allocated type object
+       to be a pointer to or function returning some given type.
+
+       * dbxread.c (read_type): Uses dbx_alloc_type in many cases.
+       Reading a pointer or function type now works by doing that,
+       then reading the value type or type pointed to, then smashing
+       it into the type already allocated.  This makes some fwd refs win.
+       Likewise for structs and unions.
+
+       * dbxread.c (read_struct_type): Now receives the type object
+       as args.  Used to get typenums as args and look up the type
+       itself.
+
+       * dbxread.c (symbol_file_command):
+       At very end, clear out any type name that `char *' has received.
+
+Thu Nov 20 16:43:53 1986  Richard M. Stallman  (rms at prep)
+
+       * m-sun2.h, m-sun3.h (FIND_FRAME_SAVED_REGS):
+       Was incrementing address even for regs not saved.
+
+Sun Nov 16 14:59:07 1986  Richard M. Stallman  (rms at prep)
+
+       * values.c (value_field): Was adding in byte offset
+       before calling unpack_field_as_long, which itself
+       adds in the offset.  Now pass addr of start of structure.
+
+       * infrun.c (normal_stop): Clean up inferior_pid conditionals:
+       just return early if no inferior.
+
+Thu Nov 13 15:45:50 1986  Richard M. Stallman  (rms at prep)
+
+       * dbxread.c (struct header_file): add new field .instance
+       to distinguish the various entries for one header file.
+
+       * dbxread.c (process_one_symbol): Use the `value' of
+       a N_BINCL or N_EXCL as the instance code for the header file.
+
+       * dbxread.c (add_{new,old}_header_file):
+       Accept an instance code as arg and treat it as if it were
+       part of the file name for distinguishing and finding entries.
+
+       * dbxread.c (add_new_header_file, read_type):
+       Turn off the header_file_prev_index feature with #if 0.
+
+       * values.c (unpack_field_as_long, modify_field):
+       Run-time test to distinguish big and little endian machines
+       and do shifting accordingly.
+
+Tue Nov 11 00:31:18 1986  Richard M. Stallman  (rms at prep)
+
+       * version.c: version 1.9.
+
+       * breakpoint.c (delete_command):
+       Don't query if 2nd arg is zero.
+
+       * breakpoint.c (clear_breakpoints):
+       Pass 2nd arg of zero to delete_command.
+
+Sat Nov  8 23:29:19 1986  Richard M. Stallman  (rms at prep)
+
+       * breakpoint.c (delete_command):
+       Ask for confirmation when used with no arg (delete all).
+
+Fri Nov  7 11:23:09 1986  Richard M. Stallman  (rms at prep)
+
+       * infrun.c (start_inferior, wait_for_inferior):
+       Eliminate `stop_in_shell' which was not being maintained right.
+       New variable `running_in_shell' is set to 1 or 0 when the
+       expected SIGTRAPs happen, and is simply examined at other times.
+
+       * infrun.c (wait_for_inferior):
+       If get SIGSEGV with running_in_shell == 1, it is sh
+       allocating memory.  Pass the signal silently to the shell.
+
+       * core.c (exec_file_command):
+       data_{start,end} are adjusted unconditionally when an
+       exec file is opened, so closing counter-adjustment is
+       now unconditional as well.
+
+       * printcmd.c (x_command):
+       Don't erase the expression from the calling args
+       if cllaed noninteractively (used to be clobbering
+       definitions of user-defined commands).
+
+       * source.c (list_command): likewise.
+
+Wed Nov  5 09:41:00 1986  Richard M. Stallman  (rms at prep)
+
+       * Makefile: New variable OBSTACK1 that people can use
+       to make obstack.o a dependency of gdb.
+
+       * breakpoint.c (initialize):
+       Define new aliases "br", "bre" and "brea" for "break".
+
+Sun Nov  2 21:16:06 1986  Richard Mlynarik  (mly at prep)
+
+       * symmisc.c (read_symsegs):
+       Add an extra protection against invalid symbol-file
+
+       * m-vax.h:
+       Set KERNEL_U_ADDR and STACK_END_ADDR non-4.2-specifically
+
+Tue Oct 21 13:34:14 1986  Richard Mlynarik  (mly at prep)
+
+       * breakpoints.c (initialize):
+       Delet reference to non-existent command "tenable" from doc of "enable"
+
+Tue Oct 14 19:58:27 1986  Richard Mlynarik  (mly at prep)
+
+       * printcmd.c (display_command, undisplay_command):
+       * infcmd.c (run_command):
+       Call dont_repeat. 
+
+\f
+Local Variables:
+mode: indented-text
+eval: (auto-fill-mode 1)
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/gdb/Makefile b/gdb/Makefile
new file mode 100644 (file)
index 0000000..c1fd60c
--- /dev/null
@@ -0,0 +1,85 @@
+# -I. for "#include <obstack.h>"
+CFLAGS = -g -I. -Dvfork=fork -DDEBUG
+# NOTE!!! -O  may FAIL TO WORK!  See initialize.h for some weird hacks.
+
+# 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.
+OBSTACK = obstack.o alloca.o -lPW
+OBSTACK1 = obstack.o alloca.o
+
+STARTOBS = main.o firstfile.o
+
+OBS = 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
+
+TSOBS = core.o inflow.o
+
+NTSOBS = standalone.o
+
+ENDOBS = lastfile.o command.o utils.o expread.o expprint.o pinsn.o \
+       environ.o version.o
+
+TSSTART = /lib/crt0.o
+
+NTSSTART = kdb-start.o
+
+gdb : $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) $(OBSTACK1)
+       $(CC) -o gdb $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) -lg $(OBSTACK)
+
+xgdb : $(STARTOBS) $(OBS) xgdb.o $(TSOBS) $(ENDOBS) $(OBSTACK1)
+       $(CC) -o xgdb $(STARTOBS) $(OBS) xgdb.o $(TSOBS) $(ENDOBS) \
+           -lXtk11 -lXrm -lX11 -lg $(OBSTACK)
+
+kdb : $(NTSSTART) $(STARTOBS) $(OBS) $(NTSOBS) $(ENDOBS) $(OBSTACK1)
+       ld -o kdb $(NTSSTART) $(STARTOBS) $(OBS) $(NTSOBS) $(ENDOBS) -lc -lg $(OBSTACK)
+
+clean:
+       rm -f $(STARTOBS) $(OBS) $(TSOBS) $(OBSTACK1) $(NTSSTART) $(NTSOBS)
+       rm -f xgdb.o gdb xgdb kdb tags errs expread.tab.c
+
+blockframe.o : blockframe.c defs.h initialize.h param.h symtab.h frame.h
+breakpoint.o : breakpoint.c defs.h initialize.h param.h symtab.h frame.h
+command.o : command.c command.h
+coffread.o : coffread.c defs.h initialize.h param.h symtab.h
+core.o : core.c defs.h initialize.h param.h
+dbxread.o : dbxread.c defs.h initialize.h param.h symtab.h
+environ.o : environ.c environ.h
+expprint.o : expprint.c defs.h symtab.h expression.h
+expread.tab.c : expread.y
+       @echo 'Expect 96 shift/reduce conflicts.'
+       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
+eval.o : eval.c defs.h initialize.h symtab.h value.h expression.h
+findvar.o : findvar.c defs.h initialize.h param.h symtab.h frame.h value.h
+firstfile.o : firstfile.c initialize.h
+infcmd.o : infcmd.c defs.h initialize.h param.h symtab.h frame.h inferior.h environ.h value.h
+inflow.o : inflow.c defs.h initialize.h param.h frame.h inferior.h
+infrun.o : infrun.c defs.h initialize.h param.h symtab.h frame.h inferior.h wait.h
+kdb-start.o : kdb-start.c defs.h param.h
+lastfile.o : lastfile.c
+main.o : main.c defs.h command.h
+# pinsn.o depends on ALL the opcode printers
+# since we don't know which one is really being used.
+pinsn.o : pinsn.c defs.h param.h symtab.h \
+    vax-opcode.h vax-pinsn.c m68k-opcode.h m68k-pinsn.c
+printcmd.o : printcmd.c defs.h initialize.h param.h symtab.h value.h expression.h
+source.o : source.c defs.h initialize.h symtab.h
+stack.o : stack.c defs.h initialize.h param.h symtab.h frame.h
+standalone.o : standalone.c defs.h initialize.h param.h symtab.h frame.h inferior.h wait.h
+symmisc.o : symmisc.c defs.h initialize.h symtab.h
+symtab.o : symtab.c defs.h initialize.h param.h symtab.h
+utils.o : utils.c defs.h
+valarith.o : valarith.c defs.h initialize.h param.h symtab.h value.h expression.h
+valops.o : valops.c defs.h initialize.h param.h symtab.h value.h
+valprint.o : valprint.c defs.h initialize.h symtab.h value.h
+values.o : values.c defs.h initialize.h param.h symtab.h value.h
+version.o : version.c
+xgdb.o : xgdb.c defs.h initialize.h param.h symtab.h frame.h
+       $(CC) -c $(CFLAGS) xgdb.c -o $@
+
+obstack.o : obstack.c
diff --git a/gdb/RCS/Makefile,v b/gdb/RCS/Makefile,v
new file mode 100644 (file)
index 0000000..d942be0
--- /dev/null
@@ -0,0 +1,160 @@
+head     1.4;
+access   ;
+symbols  RMS-has:1.2;
+locks    ; strict;
+comment  @# @;
+
+
+1.4
+date     88.06.08.23.14.28;  author gnu;  state Exp;
+branches ;
+next     1.3;
+
+1.3
+date     88.02.28.03.38.17;  author gnu;  state Exp;
+branches ;
+next     1.2;
+
+1.2
+date     88.01.26.05.14.43;  author gnu;  state Exp;
+branches ;
+next     1.1;
+
+1.1
+date     88.01.26.05.14.07;  author gnu;  state Exp;
+branches ;
+next     ;
+
+
+desc
+@Original from RMS's wheaties devl dirs
+@
+
+
+1.4
+log
+@Add -DEBUG
+@
+text
+@# -I. for "#include <obstack.h>"
+CFLAGS = -g -I. -Dvfork=fork -DDEBUG
+# NOTE!!! -O  may FAIL TO WORK!  See initialize.h for some weird hacks.
+
+# 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.
+OBSTACK = obstack.o alloca.o -lPW
+OBSTACK1 = obstack.o alloca.o
+
+STARTOBS = main.o firstfile.o
+
+OBS = 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
+
+TSOBS = core.o inflow.o
+
+NTSOBS = standalone.o
+
+ENDOBS = lastfile.o command.o utils.o expread.o expprint.o pinsn.o \
+       environ.o version.o
+
+TSSTART = /lib/crt0.o
+
+NTSSTART = kdb-start.o
+
+gdb : $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) $(OBSTACK1)
+       $(CC) -o gdb $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) -lg $(OBSTACK)
+
+xgdb : $(STARTOBS) $(OBS) xgdb.o $(TSOBS) $(ENDOBS) $(OBSTACK1)
+       $(CC) -o xgdb $(STARTOBS) $(OBS) xgdb.o $(TSOBS) $(ENDOBS) \
+           -lXtk11 -lXrm -lX11 -lg $(OBSTACK)
+
+kdb : $(NTSSTART) $(STARTOBS) $(OBS) $(NTSOBS) $(ENDOBS) $(OBSTACK1)
+       ld -o kdb $(NTSSTART) $(STARTOBS) $(OBS) $(NTSOBS) $(ENDOBS) -lc -lg $(OBSTACK)
+
+clean:
+       rm -f $(STARTOBS) $(OBS) $(TSOBS) $(OBSTACK1) $(NTSSTART) $(NTSOBS)
+       rm -f xgdb.o gdb xgdb kdb tags errs expread.tab.c
+
+blockframe.o : blockframe.c defs.h initialize.h param.h symtab.h frame.h
+breakpoint.o : breakpoint.c defs.h initialize.h param.h symtab.h frame.h
+command.o : command.c command.h
+coffread.o : coffread.c defs.h initialize.h param.h symtab.h
+core.o : core.c defs.h initialize.h param.h
+dbxread.o : dbxread.c defs.h initialize.h param.h symtab.h
+environ.o : environ.c environ.h
+expprint.o : expprint.c defs.h symtab.h expression.h
+expread.tab.c : expread.y
+       @@echo 'Expect 96 shift/reduce conflicts.'
+       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
+eval.o : eval.c defs.h initialize.h symtab.h value.h expression.h
+findvar.o : findvar.c defs.h initialize.h param.h symtab.h frame.h value.h
+firstfile.o : firstfile.c initialize.h
+infcmd.o : infcmd.c defs.h initialize.h param.h symtab.h frame.h inferior.h environ.h value.h
+inflow.o : inflow.c defs.h initialize.h param.h frame.h inferior.h
+infrun.o : infrun.c defs.h initialize.h param.h symtab.h frame.h inferior.h wait.h
+kdb-start.o : kdb-start.c defs.h param.h
+lastfile.o : lastfile.c
+main.o : main.c defs.h command.h
+# pinsn.o depends on ALL the opcode printers
+# since we don't know which one is really being used.
+pinsn.o : pinsn.c defs.h param.h symtab.h \
+    vax-opcode.h vax-pinsn.c m68k-opcode.h m68k-pinsn.c
+printcmd.o : printcmd.c defs.h initialize.h param.h symtab.h value.h expression.h
+source.o : source.c defs.h initialize.h symtab.h
+stack.o : stack.c defs.h initialize.h param.h symtab.h frame.h
+standalone.o : standalone.c defs.h initialize.h param.h symtab.h frame.h inferior.h wait.h
+symmisc.o : symmisc.c defs.h initialize.h symtab.h
+symtab.o : symtab.c defs.h initialize.h param.h symtab.h
+utils.o : utils.c defs.h
+valarith.o : valarith.c defs.h initialize.h param.h symtab.h value.h expression.h
+valops.o : valops.c defs.h initialize.h param.h symtab.h value.h
+valprint.o : valprint.c defs.h initialize.h symtab.h value.h
+values.o : values.c defs.h initialize.h param.h symtab.h value.h
+version.o : version.c
+xgdb.o : xgdb.c defs.h initialize.h param.h symtab.h frame.h
+       $(CC) -c $(CFLAGS) xgdb.c -o $@@
+
+obstack.o : obstack.c
+@
+
+
+1.3
+log
+@Make clean
+@
+text
+@d2 1
+a2 1
+CFLAGS = -g -I. -Dvfork=fork
+@
+
+
+1.2
+log
+@We don't have vfork or alloca, and regexp routines are in libPW.a for
+no good reason.
+@
+text
+@d38 4
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d2 1
+a2 1
+CFLAGS = -g -I.
+d8 2
+a9 2
+OBSTACK = obstack.o
+OBSTACK1 = obstack.o
+@
diff --git a/gdb/RCS/coffread.c,v b/gdb/RCS/coffread.c,v
new file mode 100644 (file)
index 0000000..7542030
--- /dev/null
@@ -0,0 +1,304 @@
+head     1.4;
+access   ;
+symbols  RMS-has:1.2;
+locks    ; strict;
+comment  @ * @;
+
+
+1.4
+date     88.06.08.23.13.40;  author gnu;  state Exp;
+branches ;
+next     1.3;
+
+1.3
+date     88.02.28.03.37.53;  author gnu;  state Exp;
+branches ;
+next     1.2;
+
+1.2
+date     88.01.26.05.02.32;  author gnu;  state Exp;
+branches ;
+next     1.1;
+
+1.1
+date     88.01.26.00.38.04;  author gnu;  state Exp;
+branches ;
+next     ;
+
+
+desc
+@Original from RMS's work dirs on Wheaties
+@
+
+
+1.4
+log
+@Half reasonable reading of coff files.  Problem was that it assumed
+that a .text would show up sometime, and it never did.  We have to close
+out each source file's symtab as we hit the next one.
+@
+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 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!
+*/
+\f
+#include "defs.h"
+#include "param.h"
+#ifdef COFF_FORMAT
+#include "initialize.h"
+#include "symtab.h"
+
+#include <a.out.h>
+#include <stdio.h>
+#include <obstack.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+
+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 ();
+
+START_FILE
+
+/* 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;
+
+int debug = 1;
+
+\f
+/* 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)
+    {
+      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];
+}
+
+/* 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;
+}
+\f
+/* 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 *) xmalloc (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
\ No newline at end of file
diff --git a/gdb/RCS/core.c,v b/gdb/RCS/core.c,v
new file mode 100644 (file)
index 0000000..99547f8
--- /dev/null
@@ -0,0 +1,763 @@
+head     1.2;
+access   ;
+symbols  RMS-has:1.2;
+locks    ; strict;
+comment  @ * @;
+
+
+1.2
+date     88.01.26.05.04.52;  author gnu;  state Exp;
+branches ;
+next     1.1;
+
+1.1
+date     88.01.21.05.04.03;  author gnu;  state Exp;
+branches ;
+next     ;
+
+
+desc
+@From RMS's development version on wheaties, 20Jan88
+@
+
+
+1.2
+log
+@Hacks to get it to compile on a/ux.  Needs work at finding the registers
+in a core file.
+@
+text
+@/* Work with core dump and executable files, 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 "initialize.h"
+#include "defs.h"
+#include "param.h"
+
+#include <a.out.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+
+/* Recognize COFF format systems because a.out.h defines AOUTHDR.  */
+#ifdef AOUTHDR
+#define COFF_FORMAT
+#endif
+
+#ifdef NEW_SUN_CORE
+#include <sys/core.h>
+#else /* not NEW_SUN_CORE */
+#ifdef UMAX_CORE
+#include <sys/ptrace.h>
+#else /* not UMAX_CORE */
+#ifdef mac_aux
+#include <sys/seg.h>
+#include <sys/mmu.h>
+#include <sys/signal.h>
+#include <sys/time.h>
+#include <sys/user.h>
+#else
+#include <sys/user.h>
+#endif /* mac_aux */
+#endif /* UMAX_CORE */
+#endif /* NEW_SUN_CORE */
+
+#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
+
+START_FILE
+
+/* Hook for `exec_file_command' command to call.  */
+
+void (*exec_file_display_hook) ();
+   
+/* File names of core file and executable file.  */
+
+static char *corefile;
+static 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.  */
+
+static int corechan;
+static 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.  */
+
+static CORE_ADDR data_start;
+static CORE_ADDR data_end;
+static CORE_ADDR stack_start;
+static 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.  */
+
+static CORE_ADDR text_start;
+static CORE_ADDR text_end;
+static CORE_ADDR exec_data_start;
+static CORE_ADDR exec_data_end;
+
+/* Address in executable file of start of text area data.  */
+
+static int text_offset;
+
+/* Address in executable file of start of data area data.  */
+
+static int exec_data_offset;
+
+/* Address in core file of start of data area data.  */
+
+static int data_offset;
+
+/* Address in core file of start of stack area data.  */
+
+static int stack_offset;
+  
+#ifdef COFF_FORMAT
+/* various coff data structures */
+
+static FILHDR file_hdr;
+static SCNHDR text_hdr;
+static SCNHDR data_hdr;
+
+#endif /* not COFF_FORMAT */
+
+/* a.out header saved in core file.  */
+  
+static AOUTHDR core_aouthdr;
+
+/* a.out header of exec file.  */
+
+static AOUTHDR exec_aouthdr;
+
+static void validate_files ();
+unsigned int register_addr ();
+\f
+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);
+#ifdef NEW_SUN_CORE
+      {
+       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));
+
+       data_start = exec_data_start;
+       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;
+
+       bcopy (&corestr.c_regs, registers, 16 * 4);
+       *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps;
+       *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc;
+       bcopy (corestr.c_fpstatus.fps_regs,
+              &registers[REGISTER_BYTE (FP0_REGNUM)],
+              sizeof corestr.c_fpstatus.fps_regs);
+       bcopy (&corestr.c_fpstatus.fps_control,
+              &registers[REGISTER_BYTE (FPC_REGNUM)],
+              sizeof corestr.c_fpstatus - sizeof corestr.c_fpstatus.fps_regs);
+
+       bcopy (&corestr.c_aouthdr, &core_aouthdr, sizeof (struct exec));
+
+       printf ("Core file is from \"%s\".\n", corestr.c_cmdname);
+      }
+#else /* not NEW_SUN_CORE */
+      /* 4.2-style (and perhaps also sysV-style) core dump file.  */
+      {
+#ifdef UMAX_CORE
+       struct ptrace_user u;
+#else
+       struct user u;
+#endif
+       int reg_offset;
+
+       val = myread (corechan, &u, sizeof u);
+       if (val < 0)
+         perror_with_name (filename);
+       data_start = exec_data_start;
+
+#ifdef UMAX_CORE
+       data_end = data_start + u.pt_dsize;
+       stack_start = stack_end - u.pt_ssize;
+       data_offset = sizeof u;
+       stack_offset = data_offset + u.pt_dsize;
+       reg_offset = 0;
+
+       bcopy (&u.pt_aouthdr, &core_aouthdr, sizeof (AOUTHDR));
+
+#else /* not UMAX_CORE */
+#ifdef mac_aux
+       /* This may well not work for 0407 (nonshared text) a.out's */
+       data_end = data_start + u.u_dsize << PAGESHIFT;
+       stack_start = stack_end - u.u_ssize << PAGESHIFT;
+       data_offset = USIZE;
+       stack_offset = USIZE + u.u_dsize << PAGESHIFT;
+       reg_offset = (int) &u.u_ar0[0] - (int) &u;
+
+       core_aouthdr.a_magic = u.u_exdata.ux_mag;
+#else
+       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.  */
+       core_aouthdr.a_magic = 0;
+#endif /* not mac_aux */
+#endif /* not UMAX_CORE */
+
+       /* 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);
+           }
+       }
+      }
+#endif /* not NEW_SUN_CORE */
+      if (filename[0] == '/')
+       corefile = savestring (filename, strlen (filename));
+      else
+       {
+         char dirname[MAXPATHLEN];
+
+         getwd (dirname);
+         corefile = concat (dirname, "/", filename);
+       }
+
+      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");
+}
+\f
+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);
+
+#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_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;
+
+       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 ? filename : "No executable specified.\n");
+}
+
+/* Call this to specify the hook for exec_file_command to call back.
+   This is called from the x-window display code.  */
+
+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.  */
+
+close_exec_file ()
+{
+  if (execchan >= 0)
+    close (execchan);
+  execchan = -1;
+}
+
+reopen_exec_file ()
+{
+  if (execchan < 0 && execfile != 0)
+    {
+      char *filename = concat (execfile, "", "");
+      exec_file_command (filename, 0);
+      free (filename);
+    }
+}
+\f
+/* 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.  */
+
+static void
+validate_files ()
+{
+  if (execfile != 0 && corefile != 0)
+    {
+      struct stat st_core;
+
+      fstat (corechan, &st_core);
+
+      if (core_aouthdr.a_magic != 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");
+    }
+}
+
+char *
+get_exec_file ()
+{
+  if (execfile == 0)
+    error ("No executable file specified.\n\
+Use the \"exec-file\" and \"symbol-file\" commands.");
+  return execfile;
+}
+
+int
+have_core_file_p ()
+{
+  return corefile != 0;
+}
+
+static void
+files_info ()
+{
+  char *symfile;
+  extern char *get_sym_file ();
+
+  if (execfile)
+    printf ("Executable file \"%s\".\n", execfile);
+  else
+    printf ("No executable file\n");
+  if (corefile == 0)
+    printf ("No core dump file\n");
+  else
+    printf ("Core dump file \"%s\".\n", corefile);
+
+  if (have_inferior_p ())
+    printf ("Using the running image of the program, rather than these files.\n");
+
+  symfile = get_sym_file ();
+  if (symfile != 0)
+    printf ("Symbols loaded from \"%s\".\n", symfile);
+
+  if (! have_inferior_p ())
+    {
+      if (execfile)
+       {
+         printf ("Text segment from 0x%x to 0x%x.\n",
+                 text_start, text_end);
+       }
+      if (corefile)
+       {
+         printf ("Data segment from 0x%x to 0x%x.\nStack segment from 0x%x to 0x%x.\n",
+                 data_start, data_end, stack_start, stack_end);
+       }
+      else
+       {
+         printf ("Data segment in executable from 0x%x to 0x%x.\n",
+                 exec_data_start, exec_data_end);
+       }
+    }
+}
+\f
+/* Read "memory data" from core file and/or executable file */
+
+read_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  if (have_inferior_p ())
+    read_inferior_memory (memaddr, myaddr, len);
+  else
+    xfer_core_file (memaddr, myaddr, len, 0);
+}
+
+/* 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.");
+}
+
+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;
+
+  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.  */
+
+      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);
+       }
+      /* Note that if there is no core file
+        data_start and data_end are equal.  */
+      else 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;
+       }
+
+      /* 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);
+
+      memaddr += i;
+      myaddr += i;
+      len -= i;
+    }
+}
+\f
+/* My replacement for the read system call.
+   Used like `read' but keeps going if `read' returns too soon.  */
+
+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;
+    }
+}
+\f
+#ifndef NEW_SUN_CORE
+
+/* 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);
+
+#ifdef mac_aux
+/* FIXME, we don't know where the regs are.  Maybe the test command
+ * that tests what parts of the upage are writeable will find 'em for us.
+ */
+#define REGISTER_U_ADDR(addr, foo, bar)  addr = 0;
+#endif
+  REGISTER_U_ADDR (addr, blockend, regno);
+
+  return addr;
+}
+
+#endif /* not NEW_SUN_CORE */
+\f
+static
+initialize ()
+{
+  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.");
+}
+
+END_FILE
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d27 1
+d44 5
+d50 4
+a53 1
+#endif
+d240 10
+d259 1
+d675 6
+@
diff --git a/gdb/RCS/infcmd.c,v b/gdb/RCS/infcmd.c,v
new file mode 100644 (file)
index 0000000..cc30fe4
--- /dev/null
@@ -0,0 +1,966 @@
+head     1.2;
+access   ;
+symbols  RMS-has:1.2;
+locks    ; strict;
+comment  @ * @;
+
+
+1.2
+date     88.01.26.05.06.19;  author gnu;  state Exp;
+branches ;
+next     1.1;
+
+1.1
+date     88.01.26.01.19.05;  author gnu;  state Exp;
+branches ;
+next     ;
+
+
+desc
+@Original from RMS's wheaties devl sources
+@
+
+
+1.2
+log
+@Add local sys_siglist for a/ux because they don't provide one, sigh.
+@
+text
+@/* Memory-access and commands for inferior process, 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 "defs.h"
+#include "initialize.h"
+#include "symtab.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "environ.h"
+#include "value.h"
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/param.h>
+
+#ifdef mac_aux
+/* Warning!  This table is positional and highly dependent on the local
+   system.  Check it closely against <sys/signal.h> when porting. */
+char *sys_siglist[] = {
+       "Signal 0",
+       "Hangup",
+       "Interrupt",
+       "Quit",
+       "Invalid instruction",
+       "Trace/breakpoint trap",
+       "IOT trap",
+       "EMT trap",
+       "Floating point exception",
+       "Killed",
+       "Bus error",
+       "Segmentation fault",
+       "Bad system call",
+       "Broken pipe",
+       "Alarm clock",
+       "Terminated",
+       "User signal 1",
+       "User signal 2",
+       "Child exited",
+       "Power-fail restart",
+       "Stopped",
+       "Stopped (tty input)",
+       "Stopped (tty output)",
+       "Stopped (signal)",
+       "Cputime limit exceeded",
+       "File size limit exceeded",
+       "Virtual timer expired",
+       "Profiling timer expired",
+       "Window changed",
+       "Continued",
+       "Urgent I/O condition",
+       "I/O possible",
+};
+#else
+/* More portable systems do it for you */
+extern char *sys_siglist[];
+#endif
+
+#define ERROR_NO_INFERIOR \
+   if (inferior_pid == 0) error ("The program is not being run.");
+
+/* String containing arguments to give to the program,
+   with a space added at the front.  Just a space means no args.  */
+
+static char *inferior_args;
+
+/* File name for default use for standard in/out in the inferior.  */
+
+char *inferior_io_terminal;
+
+/* Pid of our debugged inferior, or 0 if no inferior now.  */
+
+int inferior_pid;
+
+/* Last signal that the inferior received (why it stopped).  */
+
+int stop_signal;
+
+/* Address at which inferior stopped.  */
+
+CORE_ADDR stop_pc;
+
+/* Stack frame when program stopped.  */
+
+FRAME stop_frame;
+
+/* Number of breakpoint it stopped at, or 0 if none.  */
+
+int stop_breakpoint;
+
+/* Nonzero if stopped due to a step command.  */
+
+int stop_step;
+
+/* Nonzero if stopped due to completion of a stack dummy routine.  */
+
+int stop_stack_dummy;
+
+/* Range to single step within.
+   If this is nonzero, respond to a single-step signal
+   by continuing to step if the pc is in this range.  */
+
+CORE_ADDR step_range_start; /* Inclusive */
+CORE_ADDR step_range_end; /* Exclusive */
+
+/* Stack frame address as of when stepping command was issued.
+   This is how we know when we step into a subroutine call,
+   and how to set the frame for the breakpoint used to step out.  */
+
+CORE_ADDR step_frame;
+
+/* 1 means step over all subroutine calls.
+   -1 means step over calls to undebuggable functions.  */
+
+int step_over_calls;
+
+/* If stepping, nonzero means step count is > 1
+   so don't print frame next time inferior stops
+   if it stops due to stepping.  */
+
+int step_multi;
+
+/* Environment to use for running inferior,
+   in format described in environ.h.  */
+
+struct environ *inferior_environ;
+
+CORE_ADDR read_pc ();
+struct command_line *get_breakpoint_commands ();
+
+START_FILE
+\f
+int
+have_inferior_p ()
+{
+  return inferior_pid != 0;
+}
+
+static void 
+set_args_command (args)
+     char *args;
+{
+  free (inferior_args);
+  if (!args) args = "";
+  inferior_args = concat (" ", args, "");
+}
+  
+void
+tty_command (file)
+     char *file;
+{
+  if (file == 0)
+    error_no_arg ("terminal name for running target process");
+
+  inferior_io_terminal = savestring (file, strlen (file));
+}
+
+static void
+run_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  extern char **environ;
+  register int i;
+  char *exec_file;
+  char *allargs;
+
+  extern int sys_nerr;
+  extern char *sys_errlist[];
+  extern int errno;
+
+  dont_repeat ();
+
+  if (inferior_pid)
+    {
+      if (query ("The program being debugged has been started already.\n\
+Start it from the beginning? "))
+       kill_inferior ();
+      else
+       error ("Program already started.");
+    }
+
+  if (args)
+    set_args_command (args);
+
+  exec_file = (char *) get_exec_file ();
+  if (from_tty)
+    {
+      printf ("Starting program: %s%s\n",
+             exec_file, inferior_args);
+      fflush (stdout);
+    }
+
+  allargs = concat ("exec ", exec_file, inferior_args);
+  inferior_pid = create_inferior (allargs, environ_vector (inferior_environ));
+
+  clear_proceed_status ();
+
+  start_inferior ();
+}
+\f
+void
+cont_command (proc_count_exp, from_tty)
+     char *proc_count_exp;
+     int from_tty;
+{
+  ERROR_NO_INFERIOR;
+
+  clear_proceed_status ();
+
+  /* If have argument, set proceed count of breakpoint we stopped at.  */
+
+  if (stop_breakpoint && proc_count_exp)
+    {
+      set_ignore_count (stop_breakpoint,
+                       parse_and_eval_address (proc_count_exp) - 1,
+                       from_tty);
+      if (from_tty)
+       printf ("  ");
+    }
+
+  if (from_tty)
+    printf ("Continuing.\n");
+
+  proceed (-1, -1, 0);
+}
+\f
+/* Step until outside of current statement.  */
+static void step_1 ();
+
+static void
+step_command (count_string)
+{
+  step_1 (0, 0, count_string);
+}
+
+/* Likewise, but skip over subroutine calls as if single instructions.  */
+
+static void
+next_command (count_string)
+{
+  step_1 (1, 0, count_string);
+}
+
+/* Likewise, but step only one instruction.  */
+
+static void
+stepi_command (count_string)
+{
+  step_1 (0, 1, count_string);
+}
+
+static void
+nexti_command (count_string)
+{
+  step_1 (1, 1, count_string);
+}
+
+static void
+step_1 (skip_subroutines, single_inst, count_string)
+     int skip_subroutines;
+     int single_inst;
+     char *count_string;
+{
+  register int count = 1;
+
+  ERROR_NO_INFERIOR;
+  count = count_string ? parse_and_eval_address (count_string) : 1;
+
+  for (; count > 0; count--)
+    {
+      clear_proceed_status ();
+
+      step_frame = get_current_frame ();
+
+      if (! single_inst)
+       {
+         find_pc_line_pc_range (stop_pc, &step_range_start, &step_range_end);
+         if (step_range_end == 0)
+           {
+             terminal_ours ();
+             error ("Current function has no line number information.");
+           }
+       }
+      else
+       {
+         /* Say we are stepping, but stop after one insn whatever it does.
+            Don't step through subroutine calls even to undebuggable functions.  */
+         step_range_start = step_range_end = 1;
+         if (!skip_subroutines)
+           step_over_calls = 0;
+       }
+
+      if (skip_subroutines)
+       step_over_calls = 1;
+
+      step_multi = (count > 1);
+      proceed (-1, -1, 1);
+      if (! stop_step)
+       break;
+    }
+}
+\f
+/* Continue program at specified address.  */
+
+static void
+jump_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  register CORE_ADDR addr;
+  struct symtab_and_line sal;
+
+  ERROR_NO_INFERIOR;
+
+  if (!arg)
+    error_no_arg ("starting address");
+
+  sal = decode_line_spec (arg, 1);
+
+  if (sal.symtab == 0 && sal.pc == 0)
+    error ("No source file has been specified.");
+
+  if (sal.pc == 0)
+    sal.pc = find_line_pc (sal.symtab, sal.line);
+
+  {
+    struct symbol *fn = get_frame_function (get_current_frame ());
+    struct symbol *sfn = find_pc_function (sal.pc);
+    if (fn != 0 && sfn != fn
+       && ! query ("That is not in function %s.  Continue there? ",
+                   sal.line, SYMBOL_NAME (fn)))
+      error ("Not confirmed.");
+  }
+
+  if (sal.pc == 0)
+    error ("No line %d in file \"%s\".", sal.line, sal.symtab->filename);
+
+  addr = sal.pc;
+
+  clear_proceed_status ();
+
+  if (from_tty)
+    printf ("Continuing at 0x%x.\n", addr);
+
+  proceed (addr, 0, 0);
+}
+
+/* Continue program giving it specified signal.  */
+
+static void
+signal_command (signum_exp, from_tty)
+     char *signum_exp;
+     int from_tty;
+{
+  register int signum;
+
+  dont_repeat ();              /* Too dangerous.  */
+  ERROR_NO_INFERIOR;
+
+  if (!signum_exp)
+    error_no_arg ("signal number");
+
+  signum = parse_and_eval_address (signum_exp);
+
+  clear_proceed_status ();
+
+  if (from_tty)
+    printf ("Continuing with signal %d.\n", signum);
+
+  proceed (stop_pc, signum, 0);
+}
+
+/* Execute a "stack dummy", a piece of code stored in the stack
+   by the debugger to be executed in the inferior.
+
+   To call: first, do PUSH_DUMMY_FRAME.
+   Then push the contents of the dummy.  It should end with a breakpoint insn.
+   Then call here, passing address at which to start the dummy.
+
+   The contents of all registers are saved before the dummy frame is popped
+   and copied into the buffer BUFFER.
+
+   The dummy's frame is automatically popped whenever that break is hit.
+   If that is the first time the program stops, run_stack_dummy
+   returns to its caller with that frame already gone.
+   Otherwise, the caller never gets returned to.  */
+
+/* 4 => return instead of letting the stack dummy run.  */
+
+static int stack_dummy_testing = 0;
+
+void
+run_stack_dummy (addr, buffer)
+     CORE_ADDR addr;
+     REGISTER_TYPE *buffer;
+{
+  int saved_pc_changed = pc_changed;
+  int saved_stop_signal = stop_signal;
+  int saved_stop_pc = stop_pc;
+  int saved_stop_frame = stop_frame;
+  int saved_stop_breakpoint = stop_breakpoint;
+  int saved_stop_step = stop_step;
+  int saved_stop_stack_dummy = stop_stack_dummy;
+  FRAME saved_selected_frame;
+  int saved_selected_level;
+  struct command_line *saved_breakpoint_commands
+    = get_breakpoint_commands ();
+
+  record_selected_frame (&saved_selected_frame, &saved_selected_level);
+
+  /* Now proceed, having reached the desired place.  */
+  clear_proceed_status ();
+  if (stack_dummy_testing & 4)
+    {
+      POP_FRAME;
+      return;
+    }
+  proceed (addr, 0, 0);
+
+  if (!stop_stack_dummy)
+    error ("Cannot continue previously requested operation.");
+
+  set_breakpoint_commands (saved_breakpoint_commands);
+  select_frame (saved_selected_frame, saved_selected_level);
+  stop_signal = saved_stop_signal;
+  stop_pc = saved_stop_pc;
+  stop_frame = saved_stop_frame;
+  stop_breakpoint = saved_stop_breakpoint;
+  stop_step = saved_stop_step;
+  stop_stack_dummy = saved_stop_stack_dummy;
+  pc_changed = saved_pc_changed;
+
+  /* On return, the stack dummy has been popped already.  */
+
+  bcopy (stop_registers, buffer, sizeof stop_registers);
+}
+\f
+/* "finish": Set a temporary breakpoint at the place
+   the selected frame will return to, then continue.  */
+
+static void
+finish_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  struct symtab_and_line sal;
+  register FRAME frame;
+  struct frame_info fi;
+
+  register struct symbol *function;
+
+  if (!have_inferior_p ())
+    error ("The program is not being run.");
+  if (arg)
+    error ("The \"finish\" command does not take any arguments.");
+
+  frame = get_prev_frame (selected_frame);
+  if (frame == 0)
+    error ("\"finish\" not meaningful in the outermost frame.");
+
+  clear_proceed_status ();
+
+  fi = get_frame_info (frame);
+  sal = find_pc_line (fi.pc, 0);
+  sal.pc = fi.pc;
+  set_momentary_breakpoint (sal, frame);
+
+  /* Find the function we will return from.  */
+
+  fi = get_frame_info (fi.next_frame);
+  function = find_pc_function (fi.pc);
+
+  if (from_tty)
+    {
+      printf ("Run till exit from ");
+      print_selected_frame ();
+    }
+
+  proceed (-1, -1, 0);
+
+  if (stop_breakpoint == -3 && function != 0)
+    {
+      struct type *value_type;
+      register value val;
+
+      if (TYPE_CODE (SYMBOL_TYPE (function)) != TYPE_CODE_VOID)
+       value_type = SYMBOL_TYPE (function);
+      else
+       return;
+
+      val = value_being_returned (value_type, stop_registers);
+      printf ("Value returned is $%d = ", record_latest_value (val));
+      value_print (val, stdout);
+      putchar ('\n');
+    }
+}
+\f
+static void
+program_info ()
+{
+  if (inferior_pid == 0)
+    {
+      printf ("The program being debugged is not being run.\n");
+      return;
+    }
+
+  printf ("Program being debugged is in process %d, stopped at 0x%x.\n",
+         inferior_pid, stop_pc);
+  if (stop_step)
+    printf ("It stopped after being stepped.\n");
+  else if (stop_breakpoint)
+    printf ("It stopped at breakpoint %d.\n", stop_breakpoint);
+  else if (stop_signal)
+    printf ("It stopped with signal %d (%s).\n",
+           stop_signal, sys_siglist[stop_signal]);
+
+  printf ("\nType \"info stack\" or \"info reg\" for more information.\n");
+}
+\f
+static void
+environment_info (var)
+     char *var;
+{
+  if (var)
+    {
+      register char *val = get_in_environ (inferior_environ, var);
+      if (val)
+       printf ("%s = %s\n", var, val);
+      else
+       printf ("Environment variable \"%s\" not defined.\n", var);
+    }
+  else
+    {
+      register char **vector = environ_vector (inferior_environ);
+      while (*vector)
+       printf ("%s\n", *vector++);
+    }
+}
+
+static void
+set_environment_command (arg)
+     char *arg;
+{
+  register char *p, *val, *var;
+
+  if (arg == 0)
+    error_no_arg ("environment variable and value");
+
+  p = (char *) index (arg, '=');
+  val = (char *) index (arg, ' ');
+  if (p != 0 && val != 0)
+    p = arg + min (p - arg, val - arg);
+  else if (val != 0 && p == 0)
+    p = val;
+
+  if (p == 0)
+    error ("Space or \"=\" must separate variable name and its value");
+  if (p[1] == 0)
+    error_no_arg ("value for the variable");
+  if (p == arg)
+    error_no_arg ("environment variable to set");
+
+  val = p + 1;
+  while (*val == ' ' || *val == '\t') val++;
+  while (p != arg && (p[-1] == ' ' || p[-1] == '\t')) p--;
+
+  var = savestring (arg, p - arg);
+  set_in_environ (inferior_environ, var, val);
+  free (var);
+}
+
+static void
+unset_environment_command (var)
+     char *var;
+{
+  if (var == 0)
+    error_no_arg ("environment variable");
+
+  unset_in_environ (inferior_environ, var);
+}
+\f
+/* Read an integer from debugged memory, given address and number of bytes.  */
+
+read_memory_integer (memaddr, len)
+     CORE_ADDR memaddr;
+     int len;
+{
+  char cbuf;
+  short sbuf;
+  int ibuf;
+  long lbuf;
+
+  if (len == sizeof (char))
+    {
+      read_memory (memaddr, &cbuf, len);
+      return cbuf;
+    }
+  if (len == sizeof (short))
+    {
+      read_memory (memaddr, &sbuf, len);
+      return sbuf;
+    }
+  if (len == sizeof (int))
+    {
+      read_memory (memaddr, &ibuf, len);
+      return ibuf;
+    }
+  if (len == sizeof (lbuf))
+    {
+      read_memory (memaddr, &lbuf, len);
+      return lbuf;
+    }
+  error ("Cannot handle integers of %d bytes.", len);
+}
+\f
+CORE_ADDR
+read_pc ()
+{
+  return (CORE_ADDR) read_register (PC_REGNUM);
+}
+
+write_pc (val)
+     CORE_ADDR val;
+{
+  write_register (PC_REGNUM, (long) val);
+}
+
+char *reg_names[] = REGISTER_NAMES;
+
+static void
+registers_info (addr_exp)
+     char *addr_exp;
+{
+  register int i;
+  int regnum;
+
+  if (addr_exp)
+    {
+      if (*addr_exp >= '0' && *addr_exp <= '9')
+       regnum = atoi (addr_exp);
+      else
+       {
+         register char *p = addr_exp;
+         if (p[0] == '$')
+           p++;
+         for (regnum = 0; regnum < NUM_REGS; regnum++)
+           if (!strcmp (p, reg_names[regnum]))
+             break;
+         if (regnum == NUM_REGS)
+           error ("%s: invalid register name.", addr_exp);
+       }
+    }
+  else
+    printf ("Reg\tContents\n\n");
+
+  for (i = 0; i < NUM_REGS; i++)
+    {
+      unsigned char raw_buffer[MAX_REGISTER_RAW_SIZE];
+      unsigned char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+      REGISTER_TYPE val;
+
+      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);
+         read_line ();
+       }
+
+      /* 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]);
+
+      /* 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);
+      /* 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");
+         for (j = 0; j < REGISTER_VIRTUAL_SIZE (i); j++)
+           printf ("%02x", virtual_buffer[j]);
+       }
+      /* Else print as integer in hex and in decimal.  */
+      else
+       {
+         long val;
+
+         bcopy (virtual_buffer, &val, sizeof (long));
+         if (val == 0)
+           printf ("0");
+         else
+           printf ("0x%08x  %d", val, val);
+       }
+
+      /* If register has different raw and virtual formats,
+        print the raw format in hex now.  */
+
+      if (REGISTER_CONVERTIBLE (i))
+       {
+         register int j;
+
+         printf ("  (raw 0x");
+         for (j = 0; j < REGISTER_RAW_SIZE (i); j++)
+           printf ("%02x", raw_buffer[j]);
+         printf (")");
+       }
+      printf ("\n");
+    }
+
+  printf ("Contents are relative to selected stack frame.\n");
+}
+\f
+#ifdef ATTACH_DETACH
+/*
+ * TODO:
+ * Should save/restore the tty state since it might be that the
+ * program to be debugged was started on this tty and it wants
+ * 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.
+ */
+
+/*
+ * attach_command --
+ * takes a program started up outside of gdb and ``attaches'' to it.
+ * This stops it cold in it's tracks and allows us to start tracing
+ * it.  For this to work, we must be able to send the process a
+ * signal and we must have the same effective uid as the program.
+ */
+static void
+attach_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  char *exec_file;
+  int pid;
+
+  dont_repeat();
+
+  if (!args)
+    error_no_arg ("process-id to attach");
+  else
+    pid = atoi (args);
+
+  if (inferior_pid)
+    {
+      if (query ("A program is being debugged already.  Kill it? "))
+       kill_inferior ();
+      else
+       error ("Inferior not killed.");
+    }
+
+  exec_file = (char *) get_exec_file ();
+
+  if (from_tty)
+    {
+      printf ("Attaching program: %s pid %d\n",
+             exec_file, pid);
+      fflush (stdout);
+    }
+
+  attach_program (pid);
+}
+
+/*
+ * detach_command --
+ * takes a program previously attached to and detaches it.
+ * The program resumes execution and will no longer stop
+ * on signals, etc.  We better not have left any breakpoints
+ * in the program or it'll die when it hits one.  For this
+ * to work, it may be necessary for the process to have been
+ * previously attached.  It *might* work if the program was
+ * started via the normal ptrace (PTRACE_TRACEME).
+ */
+
+static void
+detach_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  char *exec_file = (char *)get_exec_file ();
+  int signal = 0;
+
+  if (!inferior_pid)
+    error ("Not currently tracing a program\n");
+  if (from_tty)
+    {
+      printf ("Detaching program: %s pid %d\n",
+             exec_file, inferior_pid);
+      fflush (stdout);
+    }
+  if (args)
+    signal = atoi (args);
+
+  detach (signal);
+  inferior_pid = 0;
+}
+#endif /* ATTACH_DETACH */
+\f
+static
+initialize ()
+{
+  add_com ("tty", class_run, tty_command,
+          "Set terminal for future runs of program being debugged.");
+
+  add_com ("set-args", class_run, set_args_command,
+          "Specify arguments to give program being debugged when it is started.\n\
+Follow this command with any number of args, to be passed to the program.");
+
+  add_info ("environment", environment_info,
+           "The environment to give the program, or one variable's value.\n\
+With an argument VAR, prints the value of environment variable VAR to\n\
+give the program being debugged.  With no arguments, prints the entire\n\
+environment to be given to the program.");
+
+  add_com ("unset-environment", class_run, unset_environment_command,
+          "Cancel environment variable VAR for the program.\n\
+This does not affect the program until the next \"run\" command.");
+  add_com ("set-environment", class_run, set_environment_command,
+          "Set environment variable value to give the program.\n\
+Arguments are VAR VALUE where VAR is variable name and VALUE is value.\n\
+VALUES of environment variables are uninterpreted strings.\n\
+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\
+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.");
+  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.");
+
+  add_com ("stepi", class_run, stepi_command,
+          "Step one instruction exactly.\n\
+Argument N means do this N times (or till program stops for another reason).");
+  add_com_alias ("si", "stepi", class_alias, 0);
+
+  add_com ("nexti", class_run, nexti_command,
+          "Step one instruction, but proceed through subroutine calls.\n\
+Argument N means do this N times (or till program stops for another reason).");
+  add_com_alias ("ni", "nexti", class_alias, 0);
+
+  add_com ("finish", class_run, finish_command,
+          "Execute until selected stack frame returns.\n\
+Upon return, the value returned is printed and put in the value history.");
+
+  add_com ("next", class_run, next_command,
+          "Step program, proceeding through subroutine calls.\n\
+Like the \"step\" command as long as subroutine calls do not happen;\n\
+when they do, the call is treated as one instruction.\n\
+Argument N means do this N times (or till program stops for another reason).");
+  add_com_alias ("n", "next", class_run, 1);
+
+  add_com ("step", class_run, step_command,
+          "Step program until it reaches a different source line.\n\
+Argument N means do this N times (or till program stops for another reason).");
+  add_com_alias ("s", "step", class_run, 1);
+
+  add_com ("jump", class_run, jump_command,
+          "Continue program being debugged at specified line or address.\n\
+Give as argument either LINENUM or *ADDR, where ADDR is an expression\n\
+for an address to start at.");
+
+  add_com ("cont", class_run, cont_command,
+          "Continue program being debugged, after signal or breakpoint.\n\
+If proceeding from breakpoint, a number N may be used as an argument:\n\
+then the same breakpoint won't break until the Nth time it is reached.");
+  add_com_alias ("c", "cont", class_run, 1);
+
+  add_com ("run", class_run, run_command,
+          "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\
+To cancel previous arguments and run with no arguments,\n\
+use \"set-args\" without arguments.");
+  add_com_alias ("r", "run", class_run, 1);
+
+  add_info ("registers", registers_info,
+           "List of registers and their contents, for selected stack frame.\n\
+Register name as argument means describe only that register.");
+
+  add_info ("program", program_info,
+           "Execution status of the program.");
+
+  inferior_args = savestring (" ", 1); /* By default, no args.  */
+  inferior_environ = make_environ ();
+  init_environ (inferior_environ);
+}
+
+END_FILE
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d34 39
+d74 1
+@
diff --git a/gdb/RCS/inflow.c,v b/gdb/RCS/inflow.c,v
new file mode 100644 (file)
index 0000000..83f44d9
--- /dev/null
@@ -0,0 +1,731 @@
+head     1.2;
+access   ;
+symbols  RMS-has:1.2;
+locks    ; strict;
+comment  @ * @;
+
+
+1.2
+date     88.01.26.05.07.38;  author gnu;  state Exp;
+branches ;
+next     1.1;
+
+1.1
+date     88.01.21.05.04.57;  author gnu;  state Exp;
+branches ;
+next     ;
+
+
+desc
+@From RMS's development sources on wheaties, 20Jan88
+@
+
+
+1.2
+log
+@Major Sys V tty changes, and a few changes to try to find the registers
+in the upage (untested yet).
+@
+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 "initialize.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include <fcntl.h>
+
+#ifdef mac_aux
+#include <sys/seg.h>
+#include <sys/mmu.h>
+#include <sys/signal.h>
+#include <sys/time.h>
+#include <sys/user.h>
+#else
+#include <sys/user.h>
+#endif /* mac_aux */
+
+
+#ifdef UMAX_PTRACE
+#include <a.out.h>
+#endif
+
+#ifdef NEW_SUN_PTRACE
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+#endif
+
+#ifdef SYSV_TTYS
+#include <termio.h>
+#endif
+
+extern int errno;
+
+/* Nonzero if we are debugging an attached outside process
+   rather than an inferior.  */
+
+static int attach_flag;
+
+#define        UPAGE_MASK      0x00003FFF
+
+START_FILE
+\f
+/* Record terminal status separately for debugger and inferior.  */
+
+#ifdef SYSV_TTYS
+static struct termio ti_inferior;
+#else
+static struct sgttyb sg_inferior;
+static struct tchars tc_inferior;
+static struct ltchars ltc_inferior;
+static int lmode_inferior;
+#endif
+static int tflags_inferior;
+static int pgrp_inferior;
+
+#ifdef SYSV_TTYS
+static struct termio ti_ours;
+#else
+static struct sgttyb sg_ours;
+static struct tchars tc_ours;
+static struct ltchars ltc_ours;
+static int lmode_ours;
+#endif
+static int tflags_ours;
+static int pgrp_ours;
+
+/* 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 ()
+{
+
+#ifdef SYSV_TTYS
+  ti_inferior = ti_ours;
+#else
+  sg_inferior = sg_ours;
+  tc_inferior = tc_ours;
+  ltc_inferior = ltc_ours;
+  lmode_inferior = lmode_ours;
+#endif
+  tflags_inferior = tflags_ours;
+  pgrp_inferior = inferior_pid;
+
+  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 (terminal_is_ours)   /*  && inferior_thisrun_terminal == 0) */
+    {
+      fcntl (0, F_SETFL, tflags_inferior);
+      fcntl (0, F_SETFL, tflags_inferior);
+#ifdef SYSV_TTYS
+      ioctl (0, TCSETA, &ti_inferior);
+#else
+      ioctl (0, TIOCSETN, &sg_inferior);
+      ioctl (0, TIOCSETC, &tc_inferior);
+      ioctl (0, TIOCSLTC, &ltc_inferior);
+      ioctl (0, TIOCLSET, &lmode_inferior);
+#endif
+      ioctl (0, TIOCSPGRP, &pgrp_inferior);
+    }
+  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 ()
+{
+  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 ()
+{
+  terminal_ours_1 (0);
+}
+
+static void
+terminal_ours_1 (output_only)
+     int output_only;
+{
+  /* Ignore this signal since it will happen when we try to set the pgrp.  */
+  int (*osigttou) ();
+
+  if (!terminal_is_ours)  /*   && inferior_thisrun_terminal == 0)  */
+    {
+      terminal_is_ours = 1;
+
+      osigttou = signal (SIGTTOU, SIG_IGN);
+
+      ioctl (0, TIOCGPGRP, &pgrp_inferior);
+      ioctl (0, TIOCSPGRP, &pgrp_ours);
+
+      signal (SIGTTOU, osigttou);
+
+      tflags_inferior = fcntl (0, F_GETFL, 0);
+#ifdef SYSV_TTYS
+      ioctl (0, TCGETA, &ti_inferior);
+#else
+      ioctl (0, TIOCGETP, &sg_inferior);
+      ioctl (0, TIOCGETC, &tc_inferior);
+      ioctl (0, TIOCGLTC, &ltc_inferior);
+      ioctl (0, TIOCLGET, &lmode_inferior);
+#endif
+    }
+
+  fcntl (0, F_SETFL, tflags_ours);
+  fcntl (0, F_SETFL, tflags_ours);
+
+
+#ifdef SYSV_TTYS
+  ti_ours.c_lflag |= ICANON | ISIG;
+  if (output_only)
+    ti_ours.c_lflag &= ~((ICANON|ISIG)&ti_inferior.c_lflag);
+  ioctl (0, TCSETA, &ti_ours);
+  ti_ours.c_lflag |= ICANON | ISIG;
+#else
+  sg_ours.sg_flags &= ~RAW & ~CBREAK;
+  if (output_only)
+    sg_ours.sg_flags |= (RAW | CBREAK) & sg_inferior.sg_flags;
+  ioctl (0, TIOCSETN, &sg_ours);
+  ioctl (0, TIOCSETC, &tc_ours);
+  ioctl (0, TIOCSLTC, &ltc_ours);
+  ioctl (0, TIOCLSET, &lmode_ours);
+  sg_ours.sg_flags &= ~RAW & ~CBREAK;
+#endif
+}
+
+static void
+term_status_command ()
+{
+  register int i;
+  printf ("Inferior's terminal status (currently saved by GDB):\n");
+#ifdef SYSV_TTYS
+  printf ("fcntl flags = 0x%x, owner pid = %d.\n",
+         tflags_inferior, pgrp_inferior);
+  printf ("iflag = 0x%04x, oflag = 0x%04x, cflag = 0x%04x, lflag = 0x%04x\n",
+         ti_inferior.c_iflag, ti_inferior.c_oflag,
+         ti_inferior.c_cflag, ti_inferior.c_lflag);
+  printf ("line discipline = %d\n", ti_inferior.c_line);
+  printf ("control chars: ");
+  for (i = 0; i < NCC; i++)
+    printf ("0x%x ", ti_inferior.c_cc[i]);
+  printf ("\n");
+#else
+  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);
+  printf ("tchars: ");
+  for (i = 0; i < sizeof (struct tchars); i++)
+    printf ("0x%x ", ((char *)&tc_inferior)[i]);
+  printf ("\n");
+  printf ("ltchars: ");
+  for (i = 0; i < sizeof (struct ltchars); i++)
+    printf ("0x%x ", ((char *)&ltc_inferior)[i]);
+  printf ("\n");
+#endif
+}
+\f
+static void
+new_tty (ttyname)
+     char *ttyname;
+{
+  register int tty;
+  register int fd;
+
+#if 0
+  /* I think it is better not to do this.  Then C-z on the GDB terminal
+     will still stop the program, while C-z on the data terminal
+     will be input.  */
+
+  /* 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);
+}
+\f
+/* 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 ());
+
+      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);  */
+
+      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.  */
+
+static void
+kill_command ()
+{
+  if (inferior_pid == 0)
+    error ("The program is not being run.");
+  if (!query ("Kill the inferior process? "))
+    error ("Not confirmed.");
+  kill_inferior ();
+}
+
+kill_inferior ()
+{
+  if (inferior_pid == 0)
+    return;
+  ptrace (8, inferior_pid, 0, 0);
+  wait (0);
+  inferior_died ();
+}
+
+inferior_died ()
+{
+  inferior_pid = 0;
+  attach_flag = 0;
+  mark_breakpoints_out ();
+  reopen_exec_file ();
+  if (have_core_file_p ())
+    set_current_frame (read_register (FP_REGNUM));
+}
+
+/* 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;
+  ptrace (step ? 9 : 7, inferior_pid, 1, signal);
+  if (errno)
+    perror_with_name ("ptrace");
+}
+\f
+#ifdef NEW_SUN_PTRACE
+
+/* 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
+\f
+#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);
+  ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers);
+
+  bcopy (&inferior_registers, registers, 16 * 4);
+  bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
+        sizeof inferior_fp_registers.fps_regs);
+  *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+  *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+  bcopy (&inferior_fp_registers.fps_control,
+        &registers[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 (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+        sizeof inferior_fp_registers.fps_regs);
+  inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
+  inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
+  bcopy (&registers[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);
+  ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
+}
+
+#else
+
+void
+fetch_inferior_registers ()
+{
+  register int regno;
+  register unsigned int regaddr;
+  char buf[MAX_REGISTER_RAW_SIZE];
+  register int i;
+
+#ifdef UMAX_PTRACE
+  unsigned int offset = 0;
+#else
+  struct user u;
+  unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
+  offset = ptrace (3, inferior_pid, offset, 0) & UPAGE_MASK;
+#endif
+
+  for (regno = 0; regno < NUM_REGS; regno++)
+    {
+      regaddr = register_addr (regno, offset);
+      for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+       {
+         *(int *) &buf[i] = ptrace (3, inferior_pid, regaddr, 0);
+         regaddr += sizeof (int);
+       }
+      supply_register (regno, buf);
+    }
+}
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+
+store_inferior_registers (regno)
+     int regno;
+{
+  register unsigned int regaddr;
+  char buf[80];
+
+#ifdef UMAX_PTRACE
+  unsigned int offset = 0;
+#else
+  struct user u;
+  unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
+  offset = ptrace (3, inferior_pid, offset, 0) & UPAGE_MASK;
+#endif
+
+  if (regno >= 0)
+    {
+      regaddr = register_addr (regno, offset);
+      errno = 0;
+      ptrace (6, inferior_pid, regaddr, read_register (regno));
+      if (errno != 0)
+       {
+         sprintf (buf, "writing register number %d", regno);
+         perror_with_name (buf);
+       }
+    }
+  else for (regno = 0; regno < NUM_REGS; regno++)
+    {
+      regaddr = register_addr (regno, offset);
+      errno = 0;
+      ptrace (6, inferior_pid, regaddr, read_register (regno));
+      if (errno != 0)
+       {
+         sprintf (buf, "writing register number %d", regno);
+         perror_with_name (buf);
+       }
+    }
+}
+
+#endif /* not NEW_SUN_PTRACE */
+\f
+/* 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 memnory 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;
+}
+\f
+static void
+try_writing_regs_command ()
+{
+  register int i;
+  register int value;
+  extern int errno;
+
+  if (inferior_pid == 0)
+    error ("The program is not being run.");
+
+  for (i = 0; ; i += 2)
+    {
+      QUIT;
+      errno = 0;
+      value = ptrace (3, inferior_pid, i, 0);
+      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);
+    }
+}
+\f
+static
+initialize ()
+{
+  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;
+
+#ifdef SYSV_TTYS
+  ioctl (0, TCGETA, &ti_ours);
+#else
+  ioctl (0, TIOCGETP, &sg_ours);
+  ioctl (0, TIOCGETC, &tc_ours);
+  ioctl (0, TIOCGLTC, &ltc_ours);
+  ioctl (0, TIOCLGET, &lmode_ours);
+#endif
+  fcntl (0, F_GETFL, tflags_ours);
+  ioctl (0, TIOCGPGRP, &pgrp_ours);
+
+  terminal_is_ours = 1;
+}
+
+END_FILE
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d28 1
+a30 1
+#include <sys/user.h>
+d36 11
+d56 4
+d67 2
+d73 3
+d80 1
+d84 3
+d91 1
+d110 4
+d118 1
+d135 3
+d142 1
+d191 3
+d198 1
+d201 11
+a214 3
+
+  fcntl (0, F_SETFL, tflags_ours);
+  fcntl (0, F_SETFL, tflags_ours);
+d220 1
+d228 12
+d251 1
+d470 1
+a470 1
+  offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
+d500 1
+a500 1
+  offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
+d647 3
+d654 1
+@
diff --git a/gdb/RCS/m-mac-aux.h,v b/gdb/RCS/m-mac-aux.h,v
new file mode 100644 (file)
index 0000000..eaac3dd
--- /dev/null
@@ -0,0 +1,523 @@
+head     1.2;
+access   ;
+symbols  RMS-has:1.2;
+locks    ; strict;
+comment  @ * @;
+
+
+1.2
+date     88.01.26.05.16.06;  author gnu;  state Exp;
+branches ;
+next     1.1;
+
+1.1
+date     88.01.26.05.15.44;  author gnu;  state Exp;
+branches ;
+next     ;
+
+
+desc
+@Originally nonexistent, I create it.
+@
+
+
+1.2
+log
+@Original new config file for Mac-II running A/UX.
+@
+text
+@/* Parameters for execution on Macintosh under A/UX, 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 mac_aux
+#define mac_aux
+#endif
+
+/* Get rid of any system-imposed stack limit if possible.  */
+
+#undef 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.  */
+
+#undef NAMES_HAVE_UNDERSCORE
+
+/* COFF format object files */
+
+#define COFF_FORMAT
+
+/* System eVil ttys */
+
+#define SYSV_TTYS
+
+/* Debugger information will not be in DBX format.  */
+
+#undef 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.  */
+
+#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.  */
+
+#define BREAKPOINT {0x4e, 0x4f}
+
+/* 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 2
+
+/* Nonzero if instruction at PC is a return instruction.  */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e76)
+
+/* Return 1 if P points to an invalid floating point value.  */
+
+#define INVALID_FLOAT(p, len) 0   /* Just a first guess; not checked */
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 31
+
+/* 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", "fpcode", "fpflags" }
+
+/* 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 */
+
+/* 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.  */
+
+#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)
+
+/* 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))
+
+/* Enable use of alternate code to read and write registers.  */
+
+#undef NEW_SUN_PTRACE
+
+/* Enable use of alternate code for Sun's format of core dump file.  */
+
+#undef NEW_SUN_CORE
+
+/* Do implement the attach and detach commands.  */
+
+#undef 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
+\f
+/* 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 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, 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 + 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.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 */ \
+    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;         \
+}
+\f
+/* 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 CORE_ADDR fp = read_register (FP_REGNUM);            \
+  register int regnum;                                          \
+  struct frame_saved_regs fsr;                                  \
+  struct frame_info fi;                                                 \
+  char raw_buffer[12];                                          \
+  fi = get_frame_info (fp);                                     \
+  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);                           \
+  set_current_frame (read_register (FP_REGNUM)); }
+
+/* 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
+     bpt
+     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, fun, nargs)     \
+{ *(int *)((char *) dummyname + 20) = nargs * 4;  \
+  *(int *)((char *) dummyname + 14) = fun; }
+\f
+/* 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.1
+log
+@Initial revision
+@
+text
+@d1 485
+@
diff --git a/gdb/RCS/m-mac-auxinit.h,v b/gdb/RCS/m-mac-auxinit.h,v
new file mode 100644 (file)
index 0000000..796bc8d
--- /dev/null
@@ -0,0 +1,43 @@
+head     1.2;
+access   ;
+symbols  RMS-has:1.2;
+locks    ; strict;
+comment  @ * @;
+
+
+1.2
+date     88.01.26.05.19.09;  author gnu;  state Exp;
+branches ;
+next     1.1;
+
+1.1
+date     88.01.26.05.18.45;  author gnu;  state Exp;
+branches ;
+next     ;
+
+
+desc
+@Originally nonexistent.
+@
+
+
+1.2
+log
+@Created by John Gilmore for Mac A/UX
+@
+text
+@
+/* This is how the size of an individual .o file's text segment
+   is rounded on a mac under a/ux.  */
+
+#define FILEADDR_ROUND(addr) (addr)
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d1 5
+@
diff --git a/gdb/RCS/m68k-pinsn.c,v b/gdb/RCS/m68k-pinsn.c,v
new file mode 100644 (file)
index 0000000..dedc0e7
--- /dev/null
@@ -0,0 +1,828 @@
+head     1.2;
+access   ;
+symbols  RMS-has:1.2;
+locks    ; strict;
+comment  @ * @;
+
+
+1.2
+date     88.01.26.05.08.29;  author gnu;  state Exp;
+branches ;
+next     1.1;
+
+1.1
+date     88.01.21.22.04.55;  author gnu;  state Exp;
+branches ;
+next     ;
+
+
+desc
+@From RMS's development sources on wheaties, 20Jan88
+@
+
+
+1.2
+log
+@Avoid the so-called "portable" preassembled instructions; call a macro
+to generate them, since a/ux assembler uses a different syntax (grumble)
+@
+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 <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "m68k-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... */
+\f
+/* 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, 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, "<invalid address mode 0%o>", 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]);
+}
+\f
+/* 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.  */
+
+#ifdef mac_aux
+#ifdef __STDC__
+#define        asm16(str)      asm ("short     " str#)
+#else
+#define        asm16(str)      asm ("short     str")
+#endif
+#else
+#ifdef __STDC__
+#define        asm16(str)      asm (".word     " str#)
+#else
+#define        asm16(str)      asm (".word     str")
+#endif
+#endif
+
+convert_from_68881 (from, to)
+     char *from;
+     double *to;
+{
+#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.  */
+  asm16 (020156);
+  asm16 (8);
+  asm16 (021156);
+  asm16 (12);
+  asm16 (0xf210);
+  asm16 (0x4800);
+  asm16 (0xf211);
+  asm16 (0x7400);
+#endif
+}
+
+/* The converse: convert the double *FROM to an extended float
+   and store where TO points.  */
+
+convert_to_68881 (from, to)
+     double *from;
+     char *to;
+{
+#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.  */
+  asm16 (020156);
+  asm16 (8);
+  asm16 (021156);
+  asm16 (12);
+  asm16 (0xf210);
+  asm16 (0x5400);
+  asm16 (0xf211);
+  asm16 (0x6800);
+#endif
+}
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d713 14
+d739 8
+a746 6
+  asm (".word 020156");
+  asm (".word 8");
+  asm (".word 021156");
+  asm (".word 12");
+  asm (".long 0xf2104800");
+  asm (".long 0xf2117400");
+d764 8
+a771 6
+  asm (".word 020156");
+  asm (".word 8");
+  asm (".word 021156");
+  asm (".word 12");
+  asm (".long 0xf2105400");
+  asm (".long 0xf2116800");
+@
diff --git a/gdb/RCS/main.c,v b/gdb/RCS/main.c,v
new file mode 100644 (file)
index 0000000..ae6615f
--- /dev/null
@@ -0,0 +1,1110 @@
+head     1.2;
+access   ;
+symbols  RMS-has:1.2;
+locks    ; strict;
+comment  @ * @;
+
+
+1.2
+date     88.01.26.05.09.12;  author gnu;  state Exp;
+branches ;
+next     1.1;
+
+1.1
+date     88.01.21.04.23.16;  author gnu;  state Exp;
+branches ;
+next     ;
+
+
+desc
+@Original from RMS development on wheaties, 20Jan88
+@
+
+
+1.2
+log
+@Add <sys/types.h>
+@
+text
+@/* Top level 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 <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/param.h>
+#include "defs.h"
+#include "command.h"
+#include "param.h"
+
+#ifdef SET_STACK_LIMIT_HUGE
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+
+/* Version number of GDB, as a string.  */
+
+extern char *version;
+
+/* Chain containing all defined commands.  */
+
+struct cmd_list_element *cmdlist;
+
+/* Chain containing all defined info subcommands.  */
+
+struct cmd_list_element *infolist;
+
+/* stdio stream that command input is being read from.  */
+
+FILE *instream;
+
+/* 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) ();
+
+void free_command_lines ();
+char *read_line ();
+static void initialize_main ();
+void command_loop ();
+static void source_command ();
+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;
+
+return_to_top_level ()
+{
+  quit_flag = 0;
+  immediate_quit = 0;
+  clear_breakpoint_commands ();
+  clear_momentary_breakpoints ();
+  do_cleanups (0);
+  longjmp (to_top_level, 1);
+}
+\f
+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;
+
+#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);
+    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 (argv[i][0] == '-')
+       i++;
+    }
+
+  /* Run the init function of each source file */
+
+  initialize_all_files ();
+  initialize_main ();          /* But that omits this file!  Do it now */
+
+  signal (SIGINT, request_quit);
+  signal (SIGQUIT, SIG_IGN);
+
+  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"))
+           /* 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);
+             /* -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)
+       {
+         if (*p)
+           error ("User-defined commands cannot take command-line arguments: \"%s\"",
+                  p);
+         cmdlines = (struct command_line *) c->function;
+         if (cmdlines == (struct command_line *) 0)
+           /* Null command */
+           return;
+         while (cmdlines)
+           {
+             execute_command (cmdlines->line, 0);
+             cmdlines = cmdlines->next;
+           }
+       }
+      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 (instream == stdin)
+       printf ("%s", prompt);
+      fflush (stdout);
+
+      if (window_hook && instream == stdin)
+       (*window_hook) (instream, prompt);
+
+      quit_flag = 0;
+      old_chain = make_cleanup (do_nothing, 0);
+      execute_command (read_line (instream == stdin), instream == stdin);
+      /* Do any commands attached to breakpoint we stopped at.  */
+      do_breakpoint_commands ();
+      do_cleanups (old_chain);
+    }
+}
+\f
+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;
+}
+
+/* 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 *
+read_line (repeat)
+     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++;
+  signal (SIGTSTP, stop_sig);
+
+  while (1)
+    {
+      c = fgetc (instream);
+      if (c == -1 || c == '\n')
+       break;
+      if (p - line == linesize - 1)
+       {
+         linesize *= 2;
+         nline = (char *) xrealloc (line, linesize);
+         p += nline - line;
+         line = nline;
+       }
+      *p++ = c;
+    }
+
+  signal (SIGTSTP, SIG_DFL);
+  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;
+}
+\f
+/* 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 = read_line (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;
+    }
+}
+\f
+/* Add an element to the list of info subcommands.  */
+
+void
+add_info (name, fun, doc)
+     char *name;
+     void (*fun) ();
+     char *doc;
+{
+  add_cmd (name, 0, 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_cmd (0, infolist, "info ", -1, stdout);
+}
+\f
+/* 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, cmdlist, "", -2, stdout);
+}
+\f
+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 >= '1' && *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);
+
+  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);
+}
+\f
+static void
+copying_info ()
+{
+  immediate_quit++;
+  printf ("                GDB GENERAL PUBLIC LICENSE\n\
+\n\
+ Copyright (C) 1986 Richard M. Stallman\n\
+ Everyone is permitted to copy and distribute verbatim copies\n\
+ of this license, but changing it is not allowed.\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);
+  read_line ();
+
+  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);
+  read_line ();
+
+  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) 1987 Free Software Foundation, Inc.\" (or with the year updated if\n\
+that is 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);
+  read_line ();
+
+  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 third\n\
+    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) 1987 Free Software Foundation, Inc.\" (or with\n\
+    the year updated if appropriate), saying that there\n\
+    is no warranty (or else, saying that you provide\n\
+    a warranty) and that users may redistribute the program under\n\
+    these conditions, and telling the user how to view a copy of\n\
+    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\
+--Type Return to print more--");
+  fflush (stdout);
+  read_line ();
+
+  printf ("\
+  3. You may copy and distribute GDB or any portion of it in\n\
+compiled, executable or object code form under the terms of Paragraphs\n\
+1 and 2 above provided that you do the following:\n\
+\n\
+    a) cause each such copy to be accompanied by the\n\
+    corresponding machine-readable source code, which must\n\
+    be distributed under the terms of Paragraphs 1 and 2 above; or,\n\
+\n\
+    b) cause each such copy to be accompanied by a\n\
+    written offer, with no time limit, to give any third party\n\
+    free (except for a nominal shipping charge) a machine readable\n\
+    copy of the corresponding source code, to be distributed\n\
+    under the terms of Paragraphs 1 and 2 above; or,\n\n");
+
+  printf ("\
+    c) in the case of a recipient of GDB in compiled, executable\n\
+    or object code form (without the corresponding source code) you\n\
+    shall cause copies you distribute to be accompanied by a copy\n\
+    of the written offer of source code which you received along\n\
+    with the copy you received.\n\
+--Type Return to print more--");
+  fflush (stdout);
+  read_line ();
+
+  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\
+  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--;
+}
+\f
+static void
+print_gdb_version ()
+{
+  printf ("GDB %s, Copyright (C) 1987 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--;
+}
+\f
+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;
+}
+\f
+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;
+}
+\f
+static void
+pwd_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  char buf[MAXPATHLEN];
+  if (arg) error ("The \"pwd\" command does not take an argument: %s", arg);
+  printf ("Working directory %s.\n", getwd (buf));
+}
+
+static void
+cd_command (dir, from_tty)
+     char *dir;
+     int from_tty;
+{
+  if (dir == 0)
+    error_no_arg ("new working directory");
+
+  if (chdir (dir) < 0)
+    perror_with_name (dir);
+  if (from_tty)
+    pwd_command ((char *) 0, 1);
+}
+
+\f
+/* Clean up on error during a "source" command.
+   Close the file opened by the command
+   and restore the previous input stream.  */
+
+static void
+source_cleanup (stream)
+     FILE *stream;
+{
+  fclose (instream);
+  instream = stream;
+}
+
+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);
+    }
+}
+
+\f
+static void
+initialize_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_com ("set-prompt", class_support, set_prompt_command,
+          "Change gdb's prompt from the default of \"(gdb)\"");
+  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
+@d21 1
+@
diff --git a/gdb/RCS/source.c,v b/gdb/RCS/source.c,v
new file mode 100644 (file)
index 0000000..bd3218b
--- /dev/null
@@ -0,0 +1,705 @@
+head     1.2;
+access   ;
+symbols  RMS-has:1.2;
+locks    ; strict;
+comment  @ * @;
+
+
+1.2
+date     88.01.26.05.09.34;  author gnu;  state Exp;
+branches ;
+next     1.1;
+
+1.1
+date     88.01.21.04.30.11;  author gnu;  state Exp;
+branches ;
+next     ;
+
+
+desc
+@Original from RMS development sources on wheaties, 20Jan88
+@
+
+
+1.2
+log
+@Add <sys/types.h>
+@
+text
+@/* List lines of source files 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 <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include "defs.h"
+#include "initialize.h"
+#include "symtab.h"
+
+/* 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 for "info line" to work on if no line specified.  */
+
+static int line_info_default_line;
+
+/* First line number listed by last listing command.  */
+
+static int first_line_listed;
+
+START_FILE
+\f
+/* Set the source file default for the "list" command,
+   specifying a symtab.  */
+
+void
+select_source_symtab (s)
+     register struct symtab *s;
+{
+  if (s)
+    {
+      struct symtab_and_line sal;
+
+      /* Make the default place to list be the function `main'
+        if one exists.  */
+      if (lookup_symbol ("main", 0, VAR_NAMESPACE))
+       {
+         sal = decode_line_spec ("main", 1);
+         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.  */
+      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;
+    }
+}
+\f
+static void
+directories_info ()
+{
+  printf ("Source directories searched: %s\n", source_path);
+}
+
+static void
+init_source_path ()
+{
+  register struct symtab *s;
+  char wd[MAXPATHLEN];
+  if (getwd (wd) == NULL)
+    perror_with_name ("getwd");
+
+  source_path = savestring (wd, strlen (wd));
+
+  /* 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;
+
+  char wd[MAXPATHLEN];
+  if (getwd (wd) == NULL)
+    perror_with_name ("getwd");
+
+  if (dirname == 0)
+    {
+      if (query ("Reinitialize source path to %s? ", wd))
+       {
+         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 = wd;
+             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 (wd, "/", 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 ();
+    }
+}
+\f
+/* 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
+      {
+       char dirname[MAXPATHLEN];
+       if (getwd (dirname) == NULL)
+         perror_with_name ("getwd");
+       *filename_opened = concat (dirname, "/", filename);
+      }
+
+  return fd;
+}
+\f
+/* 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 && 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')
+       {
+         if (nlines == lines_allocated)
+           line_charpos = (int *) xrealloc (line_charpos,
+                                            sizeof (int) * (lines_allocated *= 2));
+         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;
+}
+\f
+/* 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, fullname);
+  if (desc < 0)
+    {
+      *fullname = NULL;
+      return 0;
+    }  
+  if (s->line_charpos == 0) linenums_changed = 1;
+  if (linenums_changed) find_source_lines (s, desc);
+  close (desc);
+  return linenums_changed;
+}
+\f
+/* 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)
+     struct symtab *s;
+     int line, stopline;
+{
+  register int c;
+  register int desc;
+  register FILE *stream;
+  int nlines = stopline - line;
+
+  desc = openp (source_path, 0, s->filename, O_RDONLY, 0, (char **) 0);
+  if (desc < 0)
+    perror_with_name (s->filename);
+
+  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;
+      line_info_default_line = 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);
+}
+\f
+static void
+list_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  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)
+    error ("Listing source lines requires symbols.");
+
+  /* "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);
+      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);
+      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
+    sal = decode_line_1 (&arg1, 0, 0, 0);
+
+  /* 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)
+       sal_end = decode_line_1 (&arg1, 0, 0, 0);
+      else
+       sal_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line);
+    }
+
+  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);
+  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);
+  else
+    print_source_lines (sal.symtab, sal.line,
+                       dummy_end ? sal.line + 10 : sal_end.line + 1);
+}
+\f
+/* Print info on range of pc's in a specified line.  */
+
+static void
+line_info (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  struct symtab_and_line sal;
+  int start_pc, end_pc;
+
+  if (arg == 0)
+    {
+      sal.symtab = current_source_symtab;
+      sal.line = line_info_default_line;
+    }
+  else
+    {
+      sal = decode_line_spec (arg);
+
+      /* If this command is repeated with RET,
+        turn it into the no-arg variant.  */
+
+      if (from_tty)
+       *arg = 0;
+    }
+
+  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.  */
+      line_info_default_line = sal.line + 1;
+    }
+  else
+    printf ("Line number %d is out of range for \"%s\".\n",
+           sal.line, sal.symtab->filename);
+}
+\f
+static
+initialize ()
+{
+  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 ("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.");
+}
+
+END_FILE
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d22 1
+@
diff --git a/gdb/RCS/symmisc.c,v b/gdb/RCS/symmisc.c,v
new file mode 100644 (file)
index 0000000..42653df
--- /dev/null
@@ -0,0 +1,575 @@
+head     1.2;
+access   ;
+symbols  RMS-has:1.2;
+locks    ; strict;
+comment  @ * @;
+
+
+1.2
+date     88.01.26.05.09.53;  author gnu;  state Exp;
+branches ;
+next     1.1;
+
+1.1
+date     88.01.26.04.25.22;  author gnu;  state Exp;
+branches ;
+next     ;
+
+
+desc
+@Original from RMS's devl sources on wheaties
+@
+
+
+1.2
+log
+@Check for null pointer passed to free()...
+@
+text
+@/* Do various things to symbol tables (other than lookup)), 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 "defs.h"
+#include "initialize.h"
+#include "symtab.h"
+
+#include <stdio.h>
+#include <obstack.h>
+
+static void free_symtab ();
+
+START_FILE
+\f
+/* Free all the symtabs that are currently installed,
+   and all storage associated with them.
+   Leaves us in a consistent state with no symtabs installed.  */
+
+void
+free_all_symtabs ()
+{
+  register struct symtab *s, *snext;
+
+  /* All values will be invalid because their types will be!  */
+
+  clear_value_history ();
+  clear_displays ();
+  clear_internalvars ();
+  clear_breakpoints ();
+  set_default_breakpoint (0, 0, 0, 0);
+
+  current_source_symtab = 0;
+
+  for (s = symtab_list; s; s = snext)
+    {
+      snext = s->next;
+      free_symtab (s);
+    }
+  symtab_list = 0;
+  obstack_free (symbol_obstack, 0);
+  obstack_init (symbol_obstack);
+
+  if (misc_function_vector)
+    free (misc_function_vector);
+  misc_function_count = 0;
+  misc_function_vector = 0;
+}
+
+/* Free a struct block <- B and all the symbols defined in that block.  */
+
+static void
+free_symtab_block (b)
+     struct block *b;
+{
+  register int i, n;
+  n = BLOCK_NSYMS (b);
+  for (i = 0; i < n; i++)
+    {
+      free (SYMBOL_NAME (BLOCK_SYM (b, i)));
+      free (BLOCK_SYM (b, i));
+    }
+  free (b);
+}
+
+/* Free all the storage associated with the struct symtab <- S.
+   Note that some symtabs have contents malloc'ed structure by structure,
+   while some have contents that all live inside one big block of memory,
+   and some share the contents of another symbol table and so you should
+   not free the contents on their behalf (except sometimes the linetable,
+   which maybe per symtab even when the rest is not).
+   It is s->free_code that says which alternative to use.  */
+
+static void
+free_symtab (s)
+     register struct symtab *s;
+{
+  register int i, n;
+  register struct blockvector *bv;
+  register struct type *type;
+  register struct typevector *tv;
+
+  switch (s->free_code)
+    {
+    case free_nothing:
+      /* All the contents are part of a big block of memory
+        and some other symtab is in charge of freeing that block.
+        Therefore, do nothing.  */
+      break;
+
+    case free_explicit:
+      /* All the contents are part of a big block of memory
+        and that is our `free_ptr' and will be freed below.  */
+      break;
+
+    case free_contents:
+      /* Here all the contents were malloc'ed structure by structure
+        and must be freed that way.  */
+      /* First free the blocks (and their symbols.  */
+      bv = BLOCKVECTOR (s);
+      n = BLOCKVECTOR_NBLOCKS (bv);
+      for (i = 0; i < n; i++)
+       free_symtab_block (BLOCKVECTOR_BLOCK (bv, i));
+      /* Free the blockvector itself.  */
+      free (bv);
+      /* Free the type vector.  */
+      tv = TYPEVECTOR (s);
+      if (tv)          /* FIXME, should this happen?  It does... */
+       free (tv);
+      /* Also free the linetable.  */
+      
+    case free_linetable:
+      /* Everything will be freed either by our `free_ptr'
+        or by some other symbatb, except for our linetable.
+        Free that now.  */
+      free (LINETABLE (s));
+      break;
+    }
+
+  /* If there is a single block of memory to free, free it.  */
+  if (s->free_ptr)
+    free (s->free_ptr);
+
+  if (s->line_charpos)
+    free (s->line_charpos);
+  free (s->filename);
+  free (s);
+}
+\f
+/* Convert a raw symbol-segment to a struct symtab,
+   and relocate its internal pointers so that it is valid.  */
+
+/* This is how to relocate one pointer, given a name for it.
+   Works independent of the type of object pointed to.  */
+#define RELOCATE(slot) (slot ? (* (char **) &slot += relocation) : 0)
+
+/* This is the inverse of RELOCATE.  We use it when storing
+   a core address into a slot that has yet to be relocated.  */
+#define UNRELOCATE(slot) (slot ? (* (char **) &slot -= relocation) : 0)
+
+/* During the process of relocation, this holds the amount to relocate by
+   (the address of the file's symtab data, in core in the debugger).  */
+static int relocation;
+
+#define CORE_RELOCATE(slot) \
+  ((slot) += (((slot) < data_start) ? text_relocation          \
+             : ((slot) < bss_start) ? data_relocation : bss_relocation))
+
+#define TEXT_RELOCATE(slot)  ((slot) += text_relocation)
+
+/* Relocation amounts for addresses in the program's core image.  */
+static int text_relocation, data_relocation, bss_relocation;
+
+/* Boundaries that divide program core addresses into text, data and bss;
+   used to determine which relocation amount to use.  */
+static int data_start, bss_start;
+
+static void relocate_typevector ();
+static void relocate_blockvector ();
+static void relocate_type ();
+static void relocate_block ();
+static void relocate_symbol ();
+
+/* Relocate a file symbol table so that all the pointers
+   are valid C pointers.  Pass the struct symtab for the file
+   and the amount to relocate by.  */
+
+static struct symtab *
+relocate_symtab (root)
+     struct symbol_root *root;
+{
+  struct symtab *sp = (struct symtab *) xmalloc (sizeof (struct symtab));
+  bzero (sp, sizeof (struct symtab));
+
+  relocation = (int) root;
+  text_relocation = root->textrel;
+  data_relocation = root->datarel;
+  bss_relocation = root->bssrel;
+  data_start = root->databeg;
+  bss_start = root->bssbeg;
+
+  sp->filename = root->filename;
+  sp->ldsymoff = root->ldsymoff;
+  sp->language = root->language;
+  sp->compilation = root->compilation;
+  sp->version = root->version;
+  sp->blockvector = root->blockvector;
+  sp->typevector = root->typevector;
+  sp->free_code = free_explicit;
+  sp->free_ptr = (char *) root;
+
+  RELOCATE (TYPEVECTOR (sp));
+  RELOCATE (BLOCKVECTOR (sp));
+  RELOCATE (sp->version);
+  RELOCATE (sp->compilation);
+  RELOCATE (sp->filename);
+
+  relocate_typevector (TYPEVECTOR (sp));
+  relocate_blockvector (BLOCKVECTOR (sp));
+
+  return sp;
+}
+
+static void
+relocate_typevector (tv)
+     struct typevector *tv;
+{
+  register int ntypes = TYPEVECTOR_NTYPES (tv);
+  register int i;
+
+  for (i = 0; i < ntypes; i++)
+    RELOCATE (TYPEVECTOR_TYPE (tv, i));
+  for (i = 0; i < ntypes; i++)
+    relocate_type (TYPEVECTOR_TYPE (tv, i));
+}
+
+static void
+relocate_blockvector (blp)
+     register struct blockvector *blp;
+{
+  register int nblocks = BLOCKVECTOR_NBLOCKS (blp);
+  register int i;
+  for (i = 0; i < nblocks; i++)
+    RELOCATE (BLOCKVECTOR_BLOCK (blp, i));
+  for (i = 0; i < nblocks; i++)
+    relocate_block (BLOCKVECTOR_BLOCK (blp, i));
+}
+
+static void
+relocate_block (bp)
+     register struct block *bp;
+{
+  register int nsyms = BLOCK_NSYMS (bp);
+  register int i;
+
+  TEXT_RELOCATE (BLOCK_START (bp));
+  TEXT_RELOCATE (BLOCK_END (bp));
+
+  /* These two should not be recursively processed.
+     The superblock need not be because all blocks are
+     processed from relocate_blockvector.
+     The function need not be because it will be processed
+     under the block which is its scope.  */
+  RELOCATE (BLOCK_SUPERBLOCK (bp));
+  RELOCATE (BLOCK_FUNCTION (bp));
+
+  for (i = 0; i < nsyms; i++)
+    RELOCATE (BLOCK_SYM (bp, i));
+
+  for (i = 0; i < nsyms; i++)
+    relocate_symbol (BLOCK_SYM (bp, i));
+}
+
+static void
+relocate_symbol (sp)
+     register struct symbol *sp;
+{
+  RELOCATE (SYMBOL_NAME (sp));
+  if (SYMBOL_CLASS (sp) == LOC_BLOCK)
+    {
+      RELOCATE (SYMBOL_BLOCK_VALUE (sp));
+      /* We can assume the block that belongs to this symbol
+        is not relocated yet, since it comes after
+        the block that contains this symbol.  */
+      BLOCK_FUNCTION (SYMBOL_BLOCK_VALUE (sp)) = sp;
+      UNRELOCATE (BLOCK_FUNCTION (SYMBOL_BLOCK_VALUE (sp)));
+    }
+  else if (SYMBOL_CLASS (sp) == LOC_STATIC)
+    CORE_RELOCATE (SYMBOL_VALUE (sp));
+  else if (SYMBOL_CLASS (sp) == LOC_LABEL)
+    TEXT_RELOCATE (SYMBOL_VALUE (sp));
+  RELOCATE (SYMBOL_TYPE (sp));
+}
+
+/* We cannot come up with an a priori spanning tree
+   for the network of types, since types can be used
+   for many symbols and also as components of other types.
+   Therefore, we need to be able to mark types that we
+   already have relocated (or are already in the middle of relocating)
+   as in a garbage collector.  */
+
+static void
+relocate_type (tp)
+     register struct type *tp;
+{
+  register int nfields = TYPE_NFIELDS (tp);
+  register int i;
+
+  RELOCATE (TYPE_NAME (tp));
+  RELOCATE (TYPE_TARGET_TYPE (tp));
+  RELOCATE (TYPE_FIELDS (tp));
+  RELOCATE (TYPE_POINTER_TYPE (tp));
+
+  for (i = 0; i < nfields; i++)
+    {
+      RELOCATE (TYPE_FIELD_TYPE (tp, i));
+      RELOCATE (TYPE_FIELD_NAME (tp, i));
+    }
+}
+\f
+/* Read symsegs from file named NAME open on DESC,
+   make symtabs from them, and return a chain of them.
+   Assumes DESC is prepositioned at the end of the string table,
+   just before the symsegs if there are any.  */
+
+struct symtab *
+read_symsegs (desc, name)
+     int desc;
+     char *name;
+{
+  struct symbol_root root;
+  register char *data;
+  register struct symtab *sp, *chain = 0;
+  register int len;
+
+  while (1)
+    {
+      len = myread (desc, &root, sizeof root);
+      if (len == 0 || root.format == 0)
+       break;
+      if (root.format != 1 ||
+         root.length < sizeof root)
+       error ("Invalid symbol segment format code");
+      data = (char *) xmalloc (root.length);
+      bcopy (&root, data, sizeof root);
+      len = myread (desc, data + sizeof root,
+                   root.length - sizeof root);
+      sp = relocate_symtab (data);
+      sp->next = chain;
+      chain = sp;
+    }
+
+  return chain;
+}
+\f
+static int block_depth ();
+static void print_spaces ();
+static void print_symbol ();
+
+print_symtabs (filename)
+     char *filename;
+{
+  FILE *outfile;
+  register struct symtab *s;
+  register int i, j;
+  int len, line, blen;
+  register struct linetable *l;
+  struct blockvector *bv;
+  register struct block *b;
+  int depth;
+  struct cleanup *cleanups;
+  extern int fclose();
+
+  if (filename == 0)
+    error_no_arg ("file to write symbol data in");
+  outfile = fopen (filename, "w");
+
+  cleanups = make_cleanup (fclose, outfile);
+  immediate_quit++;
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      /* First print the line table.  */
+      fprintf (outfile, "Symtab for file %s\n\n", s->filename);
+      fprintf (outfile, "Line table:\n\n");
+      l = LINETABLE (s);
+      len = l->nitems;
+      for (i = 0; i < len; i++)
+       {
+         if (l->item[i] < 0)
+           line = - l->item[i] - 1;
+         else
+           fprintf (outfile, " line %d at %x\n", ++line, l->item[i]);
+       }
+      /* Now print the block info.  */
+      fprintf (outfile, "\nBlockvector:\n\n");
+      bv = BLOCKVECTOR (s);
+      len = BLOCKVECTOR_NBLOCKS (bv);
+      for (i = 0; i < len; i++)
+       {
+         b = BLOCKVECTOR_BLOCK (bv, i);
+         depth = block_depth (b) * 2;
+         print_spaces (depth, outfile);
+         fprintf (outfile, "block #%03d (object 0x%x) ", i, b);
+         fprintf (outfile, "[0x%x..0x%x]", BLOCK_START (b), BLOCK_END (b));
+         if (BLOCK_SUPERBLOCK (b))
+           fprintf (outfile, " (under 0x%x)", BLOCK_SUPERBLOCK (b));
+         if (BLOCK_FUNCTION (b))
+           fprintf (outfile, " %s", SYMBOL_NAME (BLOCK_FUNCTION (b)));
+         fputc ('\n', outfile);
+         blen = BLOCK_NSYMS (b);
+         for (j = 0; j < blen; j++)
+           {
+             print_symbol (BLOCK_SYM (b, j), depth + 1, outfile);
+           }
+       }
+
+      fprintf (outfile, "\n\n");
+    }
+
+  immediate_quit--;
+  do_cleanups (cleanups);
+}
+
+static void
+print_symbol (symbol, depth, outfile)
+     struct symbol *symbol;
+     int depth;
+     FILE *outfile;
+{
+  print_spaces (depth, outfile);
+  if (SYMBOL_NAMESPACE (symbol) == LABEL_NAMESPACE)
+    {
+      fprintf (outfile, "label %s at 0x%x", SYMBOL_NAME (symbol),
+              SYMBOL_VALUE (symbol));
+      return;
+    }
+  if (SYMBOL_NAMESPACE (symbol) == STRUCT_NAMESPACE)
+    {
+      if (TYPE_NAME (SYMBOL_TYPE (symbol)))
+       {
+         type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth);
+       }
+      else
+       {
+         fprintf (outfile, "%s %s = ",
+              (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_ENUM
+               ? "enum"
+               : (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_STRUCT
+                  ? "struct" : "union")),
+              SYMBOL_NAME (symbol));
+         type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth);
+       }
+      fprintf (outfile, ";\n");
+    }
+  else
+    {
+      if (SYMBOL_CLASS (symbol) == LOC_TYPEDEF)
+       fprintf (outfile, "typedef ");
+      if (SYMBOL_TYPE (symbol))
+       {
+         type_print_1 (SYMBOL_TYPE (symbol), SYMBOL_NAME (symbol),
+                       outfile, 1, depth);
+         fprintf (outfile, "; ");
+       }
+      else
+       fprintf (outfile, "%s ", SYMBOL_NAME (symbol));
+
+      switch (SYMBOL_CLASS (symbol))
+       {
+       case LOC_CONST:
+         fprintf (outfile, "const %d (0x%x),",
+                  SYMBOL_VALUE (symbol), SYMBOL_VALUE (symbol));
+         break;
+
+       case LOC_CONST_BYTES:
+         fprintf (outfile, "const %d hex bytes:",
+                  TYPE_LENGTH (SYMBOL_TYPE (symbol)));
+         {
+           int i;
+           for (i = 0; i < TYPE_LENGTH (SYMBOL_TYPE (symbol)); i++)
+             fprintf (outfile, " %2x", SYMBOL_VALUE_BYTES (symbol) [i]);
+           fprintf (outfile, ",");
+         }
+         break;
+
+       case LOC_STATIC:
+         fprintf (outfile, "static at 0x%x,", SYMBOL_VALUE (symbol));
+         break;
+
+       case LOC_REGISTER:
+         fprintf (outfile, "register %d,", SYMBOL_VALUE (symbol));
+         break;
+
+       case LOC_ARG:
+         fprintf (outfile, "arg at 0x%x,", SYMBOL_VALUE (symbol));
+         break;
+
+       case LOC_LOCAL:
+         fprintf (outfile, "local at 0x%x,", SYMBOL_VALUE (symbol));
+         break;
+
+       case LOC_TYPEDEF:
+         break;
+
+       case LOC_LABEL:
+         fprintf (outfile, "label at 0x%x", SYMBOL_VALUE (symbol));
+         break;
+
+       case LOC_BLOCK:
+         fprintf (outfile, "block (object 0x%x) starting at 0x%x,",
+                  SYMBOL_VALUE (symbol),
+                  BLOCK_START (SYMBOL_BLOCK_VALUE (symbol)));
+         break;
+       }
+    }
+  fprintf (outfile, "\n");
+}
+
+/* Return the nexting depth of a block within other blocks in its symtab.  */
+
+static int
+block_depth (block)
+     struct block *block;
+{
+  register int i = 0;
+  while (block = BLOCK_SUPERBLOCK (block)) i++;
+  return i;
+}
+\f
+static
+initialize ()
+{
+  add_com ("printsyms", class_obscure, print_symtabs,
+          "Print dump of current symbol definitions to file OUTFILE.");
+}
+
+END_FILE
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d125 2
+a126 1
+      free (tv);
+@
diff --git a/gdb/RCS/symtab.c,v b/gdb/RCS/symtab.c,v
new file mode 100644 (file)
index 0000000..7ccdaac
--- /dev/null
@@ -0,0 +1,1153 @@
+head     1.2;
+access   ;
+symbols  RMS-has:1.2;
+locks    ; strict;
+comment  @ * @;
+
+
+1.2
+date     88.01.26.05.10.33;  author gnu;  state Exp;
+branches ;
+next     1.1;
+
+1.1
+date     88.01.26.02.18.56;  author gnu;  state Exp;
+branches ;
+next     ;
+
+
+desc
+@Original from RMS's wheaties devel sources
+@
+
+
+1.2
+log
+@Permit SYS V regular expression library as well as real Unix one.
+@
+text
+@/* Symbol table lookup for the GNU debugger, 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 "defs.h"
+#include "initialize.h"
+#include "symtab.h"
+#include "param.h"
+
+#include <stdio.h>
+#include <obstack.h>
+
+#ifdef mac_aux
+#define REGCMP
+#endif
+
+START_FILE
+
+/* Allocate an obstack to hold objects that should be freed
+   when we load a new symbol table.
+   This includes the symbols made by dbxread
+   and the types that are not permanent.  */
+
+struct obstack obstack1;
+
+struct obstack *symbol_obstack = &obstack1;
+
+/* These variables point to the objects
+   representing the predefined C data types.  */
+
+struct type *builtin_type_void;
+struct type *builtin_type_char;
+struct type *builtin_type_short;
+struct type *builtin_type_int;
+struct type *builtin_type_long;
+struct type *builtin_type_unsigned_char;
+struct type *builtin_type_unsigned_short;
+struct type *builtin_type_unsigned_int;
+struct type *builtin_type_unsigned_long;
+struct type *builtin_type_float;
+struct type *builtin_type_double;
+
+/* Lookup the symbol table of a source file named NAME.  */
+
+struct symtab *
+lookup_symtab (name)
+     char *name;
+{
+  register struct symtab *s;
+  register char *copy;
+
+  for (s = symtab_list; s; s = s->next)
+    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 = symtab_list; s; s = s->next)
+    if (!strcmp (copy, s->filename))
+      return s;
+
+  return 0;
+}
+\f
+/* Lookup a typedef or primitive type named NAME,
+   visible in lexical block BLOCK.
+   If NOERR is nonzero, return zero if NAME is not suitably defined.  */
+
+struct type *
+lookup_typename (name, block, noerr)
+     char *name;
+     struct block *block;
+     int noerr;
+{
+  register struct symbol *sym = lookup_symbol (name, block, VAR_NAMESPACE);
+  if (sym == 0 || SYMBOL_CLASS (sym) != LOC_TYPEDEF)
+    {
+      if (!strcmp (name, "int"))
+       return builtin_type_int;
+      if (!strcmp (name, "long"))
+       return builtin_type_long;
+      if (!strcmp (name, "short"))
+       return builtin_type_short;
+      if (!strcmp (name, "char"))
+       return builtin_type_char;
+      if (!strcmp (name, "float"))
+       return builtin_type_float;
+      if (!strcmp (name, "double"))
+       return builtin_type_double;
+      if (!strcmp (name, "void"))
+       return builtin_type_void;
+
+      if (noerr)
+       return 0;
+      error ("No type named %s.", name);
+    }
+  return SYMBOL_TYPE (sym);
+}
+
+struct type *
+lookup_unsigned_typename (name)
+     char *name;
+{
+  if (!strcmp (name, "int"))
+    return builtin_type_unsigned_int;
+  if (!strcmp (name, "long"))
+    return builtin_type_unsigned_long;
+  if (!strcmp (name, "short"))
+    return builtin_type_unsigned_short;
+  if (!strcmp (name, "char"))
+    return builtin_type_unsigned_char;
+  error ("No type named unsigned %s.", name);
+}
+
+/* Lookup a structure type named "struct NAME",
+   visible in lexical block BLOCK.  */
+
+struct type *
+lookup_struct (name, block)
+     char *name;
+     struct block *block;
+{
+  register struct symbol *sym = lookup_symbol (name, block, STRUCT_NAMESPACE);
+  if (sym == 0)
+    error ("No struct type named %s.", name);
+  if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_STRUCT)
+    error ("This context has union or enum %s, not a struct.", name);
+  return SYMBOL_TYPE (sym);
+}
+
+/* Lookup a union type named "union NAME",
+   visible in lexical block BLOCK.  */
+
+struct type *
+lookup_union (name, block)
+     char *name;
+     struct block *block;
+{
+  register struct symbol *sym = lookup_symbol (name, block, STRUCT_NAMESPACE);
+  if (sym == 0)
+    error ("No union type named %s.", name);
+  if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_UNION)
+    error ("This context has struct or enum %s, not a union.", name);
+  return SYMBOL_TYPE (sym);
+}
+
+/* Lookup an enum type named "enum NAME",
+   visible in lexical block BLOCK.  */
+
+struct type *
+lookup_enum (name, block)
+     char *name;
+     struct block *block;
+{
+  register struct symbol *sym = lookup_symbol (name, block, STRUCT_NAMESPACE);
+  if (sym == 0)
+    error ("No enum type named %s.", name);
+  if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_ENUM)
+    error ("This context has struct or union %s, not an enum.", name);
+  return SYMBOL_TYPE (sym);
+}
+
+/* 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.  */
+
+struct type *
+lookup_pointer_type (type)
+     struct type *type;
+{
+  register struct type *ptype = TYPE_POINTER_TYPE (type);
+  if (ptype) return ptype;
+
+  /* This is the first time anyone wanted a pointer to a TYPE.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    ptype  = (struct type *) xmalloc (sizeof (struct type));
+  else
+    ptype  = (struct type *) obstack_alloc (symbol_obstack,
+                                           sizeof (struct type));
+
+  bzero (ptype, sizeof (struct type));
+  TYPE_TARGET_TYPE (ptype) = type;
+  TYPE_POINTER_TYPE (type) = ptype;
+  /* New type is permanent if type pointed to is permanent.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    TYPE_FLAGS (ptype) |= TYPE_FLAG_PERM;
+  /* We assume the machine has only one representation for pointers!  */
+  TYPE_LENGTH (ptype) = sizeof (char *);
+  TYPE_CODE (ptype) = TYPE_CODE_PTR;
+  return ptype;
+}
+
+/* Given a type TYPE, return a type of functions that return that type.
+   May need to construct such a type if this is the first use.  */
+
+struct type *
+lookup_function_type (type)
+     struct type *type;
+{
+  register struct type *ptype = TYPE_FUNCTION_TYPE (type);
+  if (ptype) return ptype;
+
+  /* This is the first time anyone wanted a function returning a TYPE.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    ptype  = (struct type *) xmalloc (sizeof (struct type));
+  else
+    ptype  = (struct type *) obstack_alloc (symbol_obstack,
+                                           sizeof (struct type));
+
+  bzero (ptype, sizeof (struct type));
+  TYPE_TARGET_TYPE (ptype) = type;
+  TYPE_FUNCTION_TYPE (type) = ptype;
+  /* New type is permanent if type returned is permanent.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    TYPE_FLAGS (ptype) |= TYPE_FLAG_PERM;
+  TYPE_LENGTH (ptype) = 1;
+  TYPE_CODE (ptype) = TYPE_CODE_FUNC;
+  TYPE_NFIELDS (ptype) = 0;
+  return ptype;
+}
+\f
+/* Smash TYPE to be a type of pointers to TO_TYPE.
+   If TO_TYPE is not permanent and has no pointer-type yet,
+   record TYPE as its pointer-type.  */
+
+void
+smash_to_pointer_type (type, to_type)
+     struct type *type, *to_type;
+{
+  bzero (type, sizeof (struct type));
+  TYPE_TARGET_TYPE (type) = to_type;
+  /* We assume the machine has only one representation for pointers!  */
+  TYPE_LENGTH (type) = sizeof (char *);
+  TYPE_CODE (type) = TYPE_CODE_PTR;
+
+  if (TYPE_POINTER_TYPE (to_type) == 0
+      && !(TYPE_FLAGS (type) & TYPE_FLAG_PERM))
+    {
+      TYPE_POINTER_TYPE (to_type) = type;
+    }
+}
+
+/* Smash TYPE to be a type of functions returning TO_TYPE.
+   If TO_TYPE is not permanent and has no function-type yet,
+   record TYPE as its function-type.  */
+
+void
+smash_to_function_type (type, to_type)
+     struct type *type, *to_type;
+{
+  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_FUNCTION_TYPE (to_type) == 0
+      && !(TYPE_FLAGS (type) & TYPE_FLAG_PERM))
+    {
+      TYPE_FUNCTION_TYPE (to_type) = type;
+    }
+}
+\f
+static struct symbol *lookup_block_symbol ();
+
+/* Find the definition for a specified symbol name NAME
+   in namespace NAMESPACE, visible from lexical block BLOCK.
+   Returns the struct symbol pointer, or zero if no symbol is found.  */
+
+struct symbol *
+lookup_symbol (name, block, namespace)
+     char *name;
+     register struct block *block;
+     enum namespace namespace;
+{
+  register int i, n;
+  register struct symbol *sym;
+  register struct symtab *s;
+  struct blockvector *bv;
+
+  /* Search specified block and its superiors.  */
+
+  while (block != 0)
+    {
+      sym = lookup_block_symbol (block, name, namespace);
+      if (sym) return sym;
+      block = BLOCK_SUPERBLOCK (block);
+    }
+
+  /* Now search all symtabs' global blocks.  */
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      bv = BLOCKVECTOR (s);
+      block = BLOCKVECTOR_BLOCK (bv, 0);
+      sym = lookup_block_symbol (block, name, namespace);
+      if (sym) return sym;
+    }
+
+  /* Now search all symtabs' per-file blocks.
+     Not strictly correct, but more useful than an error.  */
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      bv = BLOCKVECTOR (s);
+      block = BLOCKVECTOR_BLOCK (bv, 1);
+      sym = lookup_block_symbol (block, name, namespace);
+      if (sym) return sym;
+    }
+  return 0;
+}
+
+/* Look for a symbol in block BLOCK using binary search.  */
+
+static struct symbol *
+lookup_block_symbol (block, name, namespace)
+     register struct block *block;
+     char *name;
+     enum namespace namespace;
+{
+  register int bot, top, inc;
+  register struct symbol *sym;
+
+  top = BLOCK_NSYMS (block);
+  bot = 0;
+
+  /* First, advance BOT to not far before
+     the first symbol whose name is NAME.  */
+
+  while (1)
+    {
+      inc = (top - bot + 1);
+      /* No need to keep binary searching for the last few bits worth.  */
+      if (inc < 7)
+       break;
+      inc >>= 1;
+      sym = BLOCK_SYM (block, bot + inc);
+      if (strcmp (SYMBOL_NAME (sym), name) < 0)
+       bot += inc;
+      else
+       top = bot + inc;
+    }
+
+  /* Now scan forward until we run out of symbols,
+     find one whose name is greater than NAME,
+     or find one we want.
+     If there is more than one symbol with the right name and namespace,
+     we return the first one.  dbxread.c is careful to make sure
+     that if one is a register then it comes first.  */
+
+  top = BLOCK_NSYMS (block);
+  while (bot < top)
+    {
+      sym = BLOCK_SYM (block, bot);
+      inc = strcmp (SYMBOL_NAME (sym), name);
+      if (inc == 0 && SYMBOL_NAMESPACE (sym) == namespace)
+       return sym;
+      if (inc > 0)
+       return 0;
+      bot++;
+    }
+  return 0;
+}
+\f
+/* Return the symbol for the function which contains a specified
+   lexical block, described by a struct block BL.  */
+
+struct symbol *
+block_function (bl)
+     struct block *bl;
+{
+  while (BLOCK_FUNCTION (bl) == 0 && BLOCK_SUPERBLOCK (bl) != 0)
+    bl = BLOCK_SUPERBLOCK (bl);
+
+  return BLOCK_FUNCTION (bl);
+}
+
+/* Subroutine of find_pc_line */
+
+static struct symtab *
+find_pc_symtab (pc)
+     register CORE_ADDR pc;
+{
+  register struct block *b;
+  struct blockvector *bv;
+  register struct symtab *s;
+
+  /* Search all symtabs for one whose file contains our pc */
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      bv = BLOCKVECTOR (s);
+      b = BLOCKVECTOR_BLOCK (bv, 0);
+      if (BLOCK_START (b) <= pc
+         && BLOCK_END (b) > pc)
+       break;
+    }
+
+  return s;
+}
+
+/* Find the source file and line number for a given PC value.
+   Return a structure containing a symtab pointer, a line number,
+   and a pc range for the entire source line.
+   The value's .pc field is NOT the specified pc.
+   NOTCURRENT nonzero means, if specified pc is on a line boundary,
+   use the line that ends there.  Otherwise, in that case, the line
+   that begins there is used.  */
+
+struct symtab_and_line
+find_pc_line (pc, notcurrent)
+     CORE_ADDR pc;
+     int notcurrent;
+{
+  struct symtab *s;
+  register struct linetable *l;
+  register int len;
+  register int i, item;
+  int line;
+  struct symtab_and_line value;
+  struct blockvector *bv;
+
+  /* Info on best line seen so far, and where it starts, and its file.  */
+
+  int best_line = 0;
+  CORE_ADDR best_pc = 0;
+  CORE_ADDR best_end = 0;
+  struct symtab *best_symtab = 0;
+
+  /* Store here the first line number
+     of a file which contains the line at the smallest pc after PC.
+     If we don't find a line whose range contains PC,
+     we will use a line one less than this,
+     with a range from the start of that file to the first line's pc.  */
+  int alt_line = 0;
+  CORE_ADDR alt_pc = 0;
+  struct symtab *alt_symtab = 0;
+
+  /* Info on best line seen in this file.  */
+
+  int prev_line;
+  CORE_ADDR prev_pc;
+
+  /* Info on first line of this file.  */
+
+  int first_line;
+  CORE_ADDR first_pc;
+
+  /* If this pc is not from the current frame,
+     it is the address of the end of a call instruction.
+     Quite likely that is the start of the following statement.
+     But what we want is the statement containing the instruction.
+     Fudge the pc to make sure we get that.  */
+
+  if (notcurrent) pc -= 1;
+
+  s = find_pc_symtab (pc);
+  if (s == 0)
+    {
+      value.symtab = 0;
+      value.line = 0;
+      value.pc = pc;
+      return value;
+    }
+
+  bv = BLOCKVECTOR (s);
+
+  /* Look at all the symtabs that share this blockvector.
+     They all have the same apriori range, that we found was right;
+     but they have different line tables.  */
+
+  for (; s && BLOCKVECTOR (s) == bv; s = s->next)
+    {
+      /* Find the best line in this symtab.  */
+      l = LINETABLE (s);
+      len = l->nitems;
+      prev_line = -1;
+      first_line = -1;
+      for (i = 0; i < len; i++)
+       {
+         item = l->item[i];
+         if (item < 0)
+           line = - item - 1;
+         else
+           {
+             line++;
+             if (first_line < 0)
+               {
+                 first_line = line;
+                 first_pc = item;
+               }
+             /* Return the last line that did not start after PC.  */
+             if (pc >= item)
+               {
+                 prev_line = line;
+                 prev_pc = item;
+               }
+             else
+               break;
+           }
+       }
+
+      /* Is this file's best line closer than the best in the other files?
+        If so, record this file, and its best line, as best so far.  */
+      if (prev_line >= 0 && prev_pc > best_pc)
+       {
+         best_pc = prev_pc;
+         best_line = prev_line;
+         best_symtab = s;
+         if (i < len)
+           best_end = item;
+         else
+           best_end = 0;
+       }
+      /* Is this file's first line closer than the first lines of other files?
+        If so, record this file, and its first line, as best alternate.  */
+      if (first_line >= 0 && first_pc > pc
+         && (alt_pc == 0 || first_pc < alt_pc))
+       {
+         alt_pc = first_pc;
+         alt_line = first_line;
+         alt_symtab = s;
+       }
+    }
+  if (best_symtab == 0)
+    {
+      value.symtab = alt_symtab;
+      value.line = alt_line - 1;
+      value.pc = BLOCK_END (BLOCKVECTOR_BLOCK (bv, 0));
+      value.end = alt_pc;
+    }
+  else
+    {
+      value.symtab = best_symtab;
+      value.line = best_line;
+      value.pc = best_pc;
+      value.end = (best_end ? best_end
+                  : (alt_pc ? alt_pc
+                     : BLOCK_END (BLOCKVECTOR_BLOCK (bv, 0))));
+    }
+  return value;
+}
+
+/* Find the range of pc values in a line.
+   Store the starting pc of the line into *STARTPTR
+   and the ending pc (start of next line) into *ENDPTR.
+   Returns 1 to indicate success.
+   Returns 0 if could not find the specified line.  */
+
+int
+find_line_pc_range (symtab, thisline, startptr, endptr)
+     struct symtab *symtab;
+     int thisline;
+     CORE_ADDR *startptr, *endptr;
+{
+  register struct linetable *l;
+  register int i, line, item;
+  int len;
+  register CORE_ADDR prev_pc;
+  CORE_ADDR last_pc;
+
+  if (symtab == 0)
+    return 0;
+
+  l = LINETABLE (symtab);
+  len = l->nitems;
+  prev_pc = -1;
+  for (i = 0; i < len; i++)
+    {
+      item = l->item[i];
+      if (item < 0)
+       line = - item - 1;
+      else
+       {
+         line++;
+         /* As soon as we find a line following the specified one
+            we know the end pc and can return.  */
+         if (line > thisline)
+           {
+             /* If we have not seen an entry for the specified line,
+                assume that means the specified line has zero bytes.  */
+             *startptr = prev_pc == -1 ? item : prev_pc;
+             *endptr = item;
+             return 1;
+           }
+         /* If we see an entry for the specified line,
+            it gives the beginning.  */
+         if (line == thisline)
+           prev_pc = item;
+         last_pc = item;
+       }
+    }
+  if (prev_pc != -1)
+    {
+      /* If we found the specified line but no later line, it's file's last.
+        Its range is from line's pc to file's end pc.  */
+      *startptr = last_pc;
+      *endptr = BLOCK_END (BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), 0));
+      return 1;
+    }
+
+  return 0;
+}
+
+/* Find the PC value for a given source file and line number.
+   Returns zero for invalid line number.
+   The source file is specified with a struct symtab.  */
+
+CORE_ADDR
+find_line_pc (symtab, line)
+     struct symtab *symtab;
+     int line;
+{
+  register struct linetable *l;
+  register int len;
+  register int i;
+  register int item;
+  register int nextline = -1;
+
+  if (line <= 0)
+    return 0;
+
+  l = LINETABLE (symtab);
+  len = l->nitems;
+  for (i = 0; i < len; i++)
+    {
+      item = l->item[i];
+      if (item < 0)
+       nextline = - item - 1;
+      else
+       {
+         nextline++;
+         if (line <= nextline)
+           return item;
+       }
+    }
+  return 0;
+}
+
+int
+find_pc_line_pc_range (pc, startptr, endptr)
+     CORE_ADDR pc;
+     CORE_ADDR *startptr, *endptr;
+{
+  struct symtab_and_line sal;
+  sal = find_pc_line (pc, 0);
+  *startptr = sal.pc;
+  *endptr = sal.end;
+  return sal.symtab != 0;
+}
+\f
+/* Parse a string that specifies a line number.
+   Pass the address of a char * variable; that variable will be
+   advanced over the characters actually parsed.
+
+   The string can be:
+
+   LINENUM -- that line number in current file.  PC returned is 0.
+   FILE:LINENUM -- that line in that file.  PC returned is 0.
+   FUNCTION -- line number of openbrace of that function.
+      PC returned is the start of the function.
+   FILE:FUNCTION -- likewise, but prefer functions in that file.
+   *EXPR -- line in which address EXPR appears.
+
+   FUNCTION may be an undebuggable function found in misc_function_vector.
+
+   If the argument FUNFIRSTLINE is nonzero, we want the first line
+   of real code inside a function when a function is specified.
+
+   DEFAULT_SYMTAB specifies the file to use if none is specified.
+   It defaults to current_source_symtab.
+   DEFAULT_LINE specifies the line number to use for relative
+   line numbers (that start with signs).  Defaults to current_source_line.
+
+   Note that it is possible to return zero for the symtab
+   if no file is validly specified.  Callers must check that.
+   Also, the line number returned may be invalid.  */
+
+struct symtab_and_line
+decode_line_1 (argptr, funfirstline, default_symtab, default_line)
+     char **argptr;
+     int funfirstline;
+     struct symtab *default_symtab;
+     int default_line;
+{
+  struct symtab_and_line value;
+  register char *p, *p1;
+  register struct symtab *s;
+  register struct symbol *sym;
+  register CORE_ADDR pc;
+  register int i;
+  char *copy;
+
+  /* Defaults have defaults.  */
+
+  if (default_symtab == 0)
+    {
+      default_symtab = current_source_symtab;
+      default_line = current_source_line;
+    }
+
+  /* See if arg is *PC */
+
+  if (**argptr == '*')
+    {
+      (*argptr)++;
+      pc = parse_and_eval_address_1 (argptr);
+      value = find_pc_line (pc, 0);
+      value.pc = pc;
+      return value;
+    }
+
+  /* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
+
+  s = 0;
+
+  for (p = *argptr; *p; p++)
+    {
+      if (p[0] == ':' || p[0] == ' ' || p[0] == '\t')
+       break;
+    }
+  while (p[0] == ' ' || p[0] == '\t') p++;
+
+  if (p[0] == ':')
+    {
+      /* Extract the file name.  */
+      p1 = p;
+      while (p != *argptr && p[-1] == ' ') --p;
+      copy = (char *) alloca (p - *argptr + 1);
+      bcopy (*argptr, copy, p - *argptr);
+      copy[p - *argptr] = 0;
+
+      /* Find that file's data.  */
+      s = lookup_symtab (copy);
+      if (s == 0)
+       {
+         if (symtab_list == 0)
+           error ("No symbol table is loaded.  Use the \"symbol-file\" command.");
+         error ("No source file named %s.", copy);
+       }
+
+      /* Discard the file name from the arg.  */
+      p = p1 + 1;
+      while (*p == ' ' || *p == '\t') p++;
+      *argptr = p;
+    }
+
+  /* S is specified file's symtab, or 0 if no file specified.
+     arg no longer contains the file name.  */
+
+  /* Check whether arg is all digits (and sign) */
+
+  p = *argptr;
+  if (*p == '-' || *p == '+') p++;
+  while (*p >= '0' && *p <= '9')
+    p++;
+
+  if (p != *argptr && (*p == 0 || *p == ' ' || *p == '\t' || *p == ','))
+    {
+      /* We found a token consisting of all digits -- at least one digit.  */
+      enum sign {none, plus, minus} sign = none;
+
+      if (**argptr == '+')
+       sign = plus, (*argptr)++;
+      else if (**argptr == '-')
+       sign = minus, (*argptr)++;
+      value.line = atoi (*argptr);
+      switch (sign)
+       {
+       case plus:
+         if (p == *argptr)
+           value.line = 5;
+         if (s == 0)
+           value.line = default_line + value.line;
+         break;
+       case minus:
+         if (p == *argptr)
+           value.line = 15;
+         if (s == 0)
+           value.line = default_line - value.line;
+         else
+           value.line = 1;
+         break;
+       }
+
+      while (*p == ' ' || *p == '\t') p++;
+      *argptr = p;
+      if (s == 0)
+       s = default_symtab;
+      value.symtab = s;
+      value.pc = 0;
+      return value;
+    }
+
+  /* Arg token is not digits => try it as a function name
+     Find the next token (everything up to end or next whitespace).  */
+  p = *argptr;
+  while (*p && *p != ' ' && *p != '\t' && *p != ',') p++;
+  copy = (char *) alloca (p - *argptr + 1);
+  bcopy (*argptr, copy, p - *argptr);
+  copy[p - *argptr] = 0;
+  while (*p == ' ' || *p == '\t') p++;
+  *argptr = p;
+
+  /* Look up that token as a function.
+     If file specified, use that file's per-file block to start with.  */
+
+  sym = lookup_symbol (copy, s ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 1) : 0,
+                      VAR_NAMESPACE);
+
+  if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+    {
+      /* Arg is the name of a function */
+      pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) + FUNCTION_START_OFFSET;
+      if (funfirstline)
+       SKIP_PROLOGUE (pc);
+      value = find_pc_line (pc, 0);
+      value.pc = (value.end && value.pc != pc) ? value.end : pc;
+      return value;
+    }
+
+  if (sym)
+    error ("%s is not a function.", copy);
+
+  for (i = 0; i < misc_function_count; i++)
+    if (!strcmp (misc_function_vector[i].name, copy))
+      {
+       value.symtab = 0;
+       value.line = 0;
+       value.pc = misc_function_vector[i].address + FUNCTION_START_OFFSET;
+       if (funfirstline)
+         SKIP_PROLOGUE (value.pc);
+       return value;
+      }
+
+  if (symtab_list == 0)
+    error ("No symbol table is loaded.  Use the \"symbol-file\" command.");
+  error ("Function %s not defined.", copy);
+}
+
+struct symtab_and_line
+decode_line_spec (string, funfirstline)
+     char *string;
+     int funfirstline;
+{
+  struct symtab_and_line sal;
+  if (string == 0)
+    error ("Empty line specification.");
+  sal = decode_line_1 (&string, funfirstline,
+                      current_source_symtab, current_source_line);
+  if (*string)
+    error ("Junk at end of line specification: %s", string);
+  return sal;
+}
+\f
+static void
+sources_info ()
+{
+  register struct symtab *s;
+  register int column = 0;
+
+  if (symtab_list == 0)
+    {
+      printf ("No symbol table is loaded.\n");
+      return;
+    }
+  printf ("Source files for which symbol table is known:\n");
+  for (s = symtab_list; s; s = s->next)
+    {
+      if (column != 0 && column + strlen (s->filename) >= 70)
+       {
+         printf ("\n");
+         column = 0;
+       }
+      else if (column != 0)
+       {
+         printf (" ");
+         column++;
+       }
+      printf ("%s", s->filename);
+      column += strlen (s->filename);
+      if (s->next)
+       {
+         printf (",");
+         column++;
+       }
+    }
+  printf ("\n");
+}
+
+/* List all symbols (if REGEXP is 0) or all symbols matching REGEXP.
+   If CLASS is zero, list all symbols except functions and type names.
+   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);         \
+      read_line (); } }
+
+static void
+list_symbols (regexp, class)
+     char *regexp;
+     int class;
+{
+  register struct symtab *s;
+  register struct blockvector *bv;
+  struct blockvector *prev_bv = 0;
+  register struct block *b;
+  register int i, j;
+  register struct symbol *sym;
+  char *val = 0;
+  int found_in_file;
+  static char *classnames[]
+    = {"variable", "function", "type"};
+  int print_count = 0;
+#ifdef REGCMP
+  extern char *regcmp(), *regex(), *loc1;
+#endif
+
+  if (regexp) {
+#ifdef REGCMP
+    val = regcmp(regexp, (char *)0);
+    if (val == 0)
+      error ("Invalid regexp: %s", regexp);
+#else
+    if (val = (char *) re_comp (regexp))
+      error ("Invalid regexp: %s", val);
+#endif
+  }
+
+  printf (regexp
+         ? "All %ss matching regular expression \"%s\":\n"
+         : "All defined %ss:\n",
+         classnames[class],
+         regexp);
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      found_in_file = 0;
+      bv = BLOCKVECTOR (s);
+      /* Often many files share a blockvector.
+        Scan each blockvector only once so that
+        we don't get every symbol many times.
+        It happens that the first symtab in the list
+        for any given blockvector is the main file.  */
+      if (bv != prev_bv)
+       for (i = 0; i < 2; i++)
+         {
+           b = BLOCKVECTOR_BLOCK (bv, i);
+           for (j = 0; j < BLOCK_NSYMS (b); j++)
+             {
+               QUIT;
+               sym = BLOCK_SYM (b, j);
+               if (regexp) {
+#ifdef REGCMP
+                 if (!regex(val, SYMBOL_NAME (sym)))
+                   continue;
+#else
+                 if (!re_exec (SYMBOL_NAME (sym)))
+                   continue;
+#endif
+               }
+               if ((class == 0 && SYMBOL_CLASS (sym) != LOC_TYPEDEF
+                        && SYMBOL_CLASS (sym) != LOC_BLOCK)
+                       || (class == 1 && SYMBOL_CLASS (sym) == LOC_BLOCK)
+                       || (class == 2 && SYMBOL_CLASS (sym) == LOC_TYPEDEF))
+                 {
+                   if (!found_in_file)
+                     {
+                       printf ("\nFile %s:\n", s->filename);
+                       print_count += 2;
+                     }
+                   found_in_file = 1;
+                   MORE;
+                   if (class != 2 && i == 1)
+                     printf ("static ");
+                   if (class == 2
+                       && SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE)
+                     printf ("typedef ");
+
+                   type_print (SYMBOL_TYPE (sym),
+                               (SYMBOL_CLASS (sym) == LOC_TYPEDEF
+                                ? "" : SYMBOL_NAME (sym)),
+                               stdout, 0);
+                   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));
+                   printf (";\n");
+                 }
+             }
+         }
+      prev_bv = bv;
+    }
+#ifdef REGCMP
+    if (val)
+      (void)free(val);
+#endif
+}
+
+static void
+variables_info (regexp)
+     char *regexp;
+{
+  list_symbols (regexp, 0);
+}
+
+static void
+functions_info (regexp)
+     char *regexp;
+{
+  list_symbols (regexp, 1);
+}
+
+static void
+types_info (regexp)
+     char *regexp;
+{
+  list_symbols (regexp, 2);
+}
+\f
+/* Initialize the standard C scalar types.  */
+
+static
+struct type *
+init_type (code, length, uns, name)
+     enum type_code code;
+     int length, uns;
+     char *name;
+{
+  register struct type *type;
+
+  type = (struct type *) xmalloc (sizeof (struct type));
+  bzero (type, sizeof *type);
+  TYPE_CODE (type) = code;
+  TYPE_LENGTH (type) = length;
+  TYPE_FLAGS (type) = uns ? TYPE_FLAG_UNSIGNED : 0;
+  TYPE_FLAGS (type) |= TYPE_FLAG_PERM;
+  TYPE_NFIELDS (type) = 0;
+  TYPE_NAME (type) = name;
+
+  return type;
+}
+
+static
+initialize ()
+{
+  add_info ("variables", variables_info,
+           "All global and static variable names, or those matching REGEXP.");
+  add_info ("functions", functions_info,
+           "All function names, or those matching REGEXP.");
+  add_info ("types", types_info,
+           "All types names, or those matching REGEXP.");
+  add_info ("sources", sources_info,
+           "Source files in the program.");
+
+  obstack_init (symbol_obstack);
+
+  builtin_type_void = init_type (TYPE_CODE_VOID, 0, 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");
+
+  builtin_type_char = init_type (TYPE_CODE_INT, sizeof (char), 0, "char");
+  builtin_type_short = init_type (TYPE_CODE_INT, sizeof (short), 0, "short");
+  builtin_type_long = init_type (TYPE_CODE_INT, sizeof (long), 0, "long");
+  builtin_type_int = init_type (TYPE_CODE_INT, sizeof (int), 0, "int");
+
+  builtin_type_unsigned_char = init_type (TYPE_CODE_INT, sizeof (char), 1, "unsigned char");
+  builtin_type_unsigned_short = init_type (TYPE_CODE_INT, sizeof (short), 1, "unsigned short");
+  builtin_type_unsigned_long = init_type (TYPE_CODE_INT, sizeof (long), 1, "unsigned long");
+  builtin_type_unsigned_int = init_type (TYPE_CODE_INT, sizeof (int), 1, "unsigned int");
+}
+
+END_FILE
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d29 4
+d933 1
+a933 1
+  char *val;
+d938 3
+d942 6
+a947 1
+  if (regexp)
+d950 2
+d976 10
+a985 2
+               if ((regexp == 0 || re_exec (SYMBOL_NAME (sym)))
+                   && ((class == 0 && SYMBOL_CLASS (sym) != LOC_TYPEDEF
+d988 1
+a988 1
+                       || (class == 2 && SYMBOL_CLASS (sym) == LOC_TYPEDEF)))
+d1019 4
+@
diff --git a/gdb/RCS/utils.c,v b/gdb/RCS/utils.c,v
new file mode 100644 (file)
index 0000000..3f7a836
--- /dev/null
@@ -0,0 +1,461 @@
+head     1.2;
+access   ;
+symbols  RMS-has:1.2;
+locks    ; strict;
+comment  @ * @;
+
+
+1.2
+date     88.01.26.05.11.12;  author gnu;  state Exp;
+branches ;
+next     1.1;
+
+1.1
+date     88.01.21.05.11.11;  author gnu;  state Exp;
+branches ;
+next     ;
+
+
+desc
+@From RMS's development sources on wheaties, 20Jan88
+@
+
+
+1.2
+log
+@Avoid using TIOCFLUSH if it is not defined.
+@
+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 <stdio.h>
+#include <sys/ioctl.h>
+#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;
+\f
+/* 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);
+}
+\f
+/* 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 TIOCFLUSH
+  ioctl (fileno (stdout), TIOCFLUSH, 0);
+#endif
+  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");
+    }
+}
+\f
+/* 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;
+    }
+}
+\f
+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);
+    }
+}
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d194 1
+d196 1
+@
diff --git a/gdb/README b/gdb/README
new file mode 100644 (file)
index 0000000..6e985de
--- /dev/null
@@ -0,0 +1,29 @@
+This is GDB, a source-level debugger intended for GNU,
+presently running under un*x.
+
+Before compiling GDB, you must set three files according to
+the kind of machine you are running on.
+
+param.h must be set up to #include an m- file for the machine.
+The m- files written so far are m-vax.h, m-sun2.h and m-sun3.h.
+(I believe that it is the operating system version and not
+the cpu type which determines which of the two is right on a Sun.)
+This file contains macro definitions that express information
+about the machine's registers, stack frame format and instructions.
+
+initialize.h must be set up to #include an m-...init.h file.
+There are two of them written: m-vaxinit.h and m-suninit.h.
+This file defines one macro, which says how to round up from the
+address of the end of the text of one .o file to the beginning of
+the text of the next .o file.
+
+pinsn.c must be set up to include the instruction printer for
+your cpu type.  The two printers that exist are vax-pinsn.c
+and m68k-pinsn.c.
+
+`Makefile' must be changed to say `OBSTACK = obstack.o' instead of
+`OBSTACK=-lobstack' (unless you want to install obstack.o as
+/lib/libobstack.a).
+
+Once these files are set up, just `make' will do everything,
+producing an executable `gdb' in this directory.
diff --git a/gdb/TAGS b/gdb/TAGS
new file mode 100644 (file)
index 0000000..e01cba9
--- /dev/null
+++ b/gdb/TAGS
@@ -0,0 +1,852 @@
+\f
+blockframe.c,436
+block_for_pc \7f221,5337
+block_innermost_frame \7f308,7200
+find_pc_function \7f276,6473
+find_pc_misc_function \7f290,6806
+get_current_block \7f182,4485
+get_current_frame \7f47,1553
+get_frame_block \7f172,4336
+get_frame_function \7f208,5053
+get_frame_info \7f90,2661
+get_frame_pc \7f150,3800
+get_frame_saved_regs \7f161,3986
+get_pc_function_start \7f188,4557
+get_prev_frame \7f66,1893
+get_prev_frame_info \7f128,3455
+initialize \7f329,7603
+set_current_frame \7f56,1705
+\f
+breakpoint.c,1102
+#define ALL_BREAKPOINTS(\7f71,2545
+break_command \7f604,14937
+break_command_1 \7f528,13121
+breakpoint_1 \7f360,9438
+breakpoint_auto_delete \7f687,16916
+breakpoint_here_p \7f288,7887
+breakpoint_stop_status \7f308,8410
+breakpoints_info \7f409,10520
+check_duplicates \7f443,11290
+clear_breakpoint_commands \7f218,6186
+clear_breakpoints \7f757,18298
+clear_command \7f620,15179
+clear_momentary_breakpoints \7f513,12821
+commands_command \7f154,4443
+condition_command \7f109,3533
+delete_breakpoint \7f704,17221
+delete_command \7f733,17741
+disable_breakpoint \7f873,20658
+disable_command \7f882,20791
+do_breakpoint_commands \7f200,5626
+enable_breakpoint \7f857,20419
+enable_command \7f866,20550
+enable_delete_breakpoint \7f910,21276
+enable_delete_command \7f919,21413
+enable_once_breakpoint \7f894,21020
+enable_once_command \7f903,21158
+ignore_command \7f797,19190
+initialize \7f933,21666
+insert_breakpoints \7f230,6503
+map_breakpoint_numbers \7f822,19738
+mark_breakpoints_out \7f275,7576
+remove_breakpoints \7f251,7042
+set_default_breakpoint \7f426,10820
+set_ignore_count \7f767,18523
+set_momentary_breakpoint \7f501,12597
+set_raw_breakpoint \7f464,11810
+tbreak_command \7f612,15057
+\f
+command.c,151
+add_alias_cmd \7f141,6077
+add_cmd \7f116,5529
+add_prefix_cmd \7f177,7140
+delete_cmd \7f198,7681
+help_cmd \7f230,8515
+lookup_cmd \7f336,11651
+savestring \7f446,13891
+\f
+core.c,397
+#define N_DATADDR(\7f41,1348
+#define N_TXTADDR(\7f37,1278
+close_exec_file \7f268,7417
+core_file_command \7f104,2838
+exec_file_command \7f221,6183
+files_info \7f330,8673
+get_exec_file \7f315,8446
+have_core_file_p \7f324,8612
+initialize \7f548,13957
+myread \7f505,13219
+read_memory \7f373,9666
+register_addr \7f531,13685
+reopen_exec_file \7f275,7501
+validate_files \7f291,7907
+write_memory \7f389,10073
+xfer_core_file \7f400,10338
+\f
+dbxread.c,1108
+add_new_header_file \7f346,10622
+add_old_header_file \7f317,9604
+add_symbol_to_list \7f496,14905
+add_this_object_header_file \7f297,8977
+compare_misc_functions \7f931,26566
+compare_symbols \7f1000,28016
+condense_misc_bunches \7f957,27070
+dbx_alloc_type \7f454,13833
+dbx_lookup_type \7f404,12394
+define_symbol \7f1516,42011
+discard_misc_bunches \7f944,26878
+end_symtab \7f756,22240
+explicit_lookup_type \7f475,14373
+finish_block \7f512,15299
+free_header_files \7f273,8395
+get_sym_file \7f1174,32423
+hash_symsegs \7f1343,36983
+hashname \7f1318,36533
+init_header_files \7f260,8046
+init_misc_functions \7f903,25961
+initialize \7f2078,57588
+make_blockvector \7f590,17428
+new_object_header_files \7f286,8705
+next_symbol_text \7f1309,36368
+pop_subfile \7f861,25120
+process_one_symbol \7f1374,37801
+push_subfile \7f847,24770
+read_dbx_symtab \7f1186,32790
+read_enum_type \7f1892,52804
+read_number \7f2041,57023
+read_range_type \7f1962,54881
+read_struct_type \7f1809,50421
+read_type \7f1685,47313
+read_type_number \7f1658,46658
+record_line \7f627,18511
+record_misc_function \7f911,26075
+sort_syms \7f1012,28407
+start_subfile \7f699,20484
+start_symtab \7f662,19485
+symbol_file_command \7f1036,28951
+\f
+environ.c,213
+environ_vector \7f164,6337
+free_environ \7f118,5334
+get_in_environ \7f173,6472
+init_environ \7f134,5661
+make_environ \7f103,5036
+#define max(\7f96,4912
+#define min(\7f95,4870
+set_in_environ \7f192,6807
+unset_in_environ \7f232,7561
+\f
+eval.c,309
+evaluate_expression \7f95,2716
+evaluate_subexp \7f114,3104
+evaluate_subexp_for_address \7f440,13032
+evaluate_subexp_for_sizeof \7f509,14789
+evaluate_subexp_with_coercion \7f477,13979
+evaluate_type \7f106,2961
+initialize \7f550,15888
+parse_and_eval \7f64,1977
+parse_and_eval_address \7f33,1188
+parse_and_eval_address_1 \7f50,1650
+\f
+expprint.c,49
+print_expression \7f88,3265
+print_subexp \7f102,3660
+\f
+expread.tab.c,358
+copy_name \7f538,12121
+end_arglist \7f125,2565
+free_funcalls \7f139,2867
+length_of_subexp \7f572,13025
+parse_c_1 \7f751,17140
+parse_c_expression \7f790,18194
+parse_number \7f217,5038
+prefixify_expression \7f552,12457
+prefixify_subexp \7f644,14362
+start_arglist \7f111,2206
+write_exp_elt \7f156,3206
+write_exp_string \7f173,3660
+yyerror \7f529,11966
+yylex \7f315,7081
+yyparse(\7f985,25972
+\f
+findvar.c,309
+find_saved_register \7f38,1432
+initialize \7f386,10456
+locate_var_value \7f334,9235
+read_register \7f165,4621
+read_register_bytes \7f140,4050
+read_relative_register_raw_bytes \7f68,2095
+read_var_value \7f202,5600
+supply_register \7f190,5277
+value_of_register \7f102,2842
+write_register \7f175,4862
+write_register_bytes \7f151,4328
+\f
+firstfile.c,89
+initialize_all_files \7f128,6009
+initialize_dummy_1 \7f140,6338
+initialize_dummy_2 \7f148,6497
+\f
+infcmd.c,550
+cont_command \7f165,3979
+environment_info \7f479,11280
+finish_command \7f397,9291
+have_inferior_p \7f106,2907
+initialize \7f682,15823
+jump_command \7f269,6035
+next_command \7f202,4695
+nexti_command \7f216,4897
+program_info \7f457,10675
+read_memory_integer \7f542,12697
+read_pc \7f575,13293
+registers_info \7f589,13488
+run_command \7f121,3120
+run_stack_dummy \7f355,8179
+set_args_command \7f112,2972
+set_environment_command \7f499,11682
+signal_command \7f314,7007
+step_1 \7f222,4974
+step_command \7f194,4543
+stepi_command \7f210,4820
+unset_environment_command \7f531,12458
+write_pc \7f580,13357
+\f
+inflow.c,551
+create_inferior \7f187,5073
+fetch_inferior_registers \7f271,6793
+fetch_inferior_registers \7f317,8482
+inferior_died \7f244,6286
+initialize \7f483,13062
+kill_command \7f226,5974
+kill_inferior \7f235,6161
+read_inferior_memory \7f388,10475
+resume \7f258,6596
+store_inferior_registers \7f294,7707
+store_inferior_registers \7f343,9249
+term_status_command \7f165,4365
+terminal_inferior \7f87,2428
+terminal_init_inferior \7f71,2074
+terminal_ours \7f121,3326
+terminal_ours_1 \7f127,3383
+terminal_ours_for_output \7f111,3126
+try_writing_regs_command \7f457,12556
+write_inferior_memory \7f416,11420
+\f
+infrun.c,286
+clear_proceed_status \7f111,3347
+handle_command \7f728,21384
+initialize \7f848,24793
+insert_step_breakpoint \7f706,20807
+normal_stop \7f618,18254
+proceed \7f138,4172
+remove_step_breakpoint \7f718,21109
+signals_info \7f810,23832
+start_inferior \7f214,6079
+wait_for_inferior \7f242,7039
+writing_pc \7f202,5763
+\f
+kdb-start.c,14
+start \7f10,140
+\f
+lastfile.c,28
+initialize_last_file \7f4,144
+\f
+m68k-pinsn.c,361
+#define NEXTBYTE(\7f43,1554
+#define NEXTDOUBLE(\7f54,1819
+#define NEXTEXTEND(\7f57,1877
+#define NEXTLONG(\7f48,1671
+#define NEXTPACKED(\7f61,1995
+#define NEXTSINGLE(\7f51,1762
+#define NEXTWORD(\7f45,1602
+convert_from_68881 \7f713,16392
+convert_to_68881 \7f732,16806
+fetch_arg \7f504,12082
+print_base \7f693,15890
+print_indexed \7f603,13871
+print_insn \7f71,2389
+print_insn_arg \7f163,4738
+\f
+main.c,841
+add_com \7f487,11896
+add_com_alias \7f499,12123
+add_info \7f455,11186
+add_info_alias \7f466,11372
+cd_command \7f885,24375
+command_loop \7f288,7462
+copying_info \7f628,14816
+define_command \7f545,12933
+do_nothing \7f281,7362
+document_command \7f583,13895
+dont_repeat \7f323,8255
+dump_me_command \7f961,25608
+echo_command \7f935,25224
+error_no_arg \7f509,12321
+execute_command \7f245,6496
+free_command_lines \7f437,10877
+help_command \7f516,12415
+info_command \7f478,11700
+initialize_main \7f972,25764
+input_from_terminal_p \7f869,24072
+main \7f81,2147
+print_gdb_version \7f800,22767
+pwd_command \7f875,24143
+quit_command \7f856,23880
+read_command_lines \7f386,9603
+read_line \7f334,8514
+return_to_top_level \7f71,1965
+set_prompt_command \7f818,23215
+source_cleanup \7f904,24752
+source_command \7f912,24854
+stop_sig \7f307,7915
+validate_comname \7f524,12566
+version_info \7f810,23117
+warranty_info \7f770,21356
+\f
+obstack.c,77
+_obstack_begin \7f101,4993
+_obstack_free \7f148,6461
+_obstack_newchunk \7f121,5631
+\f
+pinsn.c,0
+\f
+printcmd.c,585
+address_info \7f385,9015
+clear_displays \7f661,15183
+decode_format \7f70,2061
+display_command \7f606,14214
+display_info \7f769,17310
+do_displays \7f731,16450
+do_examine \7f231,5522
+free_display \7f649,14965
+initialize \7f888,20497
+output_command \7f346,8219
+print_address \7f208,4990
+print_command \7f306,7398
+print_formatted \7f109,2860
+print_frame_args \7f810,18392
+print_frame_nameless_args \7f870,20125
+print_variable_value \7f795,17951
+ptype_command \7f525,12189
+set_command \7f374,8765
+set_next_address \7f193,4626
+undisplay_command \7f677,15445
+validate_format \7f291,6959
+whatis_command \7f500,11716
+x_command \7f452,10410
+\f
+source.c,249
+directories_info \7f53,1637
+directory_command \7f79,2168
+find_source_lines \7f264,6263
+init_source_path \7f59,1735
+initialize \7f535,13376
+line_info \7f490,12220
+list_command \7f363,8569
+openp \7f186,4596
+print_source_lines \7f303,7291
+select_source_symtab \7f250,5960
+\f
+stack.c,502
+args_info \7f350,8833
+backtrace_command \7f232,6280
+down_command \7f498,12939
+find_relative_frame \7f391,10010
+frame_command \7f444,11623
+frame_info \7f149,4137
+get_selected_block \7f371,9306
+initialize \7f542,13968
+locals_info \7f312,8132
+print_block_frame_locals \7f257,6820
+print_frame_arg_vars \7f318,8214
+print_frame_info \7f70,2167
+print_frame_local_vars \7f291,7614
+print_sel_frame \7f131,3689
+print_selected_frame \7f140,3894
+print_stack_frame \7f57,1964
+return_command \7f516,13439
+select_frame \7f359,9033
+up_command \7f477,12347
+\f
+standalone.c,1165
+_exit \7f436,8533
+_flsbuf \7f326,6852
+access \7f76,1743
+chdir \7f62,1588
+close \7f164,4224
+core_file_command \7f340,7028
+exec_file_command \7f337,7003
+execle \7f433,8519
+exit \7f81,1771
+fault \7f514,9963
+fclose \7f189,4597
+fdopen \7f183,4539
+fflush \7f331,6910
+fgetc \7f247,5466
+fopen \7f175,4414
+fprintf \7f298,6263
+fputc \7f314,6593
+fread \7f229,5154
+fstat \7f195,4647
+fwrite \7f305,6422
+get_exec_file \7f344,7060
+getpid \7f54,1543
+getrlimit \7f474,9005
+getwd \7f66,1608
+have_core_file_p \7f350,7176
+initialize \7f585,11686
+ioctl \7f45,1478
+kill \7f51,1531
+kill_command \7f355,7213
+lseek \7f266,5714
+malloc_warning \7f441,8575
+myread \7f208,4831
+open \7f129,3606
+printf \7f291,6110
+ptrace \7f427,8490
+read_inferior_register \7f372,7361
+read_memory \7f375,7391
+read_register \7f397,7764
+restore_gdb \7f528,10282
+resume \7f490,9429
+save_frame_pointer \7f502,9633
+save_registers \7f540,10627
+sbrk \7f451,8691
+setpgrp \7f430,8504
+int (* signal \7f48,1506
+sigsetmask \7f59,1570
+int kdb_stack_beg[STACK_SIZE / sizeof \7f581,11613
+terminal_inferior \7f360,7254
+terminal_init_inferior \7f366,7300
+terminal_ours \7f363,7279
+ulimit \7f463,8913
+vfork \7f417,8200
+vlimit \7f469,8955
+wait \7f554,10975
+write_inferior_register \7f369,7330
+write_memory \7f385,7564
+write_register \7f406,7933
+\f
+stuff.c,70
+err \7f162,5253
+find_symbol \7f141,4686
+get_offset \7f97,3038
+main \7f32,1184
+\f
+symmisc.c,473
+#define CORE_RELOCATE(\7f158,4817
+#define RELOCATE(\7f148,4378
+#define TEXT_RELOCATE(\7f162,4972
+#define UNRELOCATE(\7f152,4573
+block_depth \7f499,13854
+free_all_symtabs \7f38,1310
+free_symtab \7f92,2701
+free_symtab_block \7f70,1994
+initialize \7f508,13995
+print_symbol \7f413,11786
+print_symtabs \7f353,10199
+read_symsegs \7f320,9451
+relocate_block \7f243,7195
+relocate_blockvector \7f231,6886
+relocate_symbol \7f268,7855
+relocate_symtab \7f182,5675
+relocate_type \7f296,8833
+relocate_typevector \7f218,6602
+\f
+symtab.c,716
+block_function \7f383,10928
+decode_line_1 \7f694,18782
+decode_line_spec \7f853,22739
+find_line_pc \7f624,16888
+find_line_pc_range \7f565,15457
+find_pc_line \7f425,11975
+find_pc_line_pc_range \7f655,17363
+find_pc_symtab \7f395,11161
+functions_info \7f995,26000
+init_type \7f1012,26230
+initialize \7f1032,26680
+list_symbols \7f916,24143
+lookup_block_symbol \7f330,9572
+lookup_enum \7f166,4758
+lookup_function_type \7f211,6260
+lookup_pointer_type \7f182,5269
+lookup_struct \7f134,3824
+lookup_symbol \7f285,8458
+lookup_symtab \7f58,1929
+lookup_typename \7f85,2559
+lookup_union \7f150,4293
+lookup_unsigned_typename \7f116,3346
+smash_to_function_type \7f262,7816
+smash_to_pointer_type \7f241,7206
+sources_info \7f868,23119
+types_info \7f1002,26088
+variables_info \7f988,25912
+\f
+test2.c,11
+main \7f6,86
+\f
+test3.c,25
+bar \7f12,123
+newfun \7f5,51
+\f
+testbit.c,11
+main \7f7,58
+\f
+testfun.c,44
+do_add \7f7,62
+do_float_add \7f13,104
+main \7f1,0
+\f
+testkill.c,11
+       main(\7f2,1
+\f
+testrec.c,20
+foo \7f6,24
+main \7f1,0
+\f
+testreg.c,22
+foo \7f19,341
+main \7f1,0
+\f
+testregs.c,23
+foo \7f2,11
+main \7f15,321
+\f
+utils.c,382
+concat \7f254,5912
+discard_cleanups \7f84,2483
+do_cleanups \7f68,2104
+error \7f213,5038
+fatal \7f228,5397
+free_current_contents \7f104,2893
+make_cleanup \7f48,1636
+parse_escape \7f323,7736
+perror_with_name \7f142,3676
+print_spaces \7f266,6154
+print_sys_errmsg \7f168,4235
+printchar \7f390,8781
+query \7f280,6518
+quit \7f191,4675
+request_quit \7f201,4799
+savestring \7f243,5745
+xmalloc \7f115,3106
+xrealloc \7f127,3326
+\f
+valarith.c,215
+initialize \7f352,8246
+value_add \7f31,1128
+value_binop \7f116,3276
+value_equal \7f257,5535
+value_less \7f301,6746
+value_lognot \7f342,7998
+value_neg \7f328,7619
+value_sub \7f70,2102
+value_subscript \7f105,2971
+value_zerop \7f233,5184
+\f
+valops.c,395
+call_function \7f388,10791
+initialize \7f594,16295
+push_bytes \7f314,9135
+push_word \7f294,8769
+value_addr \7f247,7400
+value_arg_coerce \7f354,9928
+value_arg_push \7f373,10344
+value_assign \7f85,2697
+value_at \7f68,2289
+value_cast \7f34,1302
+value_coerce_array \7f219,6610
+value_ind \7f274,8155
+value_of_variable \7f209,6404
+value_push \7f333,9476
+value_repeat \7f186,5819
+value_string \7f485,13581
+value_struct_elt \7f555,15503
+\f
+valprint.c,237
+initialize \7f533,13661
+set_maximum_command \7f525,13515
+type_print \7f272,7365
+type_print_1 \7f283,7591
+type_print_base \7f403,10889
+type_print_varspec_prefix \7f316,8617
+type_print_varspec_suffix \7f352,9476
+val_print \7f113,3308
+value_print \7f46,1539
+\f
+values.c,762
+access_value_history \7f212,5551
+allocate_repeat_value \7f83,2505
+allocate_value \7f59,1948
+clear_internalvars \7f371,9239
+clear_value_history \7f251,6511
+convenience_info \7f386,9475
+free_all_values \7f108,3143
+history_info \7f270,6920
+initialize \7f737,18259
+internalvar_name \7f361,9048
+lookup_internalvar \7f308,7852
+modify_field \7f602,14750
+record_latest_value \7f178,4634
+release_value \7f125,3410
+set_internalvar \7f351,8879
+set_internalvar_component \7f336,8485
+set_return_value \7f709,17666
+unpack_double \7f486,11851
+unpack_field_as_long \7f578,14176
+unpack_long \7f430,10615
+value_as_double \7f418,10252
+value_as_long \7f411,10132
+value_being_returned \7f688,17121
+value_copy \7f151,3834
+value_field \7f542,13135
+value_from_double \7f654,16089
+value_from_long \7f626,15329
+value_of_internalvar \7f327,8298
+\f
+vax-pinsn.c,44
+print_insn \7f42,1456
+print_insn_arg \7f86,2396
+\f
+version.c,0
+\f
+command.h,0
+\f
+defs.h,42
+#define max(\7f24,1043
+#define min(\7f23,1001
+\f
+environ.h,0
+\f
+expression.h,0
+\f
+frame.h,0
+\f
+inferior.h,0
+\f
+initialize.h,0
+\f
+m-isi-ov.h,852
+#define ABOUT_TO_RETURN(\7f136,4974
+#define FIX_CALL_DUMMY(\7f447,17543
+#define FRAME_ARGS_ADDRESS(\7f275,9997
+#define FRAME_CHAIN(\7f264,9636
+#define FRAME_CHAIN_COMBINE(\7f269,9825
+#define FRAME_CHAIN_VALID(\7f266,9706
+#define FRAME_FIND_SAVED_REGS(\7f305,11191
+#define FRAME_LOCALS_ADDRESS(\7f277,10040
+#define FRAME_NUM_ARGS(\7f282,10176
+#define FRAME_SAVED_PC(\7f273,9929
+#define INIT_STACK(\7f471,18339
+#define INVALID_FLOAT(\7f140,5108
+#define N_DATADDR(\7f120,4437
+#define N_TXTADDR(\7f125,4616
+#define REGISTER_BYTE(\7f194,7220
+#define REGISTER_CONVERTIBLE(\7f222,8151
+#define REGISTER_CONVERT_TO_RAW(\7f236,8614
+#define REGISTER_CONVERT_TO_VIRTUAL(\7f227,8318
+#define REGISTER_RAW_SIZE(\7f203,7555
+#define REGISTER_U_ADDR(\7f174,6379
+#define REGISTER_VIRTUAL_SIZE(\7f209,7811
+#define REGISTER_VIRTUAL_TYPE(\7f245,8895
+#define SAVED_PC_AFTER_CALL(\7f97,3881
+#define SKIP_PROLOGUE(\7f77,3210
+\f
+m-sun2.h,824
+#define ABOUT_TO_RETURN(\7f79,2505
+#define FIX_CALL_DUMMY(\7f344,12862
+#define FRAME_ARGS_ADDRESS(\7f196,6448
+#define FRAME_CHAIN(\7f185,6087
+#define FRAME_CHAIN_COMBINE(\7f190,6276
+#define FRAME_CHAIN_VALID(\7f187,6157
+#define FRAME_FIND_SAVED_REGS(\7f232,7817
+#define FRAME_LOCALS_ADDRESS(\7f198,6491
+#define FRAME_NUM_ARGS(\7f205,6746
+#define FRAME_NUM_ARGS(\7f208,6795
+#define FRAME_SAVED_PC(\7f194,6380
+#define INIT_STACK(\7f368,13658
+#define INVALID_FLOAT(\7f83,2639
+#define REGISTER_BYTE(\7f121,3997
+#define REGISTER_CONVERTIBLE(\7f144,4615
+#define REGISTER_CONVERT_TO_RAW(\7f154,4927
+#define REGISTER_CONVERT_TO_VIRTUAL(\7f149,4749
+#define REGISTER_RAW_SIZE(\7f126,4162
+#define REGISTER_U_ADDR(\7f166,5375
+#define REGISTER_VIRTUAL_SIZE(\7f131,4317
+#define REGISTER_VIRTUAL_TYPE(\7f159,5092
+#define SAVED_PC_AFTER_CALL(\7f51,1836
+#define SKIP_PROLOGUE(\7f38,1400
+\f
+m-sun3.h,790
+#define ABOUT_TO_RETURN(\7f78,2454
+#define FIX_CALL_DUMMY(\7f392,15189
+#define FRAME_ARGS_ADDRESS(\7f213,7102
+#define FRAME_CHAIN(\7f202,6741
+#define FRAME_CHAIN_COMBINE(\7f207,6930
+#define FRAME_CHAIN_VALID(\7f204,6811
+#define FRAME_FIND_SAVED_REGS(\7f249,8471
+#define FRAME_LOCALS_ADDRESS(\7f215,7145
+#define FRAME_NUM_ARGS(\7f222,7400
+#define FRAME_NUM_ARGS(\7f225,7449
+#define FRAME_SAVED_PC(\7f211,7034
+#define INIT_STACK(\7f416,15985
+#define INVALID_FLOAT(\7f82,2588
+#define REGISTER_BYTE(\7f123,4130
+#define REGISTER_CONVERTIBLE(\7f151,5061
+#define REGISTER_CONVERT_TO_RAW(\7f165,5524
+#define REGISTER_CONVERT_TO_VIRTUAL(\7f156,5228
+#define REGISTER_RAW_SIZE(\7f132,4465
+#define REGISTER_VIRTUAL_SIZE(\7f138,4721
+#define REGISTER_VIRTUAL_TYPE(\7f174,5805
+#define SAVED_PC_AFTER_CALL(\7f55,1929
+#define SKIP_PROLOGUE(\7f42,1493
+\f
+m-suninit.h,29
+#define FILEADDR_ROUND(\7f5,94
+\f
+m-vax.h,791
+#define ABOUT_TO_RETURN(\7f80,2551
+#define FIX_CALL_DUMMY(\7f294,10681
+#define FRAME_ARGS_ADDRESS(\7f199,6661
+#define FRAME_CHAIN(\7f185,6120
+#define FRAME_CHAIN_COMBINE(\7f190,6314
+#define FRAME_CHAIN_VALID(\7f187,6195
+#define FRAME_FIND_SAVED_REGS(\7f222,7517
+#define FRAME_LOCALS_ADDRESS(\7f204,6836
+#define FRAME_NUM_ARGS(\7f209,6972
+#define FRAME_SAVED_PC(\7f194,6418
+#define INIT_STACK(\7f317,11455
+#define INVALID_FLOAT(\7f84,2681
+#define REGISTER_BYTE(\7f127,4329
+#define REGISTER_CONVERTIBLE(\7f150,4942
+#define REGISTER_CONVERT_TO_RAW(\7f161,5257
+#define REGISTER_CONVERT_TO_VIRTUAL(\7f155,5076
+#define REGISTER_RAW_SIZE(\7f132,4491
+#define REGISTER_U_ADDR(\7f112,3753
+#define REGISTER_VIRTUAL_SIZE(\7f137,4644
+#define REGISTER_VIRTUAL_TYPE(\7f167,5425
+#define SAVED_PC_AFTER_CALL(\7f53,1877
+#define SKIP_PROLOGUE(\7f42,1480
+\f
+m-vaxinit.h,29
+#define FILEADDR_ROUND(\7f5,94
+\f
+m68k-opcode.h,138
+#define one(\7f130,5680
+int numopcodes=sizeof(\7f1270,68164
+struct m68k_opcode *endop = m68k_opcodes+sizeof(\7f1272,68226
+#define two(\7f131,5707
+\f
+obstack.h,618
+#define obstack_1grow(\7f252,11387
+#define obstack_1grow_fast(\7f275,12190
+#define obstack_alignment_mask(\7f228,10489
+#define obstack_alloc(\7f263,11796
+#define obstack_base(\7f216,10145
+#define obstack_begin(\7f232,10606
+#define obstack_blank(\7f257,11569
+#define obstack_blank_fast(\7f277,12257
+#define obstack_copy(\7f266,11889
+#define obstack_copy0(\7f269,11994
+#define obstack_finish(\7f279,12314
+#define obstack_free(\7f290,12730
+#define obstack_grow(\7f237,10784
+#define obstack_grow0(\7f244,11064
+#define obstack_init(\7f230,10547
+#define obstack_next_free(\7f220,10254
+#define obstack_object_size(\7f224,10341
+#define obstack_room(\7f272,12101
+\f
+param.h,0
+\f
+symseg.h,0
+\f
+symtab.h,1291
+#define BLOCKLIST(\7f108,3923
+#define BLOCKLIST_BLOCK(\7f137,4911
+#define BLOCKLIST_NBLOCKS(\7f136,4853
+#define BLOCKVECTOR(\7f109,3971
+#define BLOCKVECTOR_BLOCK(\7f139,5030
+#define BLOCKVECTOR_NBLOCKS(\7f138,4970
+#define BLOCK_END(\7f145,5244
+#define BLOCK_FUNCTION(\7f148,5354
+#define BLOCK_NSYMS(\7f146,5280
+#define BLOCK_START(\7f144,5204
+#define BLOCK_SUPERBLOCK(\7f149,5396
+#define BLOCK_SYM(\7f147,5316
+#define LINELIST(\7f113,4071
+#define LINETABLE(\7f114,4116
+#define SYMBOL_BLOCK_VALUE(\7f155,5635
+#define SYMBOL_CLASS(\7f153,5539
+#define SYMBOL_NAME(\7f151,5443
+#define SYMBOL_NAMESPACE(\7f152,5486
+#define SYMBOL_TYPE(\7f156,5692
+#define SYMBOL_VALUE(\7f154,5584
+#define TYPEVECTOR(\7f111,4022
+#define TYPEVECTOR_NTYPES(\7f141,5092
+#define TYPEVECTOR_TYPE(\7f142,5147
+#define TYPE_CODE(\7f170,6307
+#define TYPE_FIELD(\7f174,6453
+#define TYPE_FIELDS(\7f172,6403
+#define TYPE_FIELD_BITPOS(\7f178,6712
+#define TYPE_FIELD_BITSIZE(\7f179,6780
+#define TYPE_FIELD_NAME(\7f176,6571
+#define TYPE_FIELD_PACKED(\7f180,6850
+#define TYPE_FIELD_TYPE(\7f175,6507
+#define TYPE_FIELD_VALUE(\7f177,6635
+#define TYPE_FLAGS(\7f168,6187
+#define TYPE_FUNCTION_TYPE(\7f166,6075
+#define TYPE_LENGTH(\7f167,6138
+#define TYPE_NAME(\7f163,5910
+#define TYPE_NFIELDS(\7f171,6352
+#define TYPE_POINTER_TYPE(\7f165,6014
+#define TYPE_TARGET_TYPE(\7f164,5955
+#define TYPE_UNSIGNED(\7f169,6234
+\f
+value.h,399
+#define COERCE_ARRAY(\7f58,1961
+#define VALUE_ADDRESS(\7f48,1560
+#define VALUE_BITPOS(\7f52,1752
+#define VALUE_BITSIZE(\7f51,1710
+#define VALUE_CONTENTS(\7f46,1469
+#define VALUE_INTERNALVAR(\7f49,1611
+#define VALUE_LVAL(\7f47,1524
+#define VALUE_NEXT(\7f53,1792
+#define VALUE_OFFSET(\7f50,1670
+#define VALUE_REGNO(\7f56,1922
+#define VALUE_REPEATED(\7f54,1828
+#define VALUE_REPETITIONS(\7f55,1872
+#define VALUE_TYPE(\7f45,1433
+\f
+vax-opcode.h,0
+\f
+wait.h,331
+#define WCOREDUMP(\7f13,439
+#define WCOREDUMP(\7f21,690
+#define WIFEXITED(\7f10,338
+#define WIFSIGNALED(\7f9,274
+#define WIFSTOPPED(\7f8,231
+#define WRETCODE(\7f11,377
+#define WRETCODE(\7f19,622
+#define WSETSTOP(\7f15,511
+#define WSETSTOP(\7f23,760
+#define WSTOPSIG(\7f12,408
+#define WSTOPSIG(\7f20,656
+#define WTERMSIG(\7f14,478
+#define WTERMSIG(\7f22,726
+\f
+expread.y,349
+copy_name \7f929,20955
+end_arglist \7f516,11399
+free_funcalls \7f530,11701
+length_of_subexp \7f963,21859
+parse_c_1 \7f1142,25974
+parse_c_expression \7f1181,27028
+parse_number \7f608,13872
+prefixify_expression \7f943,21291
+prefixify_subexp \7f1035,23196
+start_arglist \7f502,11040
+write_exp_elt \7f547,12040
+write_exp_string \7f564,12494
+yyerror \7f920,20800
+yylex \7f706,15915
diff --git a/gdb/alloca.c b/gdb/alloca.c
new file mode 100644 (file)
index 0000000..cfe98f9
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+       alloca -- (mostly) portable public-domain implementation -- D A Gwyn
+
+       last edit:      86/05/30        rms
+          include config.h, since on VMS it renames some symbols.
+          Use xmalloc instead of malloc.
+
+       This implementation of the PWB library alloca() function,
+       which is used to allocate space off the run-time stack so
+       that it is automatically reclaimed upon procedure exit, 
+       was inspired by discussions with J. Q. Johnson of Cornell.
+
+       It should work under any C implementation that uses an
+       actual procedure stack (as opposed to a linked list of
+       frames).  There are some preprocessor constants that can
+       be defined when compiling for your specific system, for
+       improved efficiency; however, the defaults should be okay.
+
+       The general concept of this implementation is to keep
+       track of all alloca()-allocated blocks, and reclaim any
+       that are found to be deeper in the stack than the current
+       invocation.  This heuristic does not reclaim storage as
+       soon as it becomes invalid, but it will do so eventually.
+
+       As a special case, alloca(0) reclaims storage without
+       allocating any.  It is a good idea to use alloca(0) in
+       your main control loop, etc. to force garbage collection.
+*/
+#ifndef lint
+static char    SCCSid[] = "@(#)alloca.c        1.1";   /* for the "what" utility */
+#endif
+
+#ifdef emacs
+#include "config.h"
+#ifdef static
+/* actually, only want this if static is defined as ""
+   -- this is for usg, in which emacs must undefine static
+   in order to make unexec workable
+   */
+#ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+#endif /* STACK_DIRECTION undefined */
+#endif static
+#endif emacs
+
+#ifdef X3J11
+typedef void   *pointer;               /* generic pointer type */
+#else
+typedef char   *pointer;               /* generic pointer type */
+#endif
+
+#define        NULL    0                       /* null pointer constant */
+
+extern void    free();
+extern pointer xmalloc();
+
+/*
+       Define STACK_DIRECTION if you know the direction of stack
+       growth for your system; otherwise it will be automatically
+       deduced at run-time.
+
+       STACK_DIRECTION > 0 => grows toward higher addresses
+       STACK_DIRECTION < 0 => grows toward lower addresses
+       STACK_DIRECTION = 0 => direction of growth unknown
+*/
+
+#ifndef STACK_DIRECTION
+#define        STACK_DIRECTION 0               /* direction unknown */
+#endif
+
+#if STACK_DIRECTION != 0
+
+#define        STACK_DIR       STACK_DIRECTION /* known at compile-time */
+
+#else  /* STACK_DIRECTION == 0; need run-time code */
+
+static int     stack_dir;              /* 1 or -1 once known */
+#define        STACK_DIR       stack_dir
+
+static void
+find_stack_direction (/* void */)
+{
+  static char  *addr = NULL;   /* address of first
+                                  `dummy', once known */
+  auto char    dummy;          /* to get stack address */
+
+  if (addr == NULL)
+    {                          /* initial entry */
+      addr = &dummy;
+
+      find_stack_direction (); /* recurse once */
+    }
+  else                         /* second entry */
+    if (&dummy > addr)
+      stack_dir = 1;           /* stack grew upward */
+    else
+      stack_dir = -1;          /* stack grew downward */
+}
+
+#endif /* STACK_DIRECTION == 0 */
+
+/*
+       An "alloca header" is used to:
+       (a) chain together all alloca()ed blocks;
+       (b) keep track of stack depth.
+
+       It is very important that sizeof(header) agree with malloc()
+       alignment chunk size.  The following default should work okay.
+*/
+
+#ifndef        ALIGN_SIZE
+#define        ALIGN_SIZE      sizeof(double)
+#endif
+
+typedef union hdr
+{
+  char align[ALIGN_SIZE];      /* to force sizeof(header) */
+  struct
+    {
+      union hdr *next;         /* for chaining headers */
+      char *deep;              /* for stack depth measure */
+    } h;
+} header;
+
+/*
+       alloca( size ) returns a pointer to at least `size' bytes of
+       storage which will be automatically reclaimed upon exit from
+       the procedure that called alloca().  Originally, this space
+       was supposed to be taken from the current stack frame of the
+       caller, but that method cannot be made to work for some
+       implementations of C, for example under Gould's UTX/32.
+*/
+
+static header *last_alloca_header = NULL; /* -> last alloca header */
+
+pointer
+alloca (size)                  /* returns pointer to storage */
+     unsigned  size;           /* # bytes to allocate */
+{
+  auto char    probe;          /* probes stack depth: */
+  register char        *depth = &probe;
+
+#if STACK_DIRECTION == 0
+  if (STACK_DIR == 0)          /* unknown growth direction */
+    find_stack_direction ();
+#endif
+
+                               /* Reclaim garbage, defined as all alloca()ed storage that
+                                  was allocated from deeper in the stack than currently. */
+
+  {
+    register header    *hp;    /* traverses linked list */
+
+    for (hp = last_alloca_header; hp != NULL;)
+      if (STACK_DIR > 0 && hp->h.deep > depth
+         || STACK_DIR < 0 && hp->h.deep < depth)
+       {
+         register header       *np = hp->h.next;
+
+         free ((pointer) hp);  /* collect garbage */
+
+         hp = np;              /* -> next header */
+       }
+      else
+       break;                  /* rest are not deeper */
+
+    last_alloca_header = hp;   /* -> last valid storage */
+  }
+
+  if (size == 0)
+    return NULL;               /* no allocation required */
+
+  /* Allocate combined header + user data storage. */
+
+  {
+    register pointer   new = xmalloc (sizeof (header) + size);
+    /* address of header */
+
+    ((header *)new)->h.next = last_alloca_header;
+    ((header *)new)->h.deep = depth;
+
+    last_alloca_header = (header *)new;
+
+    /* User storage begins just after header. */
+
+    return (pointer)((char *)new + sizeof(header));
+  }
+}
+
diff --git a/gdb/bar.c b/gdb/bar.c
new file mode 100644 (file)
index 0000000..59e559f
--- /dev/null
+++ b/gdb/bar.c
@@ -0,0 +1,13 @@
+main() {
+       int i;
+
+       for (i = 0; i >= 0; i++)
+               bar();
+}
+
+bar()
+{
+       int i;
+
+       i = 10;
+}
diff --git a/gdb/bar.nm b/gdb/bar.nm
new file mode 100644 (file)
index 0000000..6f2df5c
--- /dev/null
@@ -0,0 +1,65 @@
+0000003e - 00 0002 RBRAC 
+000020de - 00 000d SLINE 
+000020d6 - 00 000c SLINE 
+000020c8 - 00 0009 SLINE 
+000020c4 - 00 0006 SLINE 
+00000024 - 00 0002 RBRAC 
+000020be - 00 0004 SLINE 
+000020b8 - 00 0005 SLINE 
+000020ae - 00 0004 SLINE 
+0000000e - 00 0002 LBRAC 
+000020d6 - 00 0009 SLINE 
+000020e4 - 00 ffff SLINE 
+000020ae - 00 0001 SLINE 
+000020a0 - 00 0001 SLINE 
+00000036 - 00 0002 LBRAC 
+000020e4 t -lg
+00000000 - 00 0000  LSYM ???:t(0,12)=(0,1)
+00002098 t Fcrt1.o
+0002001c D _Fmode
+00020020 D _Fstatus
+0000215c T __cleanup
+00002164 T __exit
+00020052 D __exit_nhandlers
+00020056 D __exit_tnames
+00020018 D __skybase
+000020c8 T _bar
+00020000 D _environ
+00020118 D _errno
+00002110 T _exit
+00002164 t _exit.o
+000020e4 T _finitfp_
+00020010 D _fp_state_mc68881
+0002000c D _fp_state_skyffp
+00020008 D _fp_state_software
+00020014 D _fp_state_sunfpa
+00020004 D _fp_switch
+000020a0 T _main
+000020a0 - 00 0000    SO bar.c
+000020a0 t bar.o
+000020c8 - 00 0004   FUN bar:F(0,1)
+0000216c T cerror
+0000216c t cerror.o
+00000000 - 00 0000  LSYM char:t(0,2)=r(0,2);0;127;
+00002020 t crt0.o
+00000000 - 00 0000  LSYM double:t(0,10)=r(0,1);8;0;
+00002110 t exit.o
+0000215c t fakcu.o
+000020e4 t finitfp.o
+00000000 - 00 0000  LSYM float:t(0,9)=r(0,1);4;0;
+00002110 t fp_globals.o
+00002098 T fsoft_used
+fffffffc - 00 0004  LSYM i:(0,1)
+fffffffc - 00 0004  LSYM i:(0,1)
+00000000 - 00 0000  LSYM int:t(0,1)=r(0,1);-2147483648;2147483647;
+000020e4 - 00 0000    SO libg.s
+00000000 - 00 0000  LSYM long:t(0,3)=r(0,1);-2147483648;2147483647;
+000020a0 - 00 0004   FUN main:F(0,1)
+00000000 - 00 0000  LSYM short:t(0,4)=r(0,1);-32768;32767;
+00002020 T start
+00002098 T start_float
+00000000 - 00 0000  LSYM unsigned char:t(0,5)=r(0,1);0;255;
+00000000 - 00 0000  LSYM unsigned int:t(0,8)=r(0,1);0;-1;
+00000000 - 00 0000  LSYM unsigned long:t(0,7)=r(0,1);0;-1;
+00000000 - 00 0000  LSYM unsigned short:t(0,6)=r(0,1);0;65535;
+00000000 - 00 0000  LSYM void:t(0,11)=(0,11)
diff --git a/gdb/bar.s b/gdb/bar.s
new file mode 100644 (file)
index 0000000..96b4c07
--- /dev/null
+++ b/gdb/bar.s
@@ -0,0 +1,93 @@
+       .stabs  "bar.c",0144,0,0,LL0
+LL0:
+       .data
+       .stabs  "int:t(0,1)=r(0,1);-2147483648;2147483647;",0x80,0,0,0
+       .stabs  "char:t(0,2)=r(0,2);0;127;",0x80,0,0,0
+       .stabs  "long:t(0,3)=r(0,1);-2147483648;2147483647;",0x80,0,0,0
+       .stabs  "short:t(0,4)=r(0,1);-32768;32767;",0x80,0,0,0
+       .stabs  "unsigned char:t(0,5)=r(0,1);0;255;",0x80,0,0,0
+       .stabs  "unsigned short:t(0,6)=r(0,1);0;65535;",0x80,0,0,0
+       .stabs  "unsigned long:t(0,7)=r(0,1);0;-1;",0x80,0,0,0
+       .stabs  "unsigned int:t(0,8)=r(0,1);0;-1;",0x80,0,0,0
+       .stabs  "float:t(0,9)=r(0,1);4;0;",0x80,0,0,0
+       .stabs  "double:t(0,10)=r(0,1);8;0;",0x80,0,0,0
+       .stabs  "void:t(0,11)=(0,11)",0x80,0,0,0
+       .stabs  "???:t(0,12)=(0,1)",0x80,0,0,0
+       .stabs  "main:F(0,1)",0x24,0,4,_main
+       .text
+       .stabn  0104,0,1,LL1
+LL1:
+|#PROC# 04
+       .globl  _main
+_main:
+|#PROLOGUE# 0
+       link    a6,#0
+       addl    #-LF12,sp
+       moveml  #LS12,sp@
+|#PROLOGUE# 1
+       .stabn  0104,0,1,LL2
+LL2:
+       .stabs  "i:(0,1)",0x80,0,4,-4
+       .stabn  0300,0,2,LL3
+LL3:
+       .stabn  0104,0,4,LL4
+LL4:
+       clrl    a6@(-0x4)
+L16:
+       tstl    a6@(-0x4)
+       jlt     L15
+       .stabn  0104,0,5,LL5
+LL5:
+       jbsr    _bar
+L14:
+       .stabn  0104,0,4,LL6
+LL6:
+       addql   #0x1,a6@(-0x4)
+       jra     L16
+L15:
+       .stabn  0340,0,2,LL7
+LL7:
+       .stabn  0104,0,6,LL8
+LL8:
+LE12:
+       unlk    a6
+       rts
+       LF12 = 4
+       LS12 = 0x0
+       LFF12 = 4
+       LSS12 = 0x0
+       LP12 =  0x8
+       .data
+       .stabs  "bar:F(0,1)",0x24,0,4,_bar
+       .text
+       .stabn  0104,0,9,LL9
+LL9:
+|#PROC# 04
+       .globl  _bar
+_bar:
+|#PROLOGUE# 0
+       link    a6,#0
+       addl    #-LF18,sp
+       moveml  #LS18,sp@
+|#PROLOGUE# 1
+       .stabn  0104,0,9,LL10
+LL10:
+       .stabs  "i:(0,1)",0x80,0,4,-4
+       .stabn  0300,0,2,LL11
+LL11:
+       .stabn  0104,0,12,LL12
+LL12:
+       movl    #0xa,a6@(-0x4)
+       .stabn  0340,0,2,LL13
+LL13:
+       .stabn  0104,0,13,LL14
+LL14:
+LE18:
+       unlk    a6
+       rts
+       LF18 = 4
+       LS18 = 0x0
+       LFF18 = 4
+       LSS18 = 0x0
+       LP18 =  0x8
+       .data
diff --git a/gdb/bar.sym b/gdb/bar.sym
new file mode 100644 (file)
index 0000000..a3f4131
--- /dev/null
@@ -0,0 +1,51 @@
+Symtab for file libg.s
+
+Line table:
+
+ line 2 at 20e4
+
+Blockvector:
+
+block #000 (object 0x56f90) [0x20e4..0x20e4]
+  block #001 (object 0x56f7c) [0x20e4..0x20e4] (under 0x56f90)
+
+
+Symtab for file bar.c
+
+Line table:
+
+ line 1 at 20a0
+ line 1 at 20ae
+ line 4 at 20ae
+ line 5 at 20b8
+ line 4 at 20be
+ line 6 at 20c4
+ line 9 at 20c8
+ line 9 at 20d6
+ line 12 at 20d6
+ line 13 at 20de
+
+Blockvector:
+
+block #000 (object 0x56f4c) [0x20a0..0x20e4]
+ int bar; block (object 0x56ef0) starting at 0x20c8,
+ int main; block (object 0x56ea8) starting at 0x20a0,
+  block #001 (object 0x56f08) [0x20a0..0x20e4] (under 0x56f4c)
+   typedef int ???; 
+   typedef char char; 
+   typedef double double; 
+   typedef float float; 
+   typedef int int; 
+   typedef int long; 
+   typedef short short; 
+   typedef unsigned char unsigned char; 
+   typedef unsigned int unsigned int; 
+   typedef unsigned int unsigned long; 
+   typedef unsigned short unsigned short; 
+   typedef void void; 
+    block #002 (object 0x56ea8) [0x20a0..0x20c8] (under 0x56f08) main
+     int i; local at 0xfffffffc,
+    block #003 (object 0x56ef0) [0x20c8..0x20e4] (under 0x56f08) bar
+     int i; local at 0xfffffffc,
+
+
diff --git a/gdb/blockframe.c b/gdb/blockframe.c
new file mode 100644 (file)
index 0000000..5ed025c
--- /dev/null
@@ -0,0 +1,333 @@
+/* Get info from stack frames;
+   convert between frames, blocks, functions and pc values.
+   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 "initialize.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 ();
+
+START_FILE
+
+/* 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;
+}
+
+/* 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;
+{
+  CORE_ADDR pointer;
+  /* The caller of "no frame" is the innermost frame.  */
+  if (frame == 0)
+    return get_current_frame ();
+
+  /* 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.  */
+  pointer = FRAME_CHAIN (frame);
+  if (!FRAME_CHAIN_VALID (pointer, 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.  */
+  return FRAME_CHAIN_COMBINE (pointer, frame);
+}
+
+/* Return a structure containing various interesting information
+   about a specified stack frame.  */
+
+struct frame_info
+get_frame_info (frame)
+     FRAME frame;
+{
+  struct frame_info val;
+  FRAME current = get_current_frame ();
+  register FRAME frame1;
+
+  val.frame = frame;
+
+  if (frame == current)
+    {
+      val.pc = read_pc ();
+      val.next_frame = 0;
+    }
+  else 
+    {
+      for (frame1 = current; frame1; frame1 = get_prev_frame (frame1))
+       {
+         QUIT;
+         if (frame1 == frame)
+           break;
+
+         val.pc = FRAME_SAVED_PC (frame1);
+         val.next_frame = frame1;
+       }
+    }
+
+  return val;
+}
+
+/* Return a structure containing various interesting information
+   about the frame that called FRAME.
+
+   This is much faster than get_frame_info (get_prev_frame (FRAME))
+   because it does not need to search the entire stack
+   to find the frame called by the one being described -- that is FRAME.  */
+
+struct frame_info
+get_prev_frame_info (next_frame)
+     FRAME next_frame;
+{
+  struct frame_info val;
+  register FRAME frame = get_prev_frame (next_frame);
+
+  val.frame = frame;
+  val.next_frame = next_frame;
+
+  if (next_frame == 0)
+    {
+      val.pc = read_pc ();
+    }
+  else 
+    {
+      val.pc = FRAME_SAVED_PC (next_frame);
+    }
+
+  return val;
+}
+
+CORE_ADDR
+get_frame_pc (frame)
+     FRAME frame;
+{
+  struct frame_info fi;
+  fi = get_frame_info (frame);
+  return fi.pc;
+}
+
+/* Find the addresses in which registers are saved in FRAME.  */
+
+void
+get_frame_saved_regs (frame_info_addr, saved_regs_addr)
+     struct frame_info *frame_info_addr;
+     struct frame_saved_regs *saved_regs_addr;
+{
+  FRAME_FIND_SAVED_REGS (*frame_info_addr, *saved_regs_addr);
+}
+
+/* Return the innermost lexical block in execution
+   in a specified stack frame.  The frame address is assumed valid.  */
+
+struct block *
+get_frame_block (frame)
+     FRAME frame;
+{
+  struct frame_info fi;
+
+  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)
+    {
+      register int misc_index = find_pc_misc_function (pc);
+      if (misc_index >= 0)
+       return misc_function_vector[misc_index].address;
+      return 0;
+    }
+  symbol = block_function (bl);
+  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);
+}
+\f
+/* Return the innermost lexical block containing the specified pc value,
+   or 0 if there is none.  */
+
+struct block *
+block_for_pc (pc)
+     register CORE_ADDR pc;
+{
+  register struct block *b;
+  register int bot, top, half;
+  register struct symtab *s;
+  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)
+    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)
+     CORE_ADDR pc;
+{
+  register int i;
+
+  /* Note that the last thing in the vector is always _etext.  */
+  for (i = 0; i < misc_function_count; i++)
+    {
+      if (pc < misc_function_vector[i].address)
+       return i - 1;
+    }
+  return -1;
+}
+
+/* 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)
+    {
+      fi = get_prev_frame_info (frame);
+      frame = fi.frame;
+      if (frame == 0)
+       return 0;
+      if (fi.pc >= start && fi.pc < end)
+       return frame;
+    }
+}
+
+static
+initialize ()
+{
+}
+
+END_FILE
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
new file mode 100644 (file)
index 0000000..82e4075
--- /dev/null
@@ -0,0 +1,1096 @@
+/* Everything about breakpoints, 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 "defs.h"
+#include "initialize.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+
+#include <stdio.h>
+
+/* This is the sequence of bytes we insert for a breakpoint.  */
+
+static char break_insn[] = BREAKPOINT;
+
+/* States of enablement of breakpoint.
+   `temporary' means disable when hit.
+   `once' means delete when hit.  */
+
+enum enable { disabled, enabled, temporary, delete};
+
+struct breakpoint
+{
+  struct breakpoint *next;
+  /* Number assigned to distinguish breakpoints.  */
+  int number;
+  /* Address to break at.  */
+  CORE_ADDR address;
+  /* Line number of this address.  Redundant.  */
+  int line_number;
+  /* Symtab of file of this address.  Redundant.  */
+  struct symtab *symtab;
+  /* Zero means disabled; remember the info but don't break here.  */
+  enum enable enable;
+  /* Number of stops at this breakpoint that should
+     be continued automatically before really stopping.  */
+  int ignore_count;
+  /* "Real" contents of byte where breakpoint has been inserted.
+     Valid only when breakpoints are in the program.  */
+  char shadow_contents[sizeof break_insn];
+  /* Nonzero if this breakpoint is now inserted.  */
+  char inserted;
+  /* Nonzero if this is not the first breakpoint in the list
+     for the given address.  */
+  char duplicate;
+  /* Chain of command lines to execute when this breakpoint is hit.  */
+  struct command_line *commands;
+  /* Stack depth (frame).  If nonzero, break only if fp equals this.  */
+  FRAME frame;
+  /* Conditional.  Break only if this expression's value is nonzero.  */
+  struct expression *cond;
+};
+
+#define ALL_BREAKPOINTS(b)  for (b = breakpoint_chain; b; b = b->next)
+
+/* Chain of all breakpoints defined.  */
+
+struct breakpoint *breakpoint_chain;
+
+/* Number of last breakpoint made.  */
+
+static int breakpoint_count;
+
+/* Default address, symtab and line to put a breakpoint at
+   for "break" command with no arg.
+   if default_breakpoint_valid is zero, the other three are
+   not valid, and "break" with no arg is an error.
+
+   This set by print_stack_frame, which calls set_default_breakpoint.  */
+
+int default_breakpoint_valid;
+CORE_ADDR default_breakpoint_address;
+struct symtab *default_breakpoint_symtab;
+int default_breakpoint_line;
+
+/* Remaining commands (not yet executed)
+   of last breakpoint hit.  */
+
+struct command_line *breakpoint_commands;
+
+START_FILE
+
+extern char *read_line ();
+
+static void delete_breakpoint ();
+void clear_momentary_breakpoints ();
+void breakpoint_auto_delete ();
+\f
+/* condition N EXP -- set break condition of breakpoint N to EXP.  */
+
+static void
+condition_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  register struct breakpoint *b;
+  register char *p;
+  register int bnum;
+  register struct expression *expr;
+
+  if (arg == 0)
+    error_no_arg ("breakpoint number");
+
+  p = arg;
+  while (*p >= '0' && *p <= '9') p++;
+  bnum = atoi (arg);
+
+  ALL_BREAKPOINTS (b)
+    if (b->number == bnum)
+      {
+       if (b->cond)
+         free (b->cond);
+       if (*p == 0)
+         {
+           b->cond = 0;
+           if (from_tty)
+             printf ("Breakpoint %d now unconditional.\n", bnum);
+         }
+       else
+         {
+           if (*p != ' ' && *p != '\t')
+             error ("Arguments must be an integer (breakpoint number) and an expression.");
+
+           /* Find start of expression */
+           while (*p == ' ' || *p == '\t') p++;
+
+           arg = p;
+           b->cond = (struct expression *) parse_c_1 (&arg, block_for_pc (b->address));
+         }
+       return;
+      }
+
+  error ("No breakpoint number %d.", bnum);
+}
+
+static void
+commands_command (arg)
+     char *arg;
+{
+  register struct breakpoint *b;
+  register char *p, *p1;
+  register int bnum;
+  struct command_line *l;
+
+  if (arg == 0)
+    error_no_arg ("breakpoint number");
+
+  /* If we allowed this, we would have problems with when to
+     free the storage, if we change the commands currently
+     being read from.  */
+
+  if (breakpoint_commands)
+    error ("Can't use the \"commands\" command among a breakpoint's commands.");
+
+  p = arg;
+  if (! (*p >= '0' && *p <= '9'))
+    error ("Argument must be integer (a breakpoint number).");
+
+  while (*p >= '0' && *p <= '9') p++;
+  if (*p)
+    error ("Unexpected extra arguments following breakpoint number.");
+
+  bnum = atoi (arg);
+
+  ALL_BREAKPOINTS (b)
+    if (b->number == bnum)
+      {
+       if (input_from_terminal_p ())
+         printf ("Type commands for when breakpoint %d is hit, one per line.\n\
+End with a line saying just \"end\".\n", bnum);
+       l = read_command_lines ();
+       free_command_lines (&b->commands);
+       b->commands = l;
+       return;
+      }
+  error ("No breakpoint number %d.", bnum);
+}
+
+/* Called from command loop to execute the commands
+   associated with the breakpoint we just stopped at.  */
+
+void
+do_breakpoint_commands ()
+{
+  while (breakpoint_commands)
+    {
+      char *line = breakpoint_commands->line;
+      breakpoint_commands = breakpoint_commands->next;
+      execute_command (line, 0);
+      /* If command was "cont", breakpoint_commands is now 0,
+        of if we stopped at yet another breakpoint which has commands,
+        it is now the commands for the new breakpoint.  */
+    }
+  clear_momentary_breakpoints ();
+}
+
+/* Used when the program is proceeded, to eliminate any remaining
+   commands attached to the previous breakpoint we stopped at.  */
+
+void
+clear_breakpoint_commands ()
+{
+  breakpoint_commands = 0;
+  breakpoint_auto_delete (0);
+}
+
+/* Functions to get and set the current list of pending
+   breakpoint commands.  These are used by run_stack_dummy
+   to preserve the commands around a function call.  */
+
+struct command_line *
+get_breakpoint_commands ()
+{
+  return breakpoint_commands;
+}
+
+void
+set_breakpoint_commands (cmds)
+     struct command_line *cmds;
+{
+  breakpoint_commands = cmds;
+}
+\f
+/* insert_breakpoints is used when starting or continuing the program.
+   remove_breakpoints is used when the program stops.
+   Both return zero if successful,
+   or an `errno' value if could not write the inferior.  */
+
+int
+insert_breakpoints ()
+{
+  register struct breakpoint *b;
+  int val;
+
+/*   printf ("Inserting breakpoints.\n"); */
+  ALL_BREAKPOINTS (b)
+    if (b->enable != disabled && ! b->inserted && ! b->duplicate)
+      {
+       read_memory (b->address, b->shadow_contents, sizeof break_insn);
+       val = write_memory (b->address, break_insn, sizeof break_insn);
+       if (val)
+         return val;
+/*     printf ("Inserted breakpoint at 0x%x, shadow 0x%x, 0x%x.\n",
+               b->address, b->shadow_contents[0], b->shadow_contents[1]); */
+       b->inserted = 1;
+      }
+  return 0;
+}
+
+int
+remove_breakpoints ()
+{
+  register struct breakpoint *b;
+  int val;
+
+/*   printf ("Removing breakpoints.\n"); */
+  ALL_BREAKPOINTS (b)
+    if (b->inserted)
+      {
+       val = write_memory (b->address, b->shadow_contents, sizeof break_insn);
+       if (val)
+         return val;
+       b->inserted = 0;
+/*     printf ("Removed breakpoint at 0x%x, shadow 0x%x, 0x%x.\n",
+               b->address, b->shadow_contents[0], b->shadow_contents[1]); */
+      }
+
+  return 0;
+}
+
+/* Clear the "inserted" flag in all breakpoints.
+   This is done when the inferior is loaded.  */
+
+int
+mark_breakpoints_out ()
+{
+  register struct breakpoint *b;
+
+  ALL_BREAKPOINTS (b)
+    b->inserted = 0;
+}
+
+/* breakpoint_here_p (PC) returns 1 if an enabled breakpoint exists at PC.
+   When continuing from a location with a breakpoint,
+   we actually single step once before calling insert_breakpoints.  */
+
+int
+breakpoint_here_p (pc)
+     CORE_ADDR pc;
+{
+  register struct breakpoint *b;
+
+  ALL_BREAKPOINTS (b)
+    if (b->enable != disabled && b->address == pc)
+      return 1;
+
+  return 0;
+}
+
+/* Return 0 if PC is not the address just after a breakpoint,
+   or -1 if breakpoint says do not stop now,
+   or -2 if breakpoint says it has deleted itself and don't stop,
+   or -3 if hit a breakpoint number -3 (delete when program stops),
+   or else the number of the breakpoint,
+   with 0x1000000 added for a silent breakpoint.  */
+
+int
+breakpoint_stop_status (pc, frame)
+     CORE_ADDR pc;
+     FRAME frame;
+{
+  register struct breakpoint *b;
+  register int cont = 0;
+
+  /* Get the address where the breakpoint would have been.  */
+  pc -= DECR_PC_AFTER_BREAK;
+
+  ALL_BREAKPOINTS (b)
+    if (b->enable != disabled && b->address == pc)
+      {
+       if (b->frame && b->frame != frame)
+         cont = -1;
+       else
+         {
+           int value_zero;
+           if (b->cond)
+             {
+               value_zero = value_zerop (evaluate_expression (b->cond));
+               free_all_values ();
+             }
+           if (b->cond && value_zero)
+             {
+               cont = -1;
+             }
+           else if (b->ignore_count > 0)
+             {
+               b->ignore_count--;
+               cont = -1;
+             }
+           else
+             {
+               if (b->enable == temporary)
+                 b->enable = disabled;
+               breakpoint_commands = b->commands;
+               if (breakpoint_commands
+                   && !strcmp ("silent", breakpoint_commands->line))
+                 {
+                   breakpoint_commands = breakpoint_commands->next;
+                   return 0x1000000 + b->number;
+                 }
+               return b->number;
+             }
+         }
+      }
+
+  return cont;
+}
+\f
+static void
+breakpoint_1 (bnum)
+     int bnum;
+{
+  register struct breakpoint *b;
+  register struct command_line *l;
+  register struct symbol *sym;
+  CORE_ADDR last_addr = -1;
+
+  ALL_BREAKPOINTS (b)
+    if (bnum == -1 || bnum == b->number)
+      {
+       printf ("#%-3d %c  0x%08x ", b->number,
+               "nyod"[(int) b->enable],
+               b->address);
+       last_addr = b->address;
+       if (b->symtab)
+         {
+           sym = find_pc_function (b->address);
+           if (sym)
+             printf (" 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 ("\n");
+
+       if (b->ignore_count)
+         printf ("\tignore next %d hits\n", b->ignore_count);
+       if (b->frame)
+         printf ("\tstop only in stack frame at 0x%x\n", b->frame);
+       if (b->cond)
+         {
+           printf ("\tbreak only if ");
+           print_expression (b->cond, stdout);
+           printf ("\n");
+         }
+       if (l = b->commands)
+         while (l)
+           {
+             printf ("\t%s\n", l->line);
+             l = l->next;
+           }
+      }
+
+  if (last_addr != -1)
+    set_next_address (last_addr);
+}
+
+static void
+breakpoints_info (bnum_exp)
+     char *bnum_exp;
+{
+  int bnum = -1;
+
+  if (bnum_exp)
+    bnum = parse_and_eval_address (bnum_exp);
+  else if (breakpoint_chain == 0)
+    printf ("No breakpoints.\n");
+  else
+    printf ("Breakpoints:\n\
+Num Enb   Address    Where\n");
+
+  breakpoint_1 (bnum);
+}
+
+/* Print a message describing any breakpoints set at PC.  */
+
+static void
+describe_other_breakpoints (pc)
+     register CORE_ADDR pc;
+{
+  register int others = 0;
+  register struct breakpoint *b;
+
+  ALL_BREAKPOINTS (b)
+    if (b->address == pc)
+      others++;
+  if (others > 0)
+    {
+      printf ("Note: breakpoint%s ", (others > 1) ? "s" : "");
+      ALL_BREAKPOINTS (b)
+       if (b->address == pc)
+         {
+           others--;
+           printf ("%d%s%s ",
+                   b->number,
+                   (b->enable == disabled) ? " (disabled)" : "",
+                   (others > 1) ? "," : ((others == 1) ? " and" : ""));
+         }
+      printf (" also set at pc 0x%x\n", pc);
+    }
+}
+\f
+/* Set the default place to put a breakpoint
+   for the `break' command with no arguments.  */
+
+void
+set_default_breakpoint (valid, addr, symtab, line)
+     int valid;
+     CORE_ADDR addr;
+     struct symtab *symtab;
+     int line;
+{
+  default_breakpoint_valid = valid;
+  default_breakpoint_address = addr;
+  default_breakpoint_symtab = symtab;
+  default_breakpoint_line = line;
+}
+
+/* Rescan breakpoints at address ADDRESS,
+   marking the first one as "first" and any others as "duplicates".
+   This is so that the bpt instruction is only inserted once.  */
+
+static void
+check_duplicates (address)
+     CORE_ADDR address;
+{
+  register struct breakpoint *b;
+  register int count = 0;
+
+  ALL_BREAKPOINTS (b)
+    if (b->enable != disabled && b->address == address)
+      {
+       count++;
+       b->duplicate = count > 1;
+      }
+}
+
+/* Low level routine to set a breakpoint.
+   Takes as args the three things that every breakpoint must have.
+   Returns the breakpoint object so caller can set other things.
+   Does not set the breakpoint number!
+   Does not print anything.  */
+
+static struct breakpoint *
+set_raw_breakpoint (sal)
+     struct symtab_and_line sal;
+{
+  register struct breakpoint *b, *b1;
+
+  b = (struct breakpoint *) xmalloc (sizeof (struct breakpoint));
+  bzero (b, sizeof *b);
+  b->address = sal.pc;
+  b->symtab = sal.symtab;
+  b->line_number = sal.line;
+  b->enable = enabled;
+  b->next = 0;
+
+  /* Add this breakpoint to the end of the chain
+     so that a list of breakpoints will come out in order
+     of increasing numbers.  */
+
+  b1 = breakpoint_chain;
+  if (b1 == 0)
+    breakpoint_chain = b;
+  else
+    {
+      while (b1->next)
+       b1 = b1->next;
+      b1->next = b;
+    }
+
+  check_duplicates (sal.pc);
+
+  return b;
+}
+
+/* Set a breakpoint that will evaporate an end of command
+   at address specified by SAL.
+   Restrict it to frame FRAME if FRAME is nonzero.  */
+
+void
+set_momentary_breakpoint (sal, frame)
+     struct symtab_and_line sal;
+     FRAME frame;
+{
+  register struct breakpoint *b;
+  b = set_raw_breakpoint (sal);
+  b->number = -3;
+  b->enable = delete;
+  b->frame = frame;
+}
+
+void
+clear_momentary_breakpoints ()
+{
+  register struct breakpoint *b;
+  ALL_BREAKPOINTS (b)
+    if (b->number == -3)
+      {
+       delete_breakpoint (b);
+       break;
+      }
+}
+\f
+/* Set a breakpoint from a symtab and line.
+   If TEMPFLAG is nonzero, it is a temporary breakpoint.
+   Print the same confirmation messages that the breakpoint command prints.  */
+
+void
+set_breakpoint (s, line, tempflag)
+     struct symtab *s;
+     int line;
+     int tempflag;
+{
+  register struct breakpoint *b;
+  struct symtab_and_line sal;
+  
+  sal.symtab = s;
+  sal.line = line;
+  sal.pc = find_line_pc (sal.symtab, sal.line);
+  if (sal.pc == 0)
+    error ("No line %d in file \"%s\".\n", sal.line, sal.symtab->filename);
+  else
+    {
+      describe_other_breakpoints (sal.pc);
+
+      b = set_raw_breakpoint (sal);
+      b->number = ++breakpoint_count;
+      b->cond = 0;
+      if (tempflag)
+       b->enable = temporary;
+
+      printf ("Breakpoint %d at 0x%x", b->number, b->address);
+      if (b->symtab)
+       printf (": file %s, line %d.", b->symtab->filename, b->line_number);
+      printf ("\n");
+    }
+}
+\f
+/* Set a breakpoint according to ARG (function, linenum or *address)
+   and make it temporary if TEMPFLAG is nonzero.  */
+
+static void
+break_command_1 (arg, tempflag, from_tty)
+     char *arg;
+     int tempflag, from_tty;
+{
+  struct symtab_and_line sal;
+  register struct expression *cond = 0;
+  register struct breakpoint *b;
+
+  sal.pc = 0;
+
+  if (arg)
+    {
+      sal = decode_line_1 (&arg, 1, 0, 0);
+
+      if (sal.pc == 0 && sal.symtab != 0)
+       {
+         sal.pc = find_line_pc (sal.symtab, sal.line);
+         if (sal.pc == 0)
+           error ("No line %d in file \"%s\".",
+                  sal.line, sal.symtab->filename);
+       }
+
+      while (*arg)
+       {
+         if (arg[0] == 'i' && arg[1] == 'f'
+             && (arg[2] == ' ' || arg[2] == '\t'))
+           cond = (struct expression *) parse_c_1 ((arg += 2, &arg),
+                                                   block_for_pc (sal.pc));
+         else
+           error ("Junk at end of arguments.");
+       }
+    }
+  else if (default_breakpoint_valid)
+    {
+      sal.pc = default_breakpoint_address;
+      sal.line = default_breakpoint_line;
+      sal.symtab = default_breakpoint_symtab;
+    }
+  else
+    error ("No default breakpoint address now.");
+
+  if (from_tty)
+    describe_other_breakpoints (sal.pc);
+
+  b = set_raw_breakpoint (sal);
+  b->number = ++breakpoint_count;
+  b->cond = cond;
+  if (tempflag)
+    b->enable = temporary;
+
+  printf ("Breakpoint %d at 0x%x", b->number, b->address);
+  if (b->symtab)
+    printf (": file %s, line %d.", b->symtab->filename, b->line_number);
+  printf ("\n");
+}
+
+static void
+break_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  break_command_1 (arg, 0, from_tty);
+}
+
+static void
+tbreak_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  break_command_1 (arg, 1, from_tty);
+}
+\f
+static void
+clear_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  register struct breakpoint *b, *b1;
+  struct symtab_and_line sal;
+  register struct breakpoint *found;
+
+  if (arg)
+    sal = decode_line_spec (arg, 1);
+  else
+    {
+      sal.line = default_breakpoint_line;
+      sal.symtab = default_breakpoint_symtab;
+      sal.pc = 0;
+      if (sal.symtab == 0)
+       error ("No source file specified.");
+    }
+
+  /* If exact pc given, clear bpts at that pc.
+     But if sal.pc is zero, clear all bpts on specified line.  */
+
+  found = (struct breakpoint *) 0;
+  while (breakpoint_chain
+        && (sal.pc ? breakpoint_chain->address == sal.pc
+            : (breakpoint_chain->symtab == sal.symtab
+               && breakpoint_chain->line_number == sal.line)))
+    {
+      b1 = breakpoint_chain;
+      breakpoint_chain = b1->next;
+      b1->next = found;
+      found = b1;
+    }
+
+  ALL_BREAKPOINTS (b)
+    while (b->next
+          && (sal.pc ? b->next->address == sal.pc
+              : (b->next->symtab == sal.symtab
+                 && b->next->line_number == sal.line)))
+      {
+       b1 = b->next;
+       b->next = b1->next;
+       b1->next = found;
+       found = b1;
+      }
+
+  if (found == 0)
+    error ("No breakpoint at %s.", arg);
+
+  if (found->next) from_tty = 1; /* Alwats report if deleted more than one */
+  if (from_tty) printf ("Deleted breakpoint%s ", found->next ? "s" : "");
+  while (found)
+    {
+      if (from_tty) printf ("%d ", found->number);
+      b1 = found->next;
+      delete_breakpoint (found);
+      found = b1;
+    }
+  if (from_tty) putchar ('\n');
+}
+
+/* Delete breakpoint number BNUM if it is a `delete' breakpoint.
+   This is called after breakpoint BNUM has been hit.
+   Also delete any breakpoint numbered -3 unless there are breakpoint
+   commands to be executed.  */
+
+void
+breakpoint_auto_delete (bnum)
+     int bnum;
+{
+  register struct breakpoint *b;
+  if (bnum != 0)
+    ALL_BREAKPOINTS (b)
+      if (b->number == bnum)
+       {
+         if (b->enable == delete)
+           delete_breakpoint (b);
+         break;
+       }
+  if (breakpoint_commands == 0)
+    clear_momentary_breakpoints ();
+}
+
+static void
+delete_breakpoint (bpt)
+     struct breakpoint *bpt;
+{
+  register struct breakpoint *b;
+
+  if (bpt->inserted)
+    write_memory (bpt->address, bpt->shadow_contents, sizeof break_insn);
+
+  if (breakpoint_chain == bpt)
+    breakpoint_chain = bpt->next;
+
+  ALL_BREAKPOINTS (b)
+    if (b->next == bpt)
+      {
+       b->next = bpt->next;
+       break;
+      }
+
+  check_duplicates (bpt->address);
+
+  free_command_lines (&bpt->commands);
+  if (bpt->cond)
+    free (bpt->cond);
+  free (bpt);
+}
+
+void map_breakpoint_numbers ();
+
+static void
+delete_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  register struct breakpoint *b, *b1;
+
+  if (arg == 0)
+    {
+      if (!from_tty || query ("Delete all breakpoints? "))
+       {
+         /* No arg; clear all breakpoints.  */
+         while (breakpoint_chain)
+           delete_breakpoint (breakpoint_chain);
+       }
+    }
+  else
+    map_breakpoint_numbers (arg, delete_breakpoint);
+}
+
+/* Delete all breakpoints.
+   Done when new symtabs are loaded, since the break condition expressions
+   may become invalid, and the breakpoints are probably wrong anyway.  */
+
+void
+clear_breakpoints ()
+{
+  delete_command (0, 0);
+}
+\f
+/* Set ignore-count of breakpoint number BPTNUM to COUNT.
+   If from_tty is nonzero, it prints a message to that effect,
+   which ends with a period (no newline).  */
+
+void
+set_ignore_count (bptnum, count, from_tty)
+     int bptnum, count, from_tty;
+{
+  register struct breakpoint *b;
+
+  if (count < 0)
+    count = 0;
+
+  ALL_BREAKPOINTS (b)
+    if (b->number == bptnum)
+      {
+       b->ignore_count = count;
+       if (!from_tty)
+         return;
+       else if (count == 0)
+         printf ("Will stop next time breakpoint %d is reached.", bptnum);
+       else if (count == 1)
+         printf ("Will ignore next crossing of breakpoint %d.", bptnum);
+       else
+         printf ("Will ignore next %d crossings of breakpoint %d.",
+                 count, bptnum);
+       return;
+      }
+
+  error ("No breakpoint number %d.", bptnum);
+}
+
+/* Command to set ignore-count of breakpoint N to COUNT.  */
+
+static void
+ignore_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  register char *p;
+  register int num;
+
+  if (p == 0)
+    error_no_arg ("a breakpoint number");
+  
+  p = args;
+  while (*p >= '0' && *p <= '9') p++;
+  if (*p && *p != ' ' && *p != '\t')
+    error ("First argument must be a breakpoint number.");
+
+  num = atoi (args);
+
+  if (*p == 0)
+    error ("Second argument (specified ignore-count) is missing.");
+
+  set_ignore_count (num, parse_and_eval_address (p), from_tty);
+  printf ("\n");
+}
+\f
+/* Call FUNCTION on each of the breakpoints
+   whose numbers are given in ARGS.  */
+
+static void
+map_breakpoint_numbers (args, function)
+     char *args;
+     void (*function) ();
+{
+  register char *p = args;
+  register char *p1;
+  register int num;
+  register struct breakpoint *b;
+
+  if (p == 0)
+    error_no_arg ("one or more breakpoint numbers");
+
+  while (*p)
+    {
+      p1 = p;
+      while (*p1 >= '0' && *p1 <= '9') p1++;
+      if (*p1 && *p1 != ' ' && *p1 != '\t')
+       error ("Arguments must be breakpoint numbers.");
+
+      num = atoi (p);
+
+      ALL_BREAKPOINTS (b)
+       if (b->number == num)
+         {
+           function (b);
+           goto win;
+         }
+      printf ("No breakpoint number %d.\n", num);
+    win:
+      p = p1;
+      while (*p == ' ' || *p == '\t') p++;
+    }
+}
+
+static void
+enable_breakpoint (bpt)
+     struct breakpoint *bpt;
+{
+  bpt->enable = enabled;
+
+  check_duplicates (bpt->address);
+}
+
+static void
+enable_command (args)
+     char *args;
+{
+  map_breakpoint_numbers (args, enable_breakpoint);
+}
+
+static void
+disable_breakpoint (bpt)
+     struct breakpoint *bpt;
+{
+  bpt->enable = disabled;
+
+  check_duplicates (bpt->address);
+}
+
+static void
+disable_command (args)
+     char *args;
+{
+  register struct breakpoint *bpt;
+  if (args == 0)
+    ALL_BREAKPOINTS (bpt)
+      disable_breakpoint (bpt);
+  else
+    map_breakpoint_numbers (args, disable_breakpoint);
+}
+
+static void
+enable_once_breakpoint (bpt)
+     struct breakpoint *bpt;
+{
+  bpt->enable = temporary;
+
+  check_duplicates (bpt->address);
+}
+
+static void
+enable_once_command (args)
+     char *args;
+{
+  map_breakpoint_numbers (args, enable_once_breakpoint);
+}
+
+static void
+enable_delete_breakpoint (bpt)
+     struct breakpoint *bpt;
+{
+  bpt->enable = delete;
+
+  check_duplicates (bpt->address);
+}
+
+static void
+enable_delete_command (args)
+     char *args;
+{
+  map_breakpoint_numbers (args, enable_delete_breakpoint);
+}
+\f
+
+/* Chain containing all defined enable commands.  */
+
+struct cmd_list_element *enablelist;
+
+extern struct cmd_list_element *cmdlist;
+
+static
+initialize ()
+{
+  breakpoint_chain = 0;
+  breakpoint_count = 0;
+  enablelist = 0;
+
+  add_com ("ignore", class_breakpoint, ignore_command,
+          "Set ignore-count of breakpoint number N to COUNT.");
+
+  add_com ("commands", class_breakpoint, commands_command,
+          "Set commands to be executed when a breakpoint is hit.\n\
+Give breakpoint number as argument after \"commands\".\n\
+The commands themselves follow starting on the next line.\n\
+Type a line containing \"end\" to indicate the end of them.\n\
+Give \"silent\" as the first line to make the breakpoint silent;\n\
+then no output is printed when it is hit, except what the commands print.");
+
+  add_com ("condition", class_breakpoint, condition_command,
+          "Specify breakpoint number N to break only if COND is true.\n\
+N is an integer; COND is a C expression to be evaluated whenever\n\
+breakpoint N is reached.  Actually break only when COND is nonzero.");
+
+  add_com ("tbreak", class_breakpoint, tbreak_command,
+          "Set a temporary breakpoint.  Args like \"break\" command.\n\
+Like \"break\" except the breakpoint is only enabled temporarily,\n\
+so it will be disabled when hit.  Equivalent to \"break\" followed\n\
+by using \"enable once\" on the breakpoint number.");
+
+  add_prefix_cmd ("enable", class_breakpoint, enable_command,
+                 "Enable some breakpoints.  Give breakpoint numbers as arguments.\n\
+With no subcommand, breakpoints are enabled until you command otherwise.\n\
+This is used to cancel the effect of the \"disable\" command.\n\
+With a subcommand you can enable temporarily.",
+                 &enablelist, "enable ", 1, &cmdlist);
+
+  add_cmd ("delete", 0, enable_delete_command,
+          "Enable breakpoints and delete when hit.  Give breakpoint numbers.\n\
+If a breakpoint is hit while enabled in this fashion, it is deleted.",
+          &enablelist);
+
+  add_cmd ("once", 0, enable_once_command,
+          "Enable breakpoints for one hit.  Give breakpoint numbers.\n\
+If a breakpoint is hit while enabled in this fashion, it becomes disabled.\n\
+See the \"tbreak\" command which sets a breakpoint and enables it once.",
+          &enablelist);
+
+  add_com ("disable", class_breakpoint, disable_command,
+          "Disable some breakpoints.  Give breakpoint numbers as arguments.\n\
+With no arguments, disable all breakpoints.\n\
+A disabled breakpoint is not forgotten,\n\
+but it has no effect until enabled again.");
+  add_com_alias ("dis", "disable", class_breakpoint, 1);
+
+  add_com ("delete", class_breakpoint, delete_command,
+          "Delete breakpoints, specifying breakpoint numbers; or all breakpoints.\n\
+Arguments are breakpoint numbers with spaces in between.\n\
+To delete all breakpoints, give no argument.");
+  add_com_alias ("d", "delete", class_breakpoint, 1);
+
+  add_com ("clear", class_breakpoint, clear_command,
+          "Clear breakpoint at specified line or function.\n\
+Argument may be line number, function name, or \"*\" and an address.\n\
+If line number is specified, all breakpoints in that line are cleared.\n\
+If function is specified, breakpoints at beginning of function are cleared.\n\
+If an address is specified, breakpoints at that address are cleared.\n\n\
+With no argument, clears all breakpoints in the line that the selected frame\n\
+is executing in.\n\
+\n\
+See also the \"delete\" command which clears breakpoints by number.");
+
+  add_com ("break", class_breakpoint, break_command,
+          "Set breakpoint at specified line or function.\n\
+Argument may be line number, function name, or \"*\" and an address.\n\
+If line number is specified, break at start of code for that line.\n\
+If function is specified, break at start of code for that function.\n\
+If an address is specified, break at that exact address.\n\
+With no arg, uses current execution address of selected stack frame.\n\
+This is useful for breaking on return to a stack frame.\n\
+\n\
+Multiple breakpoints at one place are permitted, and useful if conditional.\n\
+\n\
+Do \"help breakpoints\" for info on other commands dealing with breakpoints.");
+  add_com_alias ("b", "break", class_run, 1);
+  add_com_alias ("br", "break", class_run, 1);
+  add_com_alias ("bre", "break", class_run, 1);
+  add_com_alias ("brea", "break", class_run, 1);
+
+  add_info ("breakpoints", breakpoints_info,
+           "Status of all breakpoints, or breakpoint number NUMBER.\n\
+Second column is \"y\" for enabled breakpoint, \"n\" for disabled,\n\
+\"o\" for enabled once (disable when hit), \"d\" for enable but delete when hit.\n\
+Then come the address and the file/line number.\n\n\
+Convenience variable \"$_\" and default examine address for \"x\"\n\
+are set to the address of the last breakpoint listed.");
+}
+
+END_FILE
diff --git a/gdb/coffread.c b/gdb/coffread.c
new file mode 100644 (file)
index 0000000..626b16f
--- /dev/null
@@ -0,0 +1,1860 @@
+/* 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 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!
+*/
+\f
+#include "defs.h"
+#include "param.h"
+#ifdef COFF_FORMAT
+#include "initialize.h"
+#include "symtab.h"
+
+#include <a.out.h>
+#include <stdio.h>
+#include <obstack.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+
+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 ();
+
+START_FILE
+
+/* 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;
+
+int debug = 1;
+
+\f
+/* 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)
+    {
+      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];
+}
+
+/* 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;
+}
+\f
+/* 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 *) xmalloc (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 *) xmalloc (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;
+{
+  /* 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 (int));
+    }
+
+  /* If this line is not continguous with previous one recorded,
+     all lines between subsequent line and current one are same pc.
+     Add one item to line vector, and if more than one line skipped, 
+     record a line-number entry for it.  */
+  if (prev_line_number > 0 && line != prev_line_number + 1)
+    line_vector->item[line_vector_index++] = pc;
+  if (prev_line_number < 0 || line > prev_line_number + 2)
+    line_vector->item[line_vector_index++] = - line;
+  prev_line_number = line;
+
+  /* Record the core address of the line.  */
+  line_vector->item[line_vector_index++] = pc;
+}
+\f
+/* 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 (int));
+}
+
+/* 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;
+      /* 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);
+    }
+
+  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);
+  blockvector = make_blockvector ();
+
+  /* Now create the symtab objects proper this source file.  */
+
+  symtab = (struct symtab *) xmalloc (sizeof (struct symtab));
+  /* Fill in its components.  */
+  symtab->blockvector = blockvector;
+  symtab->free_code = free_contents;
+  symtab->free_ptr = 0;
+  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 (int));
+  symtab->nlines = 0;
+  symtab->line_charpos = 0;
+
+  /* Link the new symtab into the list of such.  */
+  symtab->next = symtab_list;
+  symtab_list = symtab;
+
+  line_vector = 0;
+  line_vector_length = -1;
+  last_source_file = 0;
+}
+\f
+/* 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++;
+}
+
+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);
+         qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
+                sizeof (struct symbol *), compare_symbols);
+       }
+    }
+}
+\f
+/* 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.");
+      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;
+    }
+
+  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)
+    error ("\"%s\": can't get string table", name);
+  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);
+
+  printf ("Reading symbol data from %s...", name);
+  fflush (stdout);
+
+  /* Throw away the old symbol table.  */
+
+  free_all_symtabs ();
+
+  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;
+}
+\f
+/* 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;
+{
+  FILE *stream = fdopen (desc, "r");
+  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;
+
+  int num_object_files = 0;
+  int next_file_symnum = 0;
+  char *filestring;
+  int depth;
+  int fcn_first_line;
+  int fcn_last_line;
+  long fcn_line_ptr;
+
+  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)
+    {
+      read_one_sym (cs, &main_sym, &main_aux);
+
+      /*
+       * If we are finished with the previous file's symbols, and the
+       * next thing is not a C_FILE, then we have hit the global symbols.
+       */
+      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 */
+       }
+
+      if (ISFCN (cs->c_type))
+       {
+         /*
+          * gdb expects all functions to also be in misc_function
+          * list -- why not...
+          */
+         record_misc_function (cs->c_name, cs->c_value);
+
+         fcn_line_ptr = main_aux.x_sym.x_fcnary.x_fcn.x_lnnoptr;
+         within_function = 1;
+
+         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 = cs->c_value;
+         new->name = process_coff_symbol (cs, &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 ();
+             }
+           complete_symtab (filestring, 0, 0); /* FIXME, 0 0 is wrong */
+           num_object_files++;
+           break;
+
+         case C_EXT:
+           if (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_STAT:
+           if (cs->c_type == T_NULL && cs->c_secnum > N_UNDEF)
+             {
+               /* These ".text", ".data", ".bss" entries don't seem to
+                * appear in A/UX COFF output.   -- gnu@toad.com  4Apr88
+                */
+               if (strcmp (cs->c_name, _TEXT) == 0)
+                 {
+                   /* We have a ".text" symbol */
+                   if (num_object_files == 1)
+                     {
+                       /* Record end address of first file, crt0.s */
+                       first_object_file_end =
+                           cs->c_value + main_aux.x_scn.x_scnlen;
+                     }
+                   /*
+                    * Fill in missing information for debugged 
+                    * object file only if we have line number info.
+                    */
+                   if (main_aux.x_scn.x_nlinno > 0)
+                     {
+                       complete_symtab (filestring, cs->c_value,
+                                         main_aux.x_scn.x_scnlen);
+                     }
+                   break;
+                 }
+               else if (strcmp (cs->c_name, _DATA) == 0)
+                 break;
+               else if (strcmp (cs->c_name, _BSS) == 0)
+                 break;
+
+               /* get rid of assembly labels here */
+               /* record_misc_function (cs->c_name, cs->c_value); */
+               break;
+             }
+           (void) process_coff_symbol (cs, &main_aux);
+           break;
+
+         case C_FCN:
+           if (strcmp (cs->c_name, ".bf") == 0)
+             {
+               /* 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;
+             }
+           else if (strcmp (cs->c_name, ".ef") == 0)
+             {
+               /* value contains address of exit/return from function */
+                       /* round it up to next multiple of 16 */
+               cs->c_value = (cs->c_value + 15) & -16;
+               /* { 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;
+               finish_block (new->name, &local_symbols, new->old_blocks,
+                             new->start_addr, cs->c_value);
+               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.");
+               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);
+}
+\f
+/* 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;
+
+  if (BADMAG(file_hdr))
+    return -1;                 /* Non understood file */
+  return file_hdr->f_nsyms;    /* OK magic number, return # syms */
+}
+
+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;
+
+#ifdef DEBUG
+  if (debug) {
+    fprintf(stderr, "sym %3x: %2x %s %x %x %x", cs->c_symnum,
+         cs->c_sclass, cs->c_name, cs->c_value, cs->c_secnum, cs->c_type);
+    if (cs->c_nsyms > 1)
+      fprintf(stderr, " +aux %s\n", (char *)aux);
+    else
+      fprintf(stderr, "\n");
+  }
+#endif
+
+  symnum += cs->c_nsyms;
+}
+\f
+/* Support for string table handling */
+
+static char *stringtab = NULL;
+
+static int
+init_stringtab (chan, offset)
+    int chan;
+    long offset;
+{
+  long buffer;
+  int val;
+
+  if (lseek (chan, offset, 0) < 0)
+    return -1;
+
+  val = myread (chan, (char *)&buffer, sizeof buffer);
+
+  /* If no string table, we get 0 bytes back from the read.  That's OK. */
+  if (val == 0) {
+    free_stringtab();
+    return 0;
+  }
+
+  if (val != sizeof buffer)
+    return -1;
+
+  if (stringtab)
+    free (stringtab);
+  stringtab = (char *) xmalloc (buffer);
+  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)
+    {
+      if (!stringtab)
+       error("Symbol entry references nonexistent string table");
+      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 mac_aux
+  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);
+    }
+}
+\f
+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);
+                   }
+               }
+           }
+       }
+    }
+}
+\f
+static struct symbol *
+process_coff_symbol (cs, aux)
+     register struct coff_symbol *cs;
+     register AUXENT *aux;
+{
+  register struct symbol *sym = (struct symbol *)
+                               xmalloc (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) = savestring (name, strlen (name));
+
+  /* default assumptions */
+  SYMBOL_VALUE (sym) = cs->c_value;
+  SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+
+  if (ISFCN (cs->c_type))
+    {
+      SYMBOL_TYPE (sym) = 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;
+}
+\f
+/* 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);
+}
+\f
+/* 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:
+       /* NULL seems to be used as the basic type of void functions */
+       return builtin_type_void;       
+       break;
+
+      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 ", "<opaque>", "");
+           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 ", "<opaque>", "");
+           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, name %s\n", c_type, cs->c_symnum,
+       cs->c_name);
+  return builtin_type_void;
+}
+\f
+/* 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;
+
+  type = coff_alloc_type (index);
+  TYPE_CODE (type) = TYPE_CODE_STRUCT;
+  TYPE_LENGTH (type) = length;
+
+  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_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:
+           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;
+}
+\f
+/* 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) = SYMBOL_VALUE (syms->symbol);
+      TYPE_FIELD_BITPOS (type, n) = 0;
+      TYPE_FIELD_BITSIZE (type, n) = 0;
+    }
+  return type;
+}
+
+static
+initialize ()
+{
+  symfile = 0;
+
+  add_com ("symbol-file", class_files, symbol_file_command,
+          "Load symbol table (in coff format) from executable file FILE.");
+}
+
+END_FILE
+
+#endif /* COFF_FORMAT */
+
diff --git a/gdb/command.c b/gdb/command.c
new file mode 100644 (file)
index 0000000..fed5ff9
--- /dev/null
@@ -0,0 +1,454 @@
+/* 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 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.
+
+  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) cause each such copy to be accompanied by the
+    corresponding machine-readable source code, which must
+    be distributed under the terms of Paragraphs 1 and 2 above; or,
+
+    b) cause each such copy to be accompanied by a
+    written offer, with no time limit, to give any third party
+    free (except for a nominal shipping charge) a machine readable
+    copy of the corresponding source code, to be distributed
+    under the terms of Paragraphs 1 and 2 above; or,
+
+    c) in the case of a recipient of this program in compiled, executable
+    or object code form (without the corresponding source code) you
+    shall cause copies you distribute to be accompanied by a copy
+    of the written offer of source code which you received along
+    with the copy you received.
+
+  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!  */
+
+
+#include "command.h"
+#include <stdio.h>
+
+extern char *xmalloc ();
+
+static char *savestring ();
+
+/* Add element named NAME to command list *LIST.
+   FUN should be the function to execute the command;
+   it will get a character string as argument, with leading
+   and trailing blanks already eliminated.
+
+   DOC is a documentation string for the command.
+   Its first line should be a complete sentence.
+   It should start with ? for a command that is an abbreviation
+   or with * for a command that most users don't need to know about.  */
+
+struct cmd_list_element *
+add_cmd (name, class, fun, doc, list)
+     char *name;
+     int class;
+     void (*fun) ();
+     char *doc;
+     struct cmd_list_element **list;
+{
+  register struct cmd_list_element *c
+    = (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
+
+  delete_cmd (name, list);
+  c->next = *list;
+  c->name = savestring (name, strlen (name));
+  c->class = class;
+  c->function = fun;
+  c->doc = doc;
+  c->prefixlist = 0;
+  c->allow_unknown = 0;
+  c->abbrev_flag = 0;
+  c->aux = 0;
+  *list = c;
+  return c;
+}
+
+struct cmd_list_element *
+add_alias_cmd (name, oldname, class, abbrev_flag, list)
+     char *name;
+     char *oldname;
+     int class;
+     int abbrev_flag;
+     struct cmd_list_element **list;
+{
+  /* Must do this since lookup_cmd tries to side-effect its first arg */
+  char *copied_name;
+  register struct cmd_list_element *old;
+  register struct cmd_list_element *c;
+  copied_name = (char *) alloca (strlen (oldname) + 1);
+  strcpy (copied_name, oldname);
+  old  = lookup_cmd (&copied_name, *list, 0, 1);
+
+  if (old == 0)
+    {
+      delete_cmd (name, list);
+      return 0;
+    }
+
+  c = add_cmd (name, class, old->function, old->doc, list);
+  c->prefixlist = old->prefixlist;
+  c->prefixname = old->prefixname;
+  c->allow_unknown = old->allow_unknown;
+  c->abbrev_flag = abbrev_flag;
+  c->aux = old->aux;
+  return c;
+}
+
+/* Like add_prefix_cmd but adds an element for a command prefix:
+   a name that should be followed by a subcommand to be looked up
+   in another command list.  PREFIXLIST should be the address
+   of the variable containing that list.  */
+
+struct cmd_list_element *
+add_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
+               allow_unknown, list)
+     char *name;
+     int class;
+     void (*fun) ();
+     char *doc;
+     struct cmd_list_element **prefixlist;
+     char *prefixname;
+     int allow_unknown;
+     struct cmd_list_element **list;
+{
+  register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
+  c->prefixlist = prefixlist;
+  c->prefixname = prefixname;
+  c->allow_unknown = allow_unknown;
+  return c;
+}
+
+/* Remove the command named NAME from the command list.  */
+
+void
+delete_cmd (name, list)
+     char *name;
+     struct cmd_list_element **list;
+{
+  register struct cmd_list_element *c;
+
+  while (*list && !strcmp ((*list)->name, name))
+    {
+      *list = (*list)->next;
+    }
+
+  if (*list)
+    for (c = *list; c->next;)
+      {
+       if (!strcmp (c->next->name, name))
+         c->next = c->next->next;
+       else
+         c = c->next;
+      }
+}
+
+/* Implement a help command on command list LIST.
+   COMMAND is the argument given (a command from the list to document)
+   or zero for no arg (describe briefly all the commands in the list).
+   CMDTYPE is a string to use in the error message if command COMMAND
+   is not found in the list.  */
+
+/* CLASS should be -1 to list all commands in LIST,
+   or a nonnegative class number value to list just commands in that class,
+   or -2 to list the classes themselves.  */
+
+void
+help_cmd (command, list, cmdtype, class, stream)
+     char *command;
+     struct cmd_list_element *list;
+     char *cmdtype;
+     int class;
+     FILE *stream;
+{
+  register struct cmd_list_element *c;
+  register char *p;
+  register int ncmds;
+  struct cmdvec { struct cmd_list_element *cmd; int class; };
+  register struct cmdvec *cmdvec;
+  char *cmdtype1, *cmdtype2;
+  int len;
+
+  if (command)
+    {
+      c = lookup_cmd (&command, list, cmdtype, 0);
+      if (c == 0)
+       return;
+
+      /* There are three cases here.
+        If c->prefixlist is nonzer, we have a prefix command.
+        Print its documentation, then list its subcommands.
+
+        If c->function is nonzero, we really have a command.
+        Print its documentation and return.
+
+        If c->function is zero, we have a class name.
+        Print its documentation (as if it were a command)
+        and then set class to he number of this class
+        so that the commands in the class will be listed.  */
+
+      p = c->doc;
+      fprintf (stream, "%s\n", p);
+      if (c->function != 0 && c->prefixlist == 0)
+       return;
+      fputc ('\n', stream);
+      if (c->prefixlist)
+       {
+         list = *c->prefixlist;
+         class = 0;
+         cmdtype = c->prefixname;
+       }
+      else
+       class = c->class;
+    }
+
+  /* If CMDTYPE is "foo ", CMDTYPE1 gets " foo" and CMDTYPE2 gets "foo sub"  */
+  len = strlen (cmdtype);
+  cmdtype1 = (char *) alloca (len + 1);
+  cmdtype1[0] = 0;
+  cmdtype2 = (char *) alloca (len + 4);
+  cmdtype2[0] = 0;
+  if (len)
+    {
+      cmdtype1[0] = ' ';
+      strncpy (cmdtype1 + 1, cmdtype, len - 1);
+      cmdtype1[len] = 0;
+      strncpy (cmdtype2, cmdtype, len - 1);
+      strcpy (cmdtype2 + len - 1, " sub");
+    }
+
+  if (class == -2)
+    fprintf (stream, "List of classes of %scommands:\n\n", cmdtype2);
+  else
+    fprintf (stream, "List of %scommands:\n\n", cmdtype2);
+
+  for (c = list; c; c = c->next)
+    {
+      if (c->abbrev_flag == 0
+         && (class == -1       /* Listing all */
+             || (c->class == class && c->function != 0) /* Listing one class */
+             || (class == -2 && c->function == 0)))    /* Listing the classes */
+       {
+         fprintf (stream, "%s -- ", c->name);
+         /* Print just first line of documentation.  */
+         p = c->doc;
+         while (*p && *p != '\n') p++;
+         fwrite (c->doc, 1, p - c->doc, stream);
+         fputc ('\n', stream);
+       }
+    }
+
+  if (class == -2)
+    fprintf (stream, "\n\
+Type \"help%s\" followed by a class name for a list of commands in that class.",
+            cmdtype1);
+
+  fprintf (stream, "\n\
+Type \"help%s\" followed by %scommand name for full documentation.\n\
+Command name abbreviations are allowed if unambiguous.\n",
+          cmdtype1, cmdtype2);
+}
+\f
+/* Look up the contents of *LINE as a command in the command list LIST.
+   LIST is a chain of struct cmd_list_element's.
+   If it is found, return the struct cmd_list_element for that command
+   and update *LINE to point after the command name, at the first argument.
+   If not found, call error if ALLOW_UNKNOWN is zero
+   otherwise (or if error returns) return zero.
+   Call error if specified command is ambiguous,
+   unless ALLOW_UNKNOWN is negative.
+   CMDTYPE precedes the word "command" in the error message.  */
+
+struct cmd_list_element *
+lookup_cmd (line, list, cmdtype, allow_unknown)
+     char **line;
+     struct cmd_list_element *list;
+     char *cmdtype;
+     int allow_unknown;
+{
+  register char *p;
+  register struct cmd_list_element *c, *found;
+  int nfound;
+  char ambbuf[100];
+
+  /* Skip leading whitespace.  */
+
+  while (**line == ' ' || **line == '\t')
+    (*line)++;
+
+  /* Clear out trailing whitespace.  */
+
+  p = *line + strlen (*line);
+  while (p != *line && (p[-1] == ' ' || p[-1] == '\t'))
+    p--;
+  *p = 0;
+
+  /* Find end of command name.  */
+
+  p = *line;
+  while (*p == '-'
+        || (*p >= 'a' && *p <= 'z')
+        || (*p >= 'A' && *p <= 'Z')
+        || (*p >= '1' && *p <= '9'))
+    {
+      if (*p >= 'A' && *p <= 'Z')
+       *p += 'a' - 'A';
+      p++;
+    }
+
+  /* Look up the command name.
+     If exact match, keep that.
+     Otherwise, take command abbreviated, if unique.  */
+
+  found = 0;
+  nfound = 0;
+  for (c = list; c; c = c->next)
+    {
+      if (!strncmp (*line, c->name, p - *line))
+       {
+         found = c;
+         nfound++;
+         if (c->name[p - *line] == 0)
+           {
+             nfound = 1;
+             break;
+           }
+       }
+    }
+
+  /* Report error for undefined command name.  */
+
+  if (nfound != 1)
+    {
+      if (nfound > 1 && allow_unknown >= 0)
+       {
+         *p = 0;
+         ambbuf[0] = 0;
+         for (c = list; c; c = c->next)
+           if (!strncmp (*line, c->name, p - *line))
+             {
+               if (strlen (ambbuf) + strlen (c->name) + 6 < sizeof ambbuf)
+                 {
+                   if (strlen (ambbuf))
+                     strcat (ambbuf, ", ");
+                   strcat (ambbuf, c->name);
+                 }
+               else
+                 {
+                   strcat (ambbuf, "..");
+                   break;
+                 }
+             }
+         error ("Ambiguous %scommand \"%s\": %s.", cmdtype, *line, ambbuf);
+       }
+      else if (!allow_unknown)
+       {
+         *p = 0;
+         error ("Undefined %scommand: \"%s\".", cmdtype, *line);
+       }
+      return 0;
+    }
+
+  /* Skip whitespace before the argument.  */
+
+  while (*p == ' ' || *p == '\t') p++;
+  *line = p;
+
+  if (found->prefixlist && *p)
+    {
+      c = lookup_cmd (line, *found->prefixlist, found->prefixname,
+                     found->allow_unknown);
+      if (c)
+       return c;
+    }
+
+  return found;
+}
+
+/* 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.  */
+
+static char *
+savestring (ptr, size)
+     char *ptr;
+     int size;
+{
+  register char *p = (char *) xmalloc (size + 1);
+  bcopy (ptr, p, size);
+  p[size] = 0;
+  return p;
+}
diff --git a/gdb/command.h b/gdb/command.h
new file mode 100644 (file)
index 0000000..687741c
--- /dev/null
@@ -0,0 +1,154 @@
+/* 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 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.
+
+  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) cause each such copy to be accompanied by the
+    corresponding machine-readable source code, which must
+    be distributed under the terms of Paragraphs 1 and 2 above; or,
+
+    b) cause each such copy to be accompanied by a
+    written offer, with no time limit, to give any third party
+    free (except for a nominal shipping charge) a machine readable
+    copy of the corresponding source code, to be distributed
+    under the terms of Paragraphs 1 and 2 above; or,
+
+    c) in the case of a recipient of this program in compiled, executable
+    or object code form (without the corresponding source code) you
+    shall cause copies you distribute to be accompanied by a copy
+    of the written offer of source code which you received along
+    with the copy you received.
+
+  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!  */
+
+
+/* This structure records one command'd definition.  */
+
+struct cmd_list_element
+  {
+    /* Points to next command in this list.  */
+    struct cmd_list_element *next;
+
+    /* Name of this command.  */
+    char *name;
+
+    /* Command class; class values are chosen by application program.  */
+    int class;
+
+    /* Function definition of this command.
+       Zero for command class names and for help topics that
+       are not really commands.  */
+    void (*function) ();
+
+    /* Documentation of this command (or help topic).
+       First line is brief documentation; remaining lines form, with it,
+       the full documentation.  First line should end with a period.
+       Entire string should also end with a period, not a newline.  */
+    char *doc;
+
+    /* Auxiliary information.
+       It is up to the calling program to decide what this means.  */
+    char *aux;
+
+    /* Nonzero identifies a prefix command.  For them, the address
+       of the variable containing the list of subcommands.  */
+    struct cmd_list_element **prefixlist;
+
+    /* For prefix commands only:
+       String containing prefix commands to get here: this one
+       plus any others needed to get to it.  Should end in a space.
+       It is used before the word "command" in describing the
+       commands reached through this prefix.  */
+    char *prefixname;
+
+    /* For prefix commands only:
+       nonzero means do not get an error if subcommand is not
+       recognized; call the prefix's own function in that case.  */
+    char allow_unknown;
+
+    /* Nonzero says this is an abbreviation, and should not
+       be mentioned in lists of commands.  */
+    char abbrev_flag;
+  };
+
+/* Forward-declarations of the entry-points of command.c.  */
+
+extern struct cmd_list_element *add_cmd ();
+extern struct cmd_list_element *add_alias_cmd ();
+extern struct cmd_list_element *add_prefix_cmd ();
+extern struct cmd_list_element *lookup_cmd ();
+extern void delete_cmd ();
+extern void help_cmd ();
diff --git a/gdb/core.c b/gdb/core.c
new file mode 100644 (file)
index 0000000..7d3c68c
--- /dev/null
@@ -0,0 +1,717 @@
+/* Work with core dump and executable files, 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 "initialize.h"
+#include "defs.h"
+#include "param.h"
+
+#include <a.out.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+
+/* Recognize COFF format systems because a.out.h defines AOUTHDR.  */
+#ifdef AOUTHDR
+#define COFF_FORMAT
+#endif
+
+#ifdef NEW_SUN_CORE
+#include <sys/core.h>
+#else /* not NEW_SUN_CORE */
+#ifdef UMAX_CORE
+#include <sys/ptrace.h>
+#else /* not UMAX_CORE */
+#ifdef mac_aux
+#include <sys/seg.h>
+#include <sys/mmu.h>
+#include <sys/signal.h>
+#include <sys/time.h>
+#include <sys/user.h>
+#else
+#include <sys/user.h>
+#endif /* mac_aux */
+#endif /* UMAX_CORE */
+#endif /* NEW_SUN_CORE */
+
+#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
+
+START_FILE
+
+/* Hook for `exec_file_command' command to call.  */
+
+void (*exec_file_display_hook) ();
+   
+/* File names of core file and executable file.  */
+
+static char *corefile;
+static 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.  */
+
+static int corechan;
+static 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.  */
+
+static CORE_ADDR data_start;
+static CORE_ADDR data_end;
+static CORE_ADDR stack_start;
+static 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.  */
+
+static CORE_ADDR text_start;
+static CORE_ADDR text_end;
+static CORE_ADDR exec_data_start;
+static CORE_ADDR exec_data_end;
+
+/* Address in executable file of start of text area data.  */
+
+static int text_offset;
+
+/* Address in executable file of start of data area data.  */
+
+static int exec_data_offset;
+
+/* Address in core file of start of data area data.  */
+
+static int data_offset;
+
+/* Address in core file of start of stack area data.  */
+
+static int stack_offset;
+  
+#ifdef COFF_FORMAT
+/* various coff data structures */
+
+static FILHDR file_hdr;
+static SCNHDR text_hdr;
+static SCNHDR data_hdr;
+
+#endif /* not COFF_FORMAT */
+
+/* a.out header saved in core file.  */
+  
+static AOUTHDR core_aouthdr;
+
+/* a.out header of exec file.  */
+
+static AOUTHDR exec_aouthdr;
+
+static void validate_files ();
+unsigned int register_addr ();
+\f
+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);
+#ifdef NEW_SUN_CORE
+      {
+       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));
+
+       data_start = exec_data_start;
+       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;
+
+       bcopy (&corestr.c_regs, registers, 16 * 4);
+       *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps;
+       *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc;
+       bcopy (corestr.c_fpstatus.fps_regs,
+              &registers[REGISTER_BYTE (FP0_REGNUM)],
+              sizeof corestr.c_fpstatus.fps_regs);
+       bcopy (&corestr.c_fpstatus.fps_control,
+              &registers[REGISTER_BYTE (FPC_REGNUM)],
+              sizeof corestr.c_fpstatus - sizeof corestr.c_fpstatus.fps_regs);
+
+       bcopy (&corestr.c_aouthdr, &core_aouthdr, sizeof (struct exec));
+
+       printf ("Core file is from \"%s\".\n", corestr.c_cmdname);
+      }
+#else /* not NEW_SUN_CORE */
+      /* 4.2-style (and perhaps also sysV-style) core dump file.  */
+      {
+#ifdef UMAX_CORE
+       struct ptrace_user u;
+#else
+       struct user u;
+#endif
+       int reg_offset;
+
+       val = myread (corechan, &u, sizeof u);
+       if (val < 0)
+         perror_with_name (filename);
+       data_start = exec_data_start;
+
+#ifdef UMAX_CORE
+       data_end = data_start + u.pt_dsize;
+       stack_start = stack_end - u.pt_ssize;
+       data_offset = sizeof u;
+       stack_offset = data_offset + u.pt_dsize;
+       reg_offset = 0;
+
+       bcopy (&u.pt_aouthdr, &core_aouthdr, sizeof (AOUTHDR));
+
+#else /* not UMAX_CORE */
+#ifdef mac_aux
+       /* This may well not work for 0407 (nonshared text) a.out's */
+       data_end = data_start + u.u_dsize << PAGESHIFT;
+       stack_start = stack_end - u.u_ssize << PAGESHIFT;
+       data_offset = USIZE;
+       stack_offset = USIZE + u.u_dsize << PAGESHIFT;
+       reg_offset = (int) &u.u_ar0[0] - (int) &u;
+
+       core_aouthdr.a_magic = u.u_exdata.ux_mag;
+#else
+       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.  */
+       core_aouthdr.a_magic = 0;
+#endif /* not mac_aux */
+#endif /* not UMAX_CORE */
+
+       /* 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);
+           }
+       }
+      }
+#endif /* not NEW_SUN_CORE */
+      if (filename[0] == '/')
+       corefile = savestring (filename, strlen (filename));
+      else
+       {
+         char dirname[MAXPATHLEN];
+
+         getwd (dirname);
+         corefile = concat (dirname, "/", filename);
+       }
+
+      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");
+}
+\f
+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);
+
+#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_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;
+
+       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 ? filename : "No executable specified.\n");
+}
+
+/* Call this to specify the hook for exec_file_command to call back.
+   This is called from the x-window display code.  */
+
+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.  */
+
+close_exec_file ()
+{
+  if (execchan >= 0)
+    close (execchan);
+  execchan = -1;
+}
+
+reopen_exec_file ()
+{
+  if (execchan < 0 && execfile != 0)
+    {
+      char *filename = concat (execfile, "", "");
+      exec_file_command (filename, 0);
+      free (filename);
+    }
+}
+\f
+/* 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.  */
+
+static void
+validate_files ()
+{
+  if (execfile != 0 && corefile != 0)
+    {
+      struct stat st_core;
+
+      fstat (corechan, &st_core);
+
+      if (core_aouthdr.a_magic != 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");
+    }
+}
+
+char *
+get_exec_file ()
+{
+  if (execfile == 0)
+    error ("No executable file specified.\n\
+Use the \"exec-file\" and \"symbol-file\" commands.");
+  return execfile;
+}
+
+int
+have_core_file_p ()
+{
+  return corefile != 0;
+}
+
+static void
+files_info ()
+{
+  char *symfile;
+  extern char *get_sym_file ();
+
+  if (execfile)
+    printf ("Executable file \"%s\".\n", execfile);
+  else
+    printf ("No executable file\n");
+  if (corefile == 0)
+    printf ("No core dump file\n");
+  else
+    printf ("Core dump file \"%s\".\n", corefile);
+
+  if (have_inferior_p ())
+    printf ("Using the running image of the program, rather than these files.\n");
+
+  symfile = get_sym_file ();
+  if (symfile != 0)
+    printf ("Symbols loaded from \"%s\".\n", symfile);
+
+  if (! have_inferior_p ())
+    {
+      if (execfile)
+       {
+         printf ("Text segment from 0x%x to 0x%x.\n",
+                 text_start, text_end);
+       }
+      if (corefile)
+       {
+         printf ("Data segment from 0x%x to 0x%x.\nStack segment from 0x%x to 0x%x.\n",
+                 data_start, data_end, stack_start, stack_end);
+       }
+      else
+       {
+         printf ("Data segment in executable from 0x%x to 0x%x.\n",
+                 exec_data_start, exec_data_end);
+       }
+    }
+}
+\f
+/* Read "memory data" from core file and/or executable file */
+
+read_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  if (have_inferior_p ())
+    read_inferior_memory (memaddr, myaddr, len);
+  else
+    xfer_core_file (memaddr, myaddr, len, 0);
+}
+
+/* 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.");
+}
+
+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;
+
+  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.  */
+
+      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);
+       }
+      /* Note that if there is no core file
+        data_start and data_end are equal.  */
+      else 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;
+       }
+
+      /* 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);
+
+      memaddr += i;
+      myaddr += i;
+      len -= i;
+    }
+}
+\f
+/* My replacement for the read system call.
+   Used like `read' but keeps going if `read' returns too soon.  */
+
+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;
+    }
+}
+\f
+#ifndef NEW_SUN_CORE
+
+/* 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);
+
+#ifdef mac_aux
+/* FIXME, we don't know where the regs are.  Maybe the test command
+ * that tests what parts of the upage are writeable will find 'em for us.
+ */
+#define REGISTER_U_ADDR(addr, foo, bar)  addr = 0;
+#endif
+  REGISTER_U_ADDR (addr, blockend, regno);
+
+  return addr;
+}
+
+#endif /* not NEW_SUN_CORE */
+\f
+static
+initialize ()
+{
+  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.");
+}
+
+END_FILE
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
new file mode 100644 (file)
index 0000000..007e768
--- /dev/null
@@ -0,0 +1,2183 @@
+/* Read dbx symbol tables and convert to internal format, 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!
+*/
+\f
+#include "param.h"
+
+#ifdef READ_DBX_FORMAT
+
+#include <a.out.h>
+#include <stab.h>
+#include <stdio.h>
+#include <obstack.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include "defs.h"
+#include "initialize.h"
+#include "symtab.h"
+
+static void add_symbol_to_list ();
+static void read_dbx_symtab ();
+static void process_one_symbol ();
+static struct type *read_type ();
+static struct type *read_range_type ();
+static struct type *read_enum_type ();
+static struct type *read_struct_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 ();
+
+START_FILE
+
+/* 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;
+
+/* The addresses of the symbol table stream and the string table
+   of the object file we are reading (as copied into core).  */
+
+static FILE *nlist_stream_global;
+static int nlist_size_global;
+static char *stringtab_global;
+
+/* The index in nlist_global of the last dbx symbol to be processed.  */
+
+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;
+
+/* Chain 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.  */
+
+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;
+\f
+/* 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;
+
+/* 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 *) xmalloc (10 * sizeof (struct header_file));
+  n_header_files = 0;
+
+  n_allocated_this_object_header_files = 10;
+  this_object_header_files = (int *) xmalloc (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);
+  free (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 = name;
+  header_files[i].instance = instance;
+  header_files[i].length = 10;
+  header_files[i].vector
+    = (struct type **) xmalloc (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_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
+\f
+/* 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;
+}
+\f
+/* Manage the vector of line numbers.  */
+
+static
+record_line (line, pc)
+     int line;
+     CORE_ADDR pc;
+{
+  /* 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 (int));
+      current_subfile->line_vector = line_vector;
+    }
+
+  /* If this line is not continguous with previous one recorded,
+     record a line-number entry for it.  */
+  if (line != prev_line_number + 1)
+    line_vector->item[line_vector_index++] = - line;
+  prev_line_number = line;
+
+  /* Record the core address of the line.  */
+  line_vector->item[line_vector_index++] = pc;
+}
+\f
+/* 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;
+  context_stack = 0;
+  within_function = 0;
+
+  new_object_header_files ();
+
+  for (s = symseg_chain; s; s = s->next)
+    if (s->ldsymoff == symnum * sizeof (struct nlist))
+      break;
+  current_symseg = s;
+
+  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 *));
+
+  /* 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);
+}
+
+/* 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 *)
+    xmalloc (sizeof (struct linetable) + line_vector_length * sizeof (int));
+
+  /* Make an entry for this subfile in the list of all subfiles
+     of the current main source file.  */
+
+  subfile = (struct subfile *) xmalloc (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 context_stack *cstk;
+  register struct blockvector *blockvector;
+  register struct subfile *subfile;
+  register struct linetable *lv;
+  struct subfile *nextsub;
+
+  /* Finish the lexical context of the last function in the file.  */
+
+  if (context_stack)
+    {
+      cstk = context_stack;
+      /* Make a block for the local symbols within.  */
+      finish_block (cstk->name, &local_symbols, cstk->old_blocks,
+                   cstk->start_addr, end_addr);
+      free (cstk);
+    }
+
+  /* Finish defining all the blocks of this symtab.  */
+  if (current_symseg == 0)
+    {
+      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 *) xmalloc (sizeof (struct symtab));
+      /* Fill in its components.  */
+      if (current_symseg)
+       {
+         bcopy (current_symseg, symtab, sizeof (struct symtab));
+         symtab->free_code = free_linetable;
+         symtab->free_ptr = 0;
+       }
+      else
+       {
+         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 (int));
+      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;
+}
+\f
+#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 *) xmalloc (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 */
+\f
+/* 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 = 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;
+    }
+}
+
+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++)
+       {
+         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 = j;
+
+  /* Sort the misc functions by address.  */
+
+  qsort (misc_function_vector, j, sizeof (struct misc_function),
+        compare_misc_functions);
+}
+\f
+/* 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);
+         qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
+                sizeof (struct symbol *), compare_symbols);
+       }
+    }
+}
+\f
+/* 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;
+  struct exec hdr;
+  struct nlist *nlist;
+  char *stringtab;
+  long buffer;
+  register int val;
+  extern void close ();
+  struct cleanup *old_chain;
+
+  dont_repeat ();
+
+  if (name == 0)
+    {
+      if (symtab_list && !query ("Discard symbol table? ", 0))
+       error ("Not confirmed.");
+      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);
+
+  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);
+
+  if (hdr.a_syms == 0)
+    {
+      free_all_symtabs ();
+      printf ("%s does not have a symbol-table.\n", name);
+      fflush (stdout);
+      return;
+    }
+
+  /* Now read the string table, all at once.  */
+  val = lseek (desc, N_SYMOFF (hdr) + hdr.a_syms, 0);
+  if (val < 0)
+    perror_with_name (name);
+  val = myread (desc, &buffer, sizeof buffer);
+  if (val < 0)
+    perror_with_name (name);
+  stringtab = (char *) alloca (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 ();
+#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, N_SYMOFF (hdr), 0);
+  if (val < 0)
+    perror_with_name (name);
+
+  printf ("Reading symbol data from %s...", name);
+  fflush (stdout);
+
+  /* Throw away the old symbol table.  */
+
+  free_all_symtabs ();
+
+  init_misc_functions ();
+  make_cleanup (discard_misc_bunches, 0);
+  init_header_files ();
+  make_cleanup (free_header_files, 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, hdr.a_syms / sizeof (struct nlist));
+
+  /* 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);
+
+  /* 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);
+}
+
+/* Return name of file symbols were loaded from, or 0 if none..  */
+
+char *
+get_sym_file ()
+{
+  return symfile;
+}
+\f
+/* Given pointers to a a.out symbol table in core containing  dbx style data,
+   analyze them and create struct symtab's describing the symbols.
+   NLISTLEN is the number of symbols in the symbol table.
+   We read them one at a time using stdio.
+   All symbol names are given as offsets relative to STRINGTAB.  */
+
+static void
+read_dbx_symtab (desc, stringtab, nlistlen)
+     int desc;
+     register char *stringtab;
+     register int nlistlen;
+{
+  FILE *stream = fdopen (desc, "r");
+  struct nlist buf;
+  register char *namestring;
+  register struct symbol *sym, *prev;
+  int hash;
+  int num_object_files = 0;
+
+#ifdef N_BINCL
+  subfile_stack = 0;
+#endif
+
+  nlist_stream_global = stream;
+  nlist_size_global = nlistlen;
+  stringtab_global = stringtab;
+  last_source_file = 0;
+  bzero (global_sym_chain, sizeof global_sym_chain);
+
+  for (symnum = 0; symnum < nlistlen; symnum++)
+    {
+      fread (&buf, sizeof buf, 1, stream);
+      namestring = buf.n_un.n_strx ? buf.n_un.n_strx + stringtab : "";
+      if (buf.n_type & N_STAB)
+       process_one_symbol (buf.n_type, buf.n_desc,
+                           buf.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 (buf.n_type == N_TEXT
+              && !strcmp (namestring + strlen (namestring) - 2, ".o"))
+       {
+         if (num_object_files++ == 1)
+           first_object_file_end = buf.n_value;
+         if (last_source_file)
+           end_symtab (buf.n_value);
+       }
+      else if (buf.n_type & N_EXT || buf.n_type == N_TEXT)
+       {
+         int used_up = 0;
+
+         /* Record the location of _etext.  */
+         if (buf.n_type == (N_TEXT | N_EXT)
+             && !strcmp (namestring, "_etext"))
+           end_of_text_addr = buf.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 (buf.n_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) = buf.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 (buf.n_type <= (N_TYPE | N_EXT)
+             && buf.n_type != N_EXT
+             && ! used_up)
+           record_misc_function (namestring, buf.n_value);
+       }
+    }
+
+  if (last_source_file)
+    end_symtab (end_of_text_addr);
+
+  fclose (stream);
+}
+
+/* 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 ()
+{
+  struct nlist buf;
+  fread (&buf, sizeof buf, 1, nlist_stream_global);
+  symnum++;
+  return buf.n_un.n_strx + stringtab_global;
+}
+
+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;
+}
+
+/* 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;
+               }
+           }
+       }
+    }
+}
+\f
+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.  */
+  
+#ifdef N_NSYMS
+  if (type == N_NSYMS) return;
+#endif
+
+  if (type != N_SO && last_source_file == 0)
+    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.  */
+      new = context_stack;
+      within_function = 1;
+      if (new)
+       {
+         /* Make a block for the local symbols within.  */
+         finish_block (new->name, &local_symbols, new->old_blocks,
+                       new->start_addr, value);
+       }
+      else
+       {
+         new = (struct context_stack *) xmalloc (sizeof (struct context_stack));
+         new->next = 0;
+         new->depth = -1;
+         context_stack = new;
+       }
+      new->locals = 0;
+      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.  */
+      new = (struct context_stack *) xmalloc (sizeof (struct context_stack));
+      new->depth = desc;
+      new->next = context_stack;
+      context_stack = new;
+      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;
+      if (new == 0 || desc != new->depth)
+       error ("Invalid symbol data: N_LBRAC/N_RBRAC symbol mismatch, symtab pos %d.", symnum);
+      local_symbols = new->locals;
+      context_stack = new->next;
+      /* 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->next)
+       {
+         /* 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);
+       }
+      free (new);
+      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;
+
+    default:
+      if (name)
+       define_symbol (value, name, desc);
+    }
+}
+\f
+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;
+
+  bzero (sym, sizeof (struct symbol));
+  SYMBOL_NAME (sym) = obstack_copy0 (symbol_obstack, string, p - string);
+  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
+    SYMBOL_TYPE (sym) = read_type (&p);
+
+  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 '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)) = concat (SYMBOL_NAME (sym), "", "");
+      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))
+         = concat ("",
+                   (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;
+}
+\f
+/* 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.  */
+      *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 '*':
+      type = dbx_alloc_type (typenums);
+      smash_to_pointer_type (type, read_type (pp));
+      break;
+
+    case 'f':
+      type = dbx_alloc_type (typenums);
+      smash_to_function_type (type, read_type (pp));
+      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':
+      /* Define an array type.  */
+      type = dbx_alloc_type (typenums);
+
+      /* 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;
+
+    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;
+}
+\f
+/* 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;
+      struct field field;
+    };
+
+  register struct nextfield *list = 0;
+  struct nextfield *new;
+  int totalsize;
+  char *name;
+  register char *p;
+  int nfields = 0;
+  register int n;
+
+  TYPE_CODE (type) = TYPE_CODE_STRUCT;
+
+  /* First comes the total size in bytes.  */
+
+  TYPE_LENGTH (type) = read_number (pp, 0);
+
+  /* Now come the fields, as NAME:TYPENUM,BITPOS,BITSIZE; for each one.
+     At the end, we see a semicolon instead of a field.  */
+
+  while (**pp != ';')
+    {
+      /* 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 = savestring (*pp, p - *pp);
+      *pp = p + 1;
+      list->field.type = read_type (pp);
+      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.
+        Also detect forward refs to structures and unions,
+        and treat enums as if they had the width of ints.  */
+      if ((list->field.bitsize == 8 * TYPE_LENGTH (list->field.type)
+          || TYPE_CODE (list->field.type) == TYPE_CODE_STRUCT
+          || TYPE_CODE (list->field.type) == TYPE_CODE_UNION
+          || (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++;
+    }
+
+  (*pp)++;                     /* Skip the terminating ';'.  */
+
+  /* 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 (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;
+
+  if (within_function)
+    symlist = &local_symbols;
+  else
+    symlist = &file_symbols;
+  osyms = *symlist;
+
+  /* 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 = savestring (*pp, p - *pp);
+      *pp = p + 1;
+      n = read_number (pp, ',');
+      
+      sym = (struct symbol *) xmalloc (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 != osyms; syms = syms->next)
+    {
+      SYMBOL_TYPE (syms->symbol) = type;
+      TYPE_FIELD_NAME (type, --n) = SYMBOL_NAME (syms->symbol);
+      TYPE_FIELD_VALUE (type, n) = SYMBOL_VALUE (syms->symbol);
+      TYPE_FIELD_BITPOS (type, n) = 0;
+      TYPE_FIELD_BITSIZE (type, n) = 0;
+    }
+
+  return type;
+}
+  
+static struct type *
+read_range_type (pp, typenums)
+     char **pp;
+     int typenums[2];
+{
+  char *errp = *pp;
+  int rangenums[2];
+  int n1, n2, n3;
+
+  /* First comes a type we are a subrange of.
+     In practice it is usually 0, 1 or the type being defined.  */
+  read_type_number (pp, rangenums);
+  n1 = rangenums[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 (rangenums[0] == typenums[0] && rangenums[1] == typenums[1]
+      && 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;
+    }
+
+  /* Detect unsigned subranges of int.  Int is normally 1.
+     Note that `char' is usually given bounds of 0 to 127,
+     and would therefore appear unsigned; but it is described
+     as a subrange of itself, so we reject it here.  */
+
+  else if (n2 == 0 && n1 == 1)
+    {
+      /* 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
+    {
+      /* 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;
+    }
+  error ("Invalid symbol data: range type spec %s at symtab pos %d.",
+        errp - 1, symnum);
+}
+
+/* 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 != end)
+       error ("Invalid symbol data: invalid character \\%03o at symbol pos %d.", c, symnum);
+    }
+  else
+    --p;
+
+  *pp = p;
+  return n * sign;
+}
+
+static
+initialize ()
+{
+  symfile = 0;
+
+  add_com ("symbol-file", class_files, symbol_file_command,
+          "Load symbol table (in dbx format) from executable file FILE.");
+}
+
+END_FILE
+
+#endif /* READ_DBX_FORMAT */
diff --git a/gdb/defs.h b/gdb/defs.h
new file mode 100644 (file)
index 0000000..b232972
--- /dev/null
@@ -0,0 +1,75 @@
+/* Basic definitions 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!
+*/
+
+#define CORE_ADDR unsigned int
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+extern char *savestring ();
+extern char *concat ();
+extern char *xmalloc (), *xrealloc ();
+extern int parse_escape ();
+extern char *reg_names[];
+
+extern int quit_flag;
+
+extern int immediate_quit;
+
+#define QUIT { if (quit_flag) quit (); }
+
+enum command_class
+{
+  class_run, class_vars, class_stack, class_files, class_support, class_info,
+  class_breakpoint, class_alias, class_obscure, class_user,
+};
+
+/* the cleanup list records things that have to be undone
+   if an error happens (descriptors to be closed, memory to be freed, etc.)
+   Each link in the chain records a function to call and an
+   argument to give it.
+
+   Use make_cleanup to add an element to the cleanup chain.
+   Use do_cleanups to do all cleanup actions back to a given
+   point in the chain.  Use discard_cleanups to remove cleanups
+   from the chain back to a given point, not doing them.  */
+
+struct cleanup
+{
+  struct cleanup *next;
+  void (*function) ();
+  int arg;
+};
+
+extern void do_cleanups ();
+extern void discard_cleanups ();
+extern struct cleanup *make_cleanup ();
+extern void free_current_contents ();
+
+/* Structure for saved commands lines
+   (for breakpoints, defined commands, etc).  */
+
+struct command_line
+{
+  struct command_line *next;
+  char *line;
+};
+
+struct command_line *read_command_lines ();
diff --git a/gdb/environ.c b/gdb/environ.c
new file mode 100644 (file)
index 0000000..0b9f913
--- /dev/null
@@ -0,0 +1,250 @@
+/* environ.c -- library for manipulating environments for GNU.
+   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 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.
+
+  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) cause each such copy to be accompanied by the
+    corresponding machine-readable source code, which must
+    be distributed under the terms of Paragraphs 1 and 2 above; or,
+
+    b) cause each such copy to be accompanied by a
+    written offer, with no time limit, to give any third party
+    free (except for a nominal shipping charge) a machine readable
+    copy of the corresponding source code, to be distributed
+    under the terms of Paragraphs 1 and 2 above; or,
+
+    c) in the case of a recipient of this program in compiled, executable
+    or object code form (without the corresponding source code) you
+    shall cause copies you distribute to be accompanied by a copy
+    of the written offer of source code which you received along
+    with the copy you received.
+
+  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.  */
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+#include "environ.h"
+\f
+/* Return a new environment object.  */
+
+struct environ *
+make_environ ()
+{
+  register struct environ *e;
+
+  e = (struct environ *) xmalloc (sizeof (struct environ));
+
+  e->allocated = 10;
+  e->vector = (char **) xmalloc ((e->allocated + 1) * sizeof (char *));
+  e->vector[0] = 0;
+  return e;
+}
+
+/* Free an environment and all the strings in it.  */
+
+void
+free_environ (e)
+     register struct environ *e;
+{
+  register char **vector = e->vector;
+
+  while (*vector)
+    free (*vector++);
+
+  free (e);
+}
+
+/* Copy the environment given to this process into E.
+   Also copies all the strings in it, so we can be sure
+   that all strings in these environments are safe to free.  */
+
+void
+init_environ (e)
+     register struct environ *e;
+{
+  extern char **environ;
+  register int i;
+
+  for (i = 0; environ[i]; i++);
+
+  if (e->allocated < i)
+    {
+      e->allocated = max (i, e->allocated + 10);
+      e->vector = (char **) xrealloc (e->vector,
+                                     (e->allocated + 1) * sizeof (char *));
+    }
+
+  bcopy (environ, e->vector, (i + 1) * sizeof (char *));
+
+  while (--i >= 0)
+    {
+      register int len = strlen (e->vector[i]);
+      register char *new = (char *) xmalloc (len + 1);
+      bcopy (e->vector[i], new, len);
+      e->vector[i] = new;
+    }
+}
+
+/* Return the vector of environment E.
+   This is used to get something to pass to execve.  */
+
+char **
+environ_vector (e)
+     struct environ *e;
+{
+  return e->vector;
+}
+\f
+/* Return the value in environment E of variable VAR.  */
+
+char *
+get_in_environ (e, var)
+     struct environ *e;
+     char *var;
+{
+  register int len = strlen (var);
+  register char **vector = e->vector;
+  register char *s;
+
+  for (; s = *vector; vector++)
+    if (!strncmp (s, var, len)
+       && s[len] == '=')
+      return &s[len + 1];
+
+  return 0;
+}
+
+/* Store the value in E of VAR as VALUE.  */
+
+void
+set_in_environ (e, var, value)
+     struct environ *e;
+     char *var;
+     char *value;
+{
+  register int i;
+  register int len = strlen (var);
+  register char **vector = e->vector;
+  register char *s;
+
+  for (i = 0; s = vector[i]; i++)
+    if (!strncmp (s, var, len)
+       && s[len] == '=')
+      break;
+
+  if (s == 0)
+    {
+      if (i == e->allocated)
+       {
+         e->allocated += 10;
+         vector = (char **) xrealloc (vector,
+                                      (e->allocated + 1) * sizeof (char *));
+         e->vector = vector;
+       }
+      vector[i + 1] = 0;
+    }
+  else
+    free (s);
+
+  s = (char *) xmalloc (len + strlen (value) + 2);
+  strcpy (s, var);
+  strcat (s, "=");
+  strcat (s, value);
+  vector[i] = s;
+  return;
+}
+
+/* Remove the setting for variable VAR from environment E.  */
+
+void
+unset_in_environ (e, var)
+     struct environ *e;
+     char *var;
+{
+  register int len = strlen (var);
+  register char **vector = e->vector;
+  register char *s;
+
+  for (; s = *vector; vector++)
+    if (!strncmp (s, var, len)
+       && s[len] == '=')
+      {
+       free (s);
+       bcopy (vector + 1, vector,
+              (e->allocated - (vector - e->vector)) * sizeof (char *));
+       e->vector[e->allocated - 1] = 0;
+       return;
+      }
+}
diff --git a/gdb/environ.h b/gdb/environ.h
new file mode 100644 (file)
index 0000000..5ebeaa2
--- /dev/null
@@ -0,0 +1,23 @@
+
+/* We manipulate environments represented as these structures.  */
+
+struct environ
+{
+  /* Number of usable slots allocated in VECTOR.
+     VECTOR always has one slot not counted here,
+     to hold the terminating zero.  */
+  int allocated;
+  /* A vector of slots, ALLOCATED + 1 of them.
+     The first few slots contain strings "VAR=VALUE"
+     and the next one contains zero.
+     Then come some unused slots.  */
+  char **vector;
+};
+
+struct environ *make_environ ();
+void free_environ ();
+void init_environ ();
+char *get_in_environ ();
+void set_in_environ ();
+void unset_in_environ ();
+char **environ_vector ();
diff --git a/gdb/eval.c b/gdb/eval.c
new file mode 100644 (file)
index 0000000..97f39c3
--- /dev/null
@@ -0,0 +1,556 @@
+/* Evaluate expressions 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 "defs.h"
+#include "initialize.h"
+#include "symtab.h"
+#include "value.h"
+#include "expression.h"
+
+START_FILE
+\f
+/* Parse the string EXP as a C expression, evaluate it,
+   and return the result as a number.  */
+
+CORE_ADDR
+parse_and_eval_address (exp)
+     char *exp;
+{
+  struct expression *expr = parse_c_expression (exp);
+  register CORE_ADDR addr;
+  register struct cleanup *old_chain
+    = make_cleanup (free_current_contents, &expr);
+
+  addr = value_as_long (evaluate_expression (expr));
+  do_cleanups (old_chain);
+  return addr;
+}
+
+/* Like parse_and_eval_address but takes a pointer to a char * variable
+   and advanced that variable across the characters parsed.  */
+
+CORE_ADDR
+parse_and_eval_address_1 (expptr)
+     char **expptr;
+{
+  struct expression *expr = parse_c_1 (expptr, 0);
+  register CORE_ADDR addr;
+  register struct cleanup *old_chain
+    = make_cleanup (free_current_contents, &expr);
+
+  addr = value_as_long (evaluate_expression (expr));
+  do_cleanups (old_chain);
+  return addr;
+}
+
+value
+parse_and_eval (exp)
+     char *exp;
+{
+  struct expression *expr = parse_c_expression (exp);
+  register value val;
+  register struct cleanup *old_chain
+    = make_cleanup (free_current_contents, &expr);
+
+  val = evaluate_expression (expr);
+  do_cleanups (old_chain);
+  return val;
+}
+\f
+/* Evaluate an expression in internal prefix form
+   such as is constructed by expread.y.
+
+   See expression.h for info on the format of an expression.  */
+
+static value evaluate_subexp ();
+static value evaluate_subexp_for_address ();
+static value evaluate_subexp_for_sizeof ();
+static value evaluate_subexp_with_coercion ();
+
+/* Values of NOSIDE argument to eval_subexp.  */
+enum noside
+{ EVAL_NORMAL, 
+  EVAL_SKIP,
+  EVAL_AVOID_SIDE_EFFECTS,
+};
+
+value
+evaluate_expression (exp)
+     struct expression *exp;
+{
+  int pc = 0;
+  return evaluate_subexp (exp, &pc, EVAL_NORMAL);
+}
+
+/* Evaluate an expression, avoiding all memory references
+   and getting a value whose type alone is correct.  */
+
+value
+evaluate_type (exp)
+     struct expression *exp;
+{
+  int pc = 0;
+  return evaluate_subexp (exp, &pc, EVAL_AVOID_SIDE_EFFECTS);
+}
+
+static value
+evaluate_subexp (exp, pos, noside)
+     register struct expression *exp;
+     register int *pos;
+     enum noside noside;
+{
+  enum exp_opcode op;
+  int tem;
+  register int pc;
+  register value arg1, arg2;
+  int nargs;
+  value *argvec;
+
+  pc = (*pos)++;
+  op = exp->elts[pc].opcode;
+
+  switch (op)
+    {
+    case OP_LONG:
+      (*pos) += 3;
+      return value_from_long (exp->elts[pc + 1].type,
+                             exp->elts[pc + 2].longconst);
+
+    case OP_DOUBLE:
+      (*pos) += 3;
+      return value_from_double (exp->elts[pc + 1].type,
+                               exp->elts[pc + 2].doubleconst);
+
+    case OP_VAR_VALUE:
+      (*pos) += 2;
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      return value_of_variable (exp->elts[pc + 1].symbol);
+
+    case OP_LAST:
+      (*pos) += 2;
+      return access_value_history (exp->elts[pc + 1].longconst);
+
+    case OP_REGISTER:
+      (*pos) += 2;
+      return value_of_register (exp->elts[pc + 1].longconst);
+
+    case OP_INTERNALVAR:
+      (*pos) += 2;
+      return value_of_internalvar (exp->elts[pc + 1].internalvar);
+
+    case OP_FUNCALL:
+      (*pos) += 2;
+      nargs = exp->elts[pc + 1].longconst;
+      argvec = (value *) alloca (sizeof (value) * (nargs + 1));
+      for (tem = 0; tem <= nargs; tem++)
+
+       /* Ensure that array expressions are coerced into pointer objects. */
+       argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
+
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+       return allocate_value (TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0])));
+      return call_function (argvec[0], nargs, argvec + 1);
+
+    case OP_STRING:
+      tem = strlen (&exp->elts[pc + 1].string);
+      (*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);
+
+    case TERNOP_COND:
+      /* Skip third and second args to evaluate the first one.  */
+      arg1 = evaluate_subexp (exp, pos, noside);
+      if (value_zerop (arg1))
+       {
+         evaluate_subexp (exp, pos, EVAL_SKIP);
+         return evaluate_subexp (exp, pos, noside);
+       }
+      else
+       {
+         arg2 = evaluate_subexp (exp, pos, noside);
+         evaluate_subexp (exp, pos, EVAL_SKIP);
+         return arg2;
+       }
+
+    case STRUCTOP_STRUCT:
+      tem = strlen (&exp->elts[pc + 1].string);
+      (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
+      arg1 = evaluate_subexp (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      return value_struct_elt (arg1, &exp->elts[pc + 1].string,
+                              "structure");
+
+    case STRUCTOP_PTR:
+      tem = strlen (&exp->elts[pc + 1].string);
+      (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
+      arg1 = evaluate_subexp (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      return value_struct_elt (arg1, &exp->elts[pc + 1].string,
+                              "structure pointer");
+
+    case BINOP_ASSIGN:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      arg2 = evaluate_subexp (exp, pos, noside);
+      if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+       return arg1;
+      return value_assign (arg1, arg2);
+
+    case BINOP_ASSIGN_MODIFY:
+      (*pos) += 2;
+      arg1 = evaluate_subexp (exp, pos, noside);
+      arg2 = evaluate_subexp (exp, pos, noside);
+      if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+       return arg1;
+      op = exp->elts[pc + 1].opcode;
+      if (op == BINOP_ADD)
+       arg2 = value_add (arg1, arg2);
+      else if (op == BINOP_SUB)
+       arg2 = value_sub (arg1, arg2);
+      else
+       arg2 = value_binop (arg1, arg2, op);
+      return value_assign (arg1, arg2);
+
+    case BINOP_ADD:
+      arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+      arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      return value_add (arg1, arg2);
+
+    case BINOP_SUB:
+      arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+      arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      return value_sub (arg1, arg2);
+
+    case BINOP_MUL:
+    case BINOP_DIV:
+    case BINOP_REM:
+    case BINOP_LSH:
+    case BINOP_RSH:
+    case BINOP_LOGAND:
+    case BINOP_LOGIOR:
+    case BINOP_LOGXOR:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      arg2 = evaluate_subexp (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      return value_binop (arg1, arg2, op);
+
+    case BINOP_SUBSCRIPT:
+      arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+      arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      return value_subscript (arg1, arg2, op);
+      
+    case BINOP_AND:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      tem = value_zerop (arg1);
+      arg2 = evaluate_subexp (exp, pos,
+                             (tem ? EVAL_SKIP : noside));
+      return value_from_long (builtin_type_int,
+                             !tem && !value_zerop (arg2));
+
+    case BINOP_OR:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      tem = value_zerop (arg1);
+      arg2 = evaluate_subexp (exp, pos,
+                             (!tem ? EVAL_SKIP : noside));
+      return value_from_long (builtin_type_int,
+                             !tem || !value_zerop (arg2));
+
+    case BINOP_EQUAL:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      arg2 = evaluate_subexp (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      tem = value_equal (arg1, arg2);
+      return value_from_long (builtin_type_int, tem);
+
+    case BINOP_NOTEQUAL:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      arg2 = evaluate_subexp (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      tem = value_equal (arg1, arg2);
+      return value_from_long (builtin_type_int, ! tem);
+
+    case BINOP_LESS:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      arg2 = evaluate_subexp (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      tem = value_less (arg1, arg2);
+      return value_from_long (builtin_type_int, tem);
+
+    case BINOP_GTR:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      arg2 = evaluate_subexp (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      tem = value_less (arg2, arg1);
+      return value_from_long (builtin_type_int, tem);
+
+    case BINOP_GEQ:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      arg2 = evaluate_subexp (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      tem = value_less (arg1, arg2);
+      return value_from_long (builtin_type_int, ! tem);
+
+    case BINOP_LEQ:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      arg2 = evaluate_subexp (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      tem = value_less (arg2, arg1);
+      return value_from_long (builtin_type_int, ! tem);
+
+    case BINOP_REPEAT:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      arg2 = evaluate_subexp (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      return value_repeat (arg1, value_as_long (arg2));
+
+    case BINOP_COMMA:
+      evaluate_subexp (exp, pos, noside);
+      return evaluate_subexp (exp, pos, noside);
+
+    case UNOP_NEG:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      return value_neg (arg1);
+
+    case UNOP_LOGNOT:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      return value_lognot (arg1);
+
+    case UNOP_ZEROP:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      return value_from_long (builtin_type_int, value_zerop (arg1));
+
+    case UNOP_IND:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      return value_ind (arg1);
+
+    case UNOP_ADDR:
+      if (noside == EVAL_SKIP)
+       {
+         evaluate_subexp (exp, pos, EVAL_SKIP);
+         goto nosideret;
+       }
+      return evaluate_subexp_for_address (exp, pos, noside);
+
+    case UNOP_SIZEOF:
+      if (noside == EVAL_SKIP)
+       {
+         evaluate_subexp (exp, pos, EVAL_SKIP);
+         goto nosideret;
+       }
+      return evaluate_subexp_for_sizeof (exp, pos);
+
+    case UNOP_CAST:
+      (*pos) += 2;
+      arg1 = evaluate_subexp (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      return value_cast (exp->elts[pc + 1].type, arg1);
+
+    case UNOP_MEMVAL:
+      (*pos) += 2;
+      arg1 = evaluate_subexp (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      return value_at (exp->elts[pc + 1].type, value_as_long (arg1));
+
+    case UNOP_PREINCREMENT:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      arg2 = value_add (arg1, value_from_long (builtin_type_char, 1));
+      if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+       return arg1;
+      return value_assign (arg1, arg2);
+
+    case UNOP_PREDECREMENT:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      arg2 = value_sub (arg1, value_from_long (builtin_type_char, 1));
+      if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+       return arg1;
+      return value_assign (arg1, arg2);
+
+    case UNOP_POSTINCREMENT:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      arg2 = value_add (arg1, value_from_long (builtin_type_char, 1));
+      if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+       return arg1;
+      value_assign (arg1, arg2);
+      return arg1;
+
+    case UNOP_POSTDECREMENT:
+      arg1 = evaluate_subexp (exp, pos, noside);
+      arg2 = value_sub (arg1, value_from_long (builtin_type_char, 1));
+      if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+       return arg1;
+      value_assign (arg1, arg2);
+      return arg1;
+    }
+
+ nosideret:
+  return value_from_long (builtin_type_long, 1);
+}
+\f
+/* Evaluate a subexpression of EXP, at index *POS,
+   and return the address of that subexpression.
+   Advance *POS over the subexpression.
+   If the subexpression isn't an lvalue, get an error.
+   NOSIDE may be EVAL_AVOID_SIDE_EFFECTS;
+   then only the type of the result need be correct.  */
+
+static value
+evaluate_subexp_for_address (exp, pos, noside)
+     register struct expression *exp;
+     register int *pos;
+     enum noside noside;
+{
+  enum exp_opcode op;
+  register int pc;
+
+  pc = (*pos);
+  op = exp->elts[pc].opcode;
+
+  switch (op)
+    {
+    case UNOP_IND:
+      (*pos)++;
+      return evaluate_subexp (exp, pos, noside);
+
+    case UNOP_MEMVAL:
+      (*pos) += 3;
+      return value_cast (lookup_pointer_type (exp->elts[pc + 1].type),
+                        evaluate_subexp (exp, pos, noside));
+
+    case OP_VAR_VALUE:
+      (*pos) += 3;
+      return locate_var_value (exp->elts[pc + 1].symbol, (CORE_ADDR) 0);
+
+    default:
+      return value_addr (evaluate_subexp (exp, pos, noside));
+    }
+}
+
+/* Evaluate like `evaluate_subexp' except coercing arrays to pointers.
+   When used in contexts where arrays will be coerced anyway,
+   this is equivalent to `evaluate_subexp'
+   but much faster because it avoids actually fetching array contents.  */
+
+static value
+evaluate_subexp_with_coercion (exp, pos, noside)
+     register struct expression *exp;
+     register int *pos;
+     enum noside noside;
+{
+  register enum exp_opcode op;
+  register int pc;
+  register value val;
+
+  pc = (*pos);
+  op = exp->elts[pc].opcode;
+
+  switch (op)
+    {
+    case OP_VAR_VALUE:
+      if (TYPE_CODE (SYMBOL_TYPE (exp->elts[pc + 1].symbol)) == TYPE_CODE_ARRAY)
+       {
+         (*pos) += 3;
+         val = locate_var_value (exp->elts[pc + 1].symbol, (CORE_ADDR) 0);
+         return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (SYMBOL_TYPE (exp->elts[pc + 1].symbol))),
+                            val);
+       }
+    }
+
+  return evaluate_subexp (exp, pos, noside);
+}
+
+/* Evaluate a subexpression of EXP, at index *POS,
+   and return a value for the size of that subexpression.
+   Advance *POS over the subexpression.  */
+
+static value
+evaluate_subexp_for_sizeof (exp, pos)
+     register struct expression *exp;
+     register int *pos;
+{
+  enum exp_opcode op;
+  register int pc;
+  value val;
+
+  pc = (*pos);
+  op = exp->elts[pc].opcode;
+
+  switch (op)
+    {
+      /* This case is handled specially
+        so that we avoid creating a value for the result type.
+        If the result type is very big, it's desirable not to
+        create a value unnecessarily.  */
+    case UNOP_IND:
+      (*pos)++;
+      val = evaluate_subexp (exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+      return value_from_long (builtin_type_int,
+                             TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (val))));
+
+    case UNOP_MEMVAL:
+      (*pos) += 3;
+      return value_from_long (builtin_type_int,
+                             TYPE_LENGTH (exp->elts[pc + 1].type));
+
+    case OP_VAR_VALUE:
+      (*pos) += 3;
+      return value_from_long (builtin_type_int,
+                             TYPE_LENGTH (SYMBOL_TYPE (exp->elts[pc + 1].symbol)));
+
+    default:
+      val = evaluate_subexp (exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+      return value_from_long (builtin_type_int,
+                             TYPE_LENGTH (VALUE_TYPE (val)));
+    }
+}
+\f
+static
+initialize ()
+{ }
+
+END_FILE
diff --git a/gdb/expprint.c b/gdb/expprint.c
new file mode 100644 (file)
index 0000000..36b31c6
--- /dev/null
@@ -0,0 +1,304 @@
+/* Print in infix form a struct expression.
+   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 "defs.h"
+#include "symtab.h"
+#include "expression.h"
+
+#include <stdio.h>
+\f
+/* These codes indicate operator precedences, least tightly binding first.  */
+/* Adding 1 to a precedence value is done for binary operators,
+   on the operand which is more tightly bound, so that operators
+   of equal precedence within that operand will get parentheses.  */
+/* PREC_HYPER and PREC_ABOVE_COMMA are not the precedence of any operator;
+   they are used as the "surrounding precedence" to force
+   various kinds of things to be parenthesized.  */
+enum precedence
+{ PREC_NULL, PREC_COMMA, PREC_ABOVE_COMMA, PREC_ASSIGN, PREC_OR, PREC_AND,
+  PREC_LOGIOR, PREC_LOGAND, PREC_LOGXOR, PREC_EQUAL, PREC_ORDER,
+  PREC_SHIFT, PREC_ADD, PREC_MUL, PREC_REPEAT,
+  PREC_HYPER, PREC_PREFIX, PREC_SUFFIX };
+
+/* Table mapping opcodes into strings for printing operators
+   and precedences of the operators.  */
+
+struct op_print
+{
+  char *string;
+  enum exp_opcode opcode;
+  /* Precedence of operator.  These values are used only by comparisons.  */
+  enum precedence precedence;
+  int right_assoc;
+};
+
+static struct op_print op_print_tab[] =
+  {
+    {",", BINOP_COMMA, PREC_COMMA, 0},
+    {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+    {"||", BINOP_OR, PREC_OR, 0},
+    {"&&", BINOP_AND, PREC_AND, 0},
+    {"|", BINOP_LOGIOR, PREC_LOGIOR, 0},
+    {"&", BINOP_LOGAND, PREC_LOGAND, 0},
+    {"^", BINOP_LOGXOR, PREC_LOGXOR, 0},
+    {"==", BINOP_EQUAL, PREC_EQUAL, 0},
+    {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
+    {"<=", BINOP_LEQ, PREC_ORDER, 0},
+    {">=", BINOP_GEQ, PREC_ORDER, 0},
+    {">", BINOP_GTR, PREC_ORDER, 0},
+    {"<", BINOP_LESS, PREC_ORDER, 0},
+    {">>", BINOP_RSH, PREC_SHIFT, 0},
+    {"<<", BINOP_LSH, PREC_SHIFT, 0},
+    {"+", BINOP_ADD, PREC_ADD, 0},
+    {"-", BINOP_SUB, PREC_ADD, 0},
+    {"*", BINOP_MUL, PREC_MUL, 0},
+    {"/", BINOP_DIV, PREC_MUL, 0},
+    {"%", BINOP_REM, PREC_MUL, 0},
+    {"@", BINOP_REPEAT, PREC_REPEAT, 0},
+    {"-", UNOP_NEG, PREC_PREFIX, 0},
+    {"!", UNOP_ZEROP, PREC_PREFIX, 0},
+    {"~", UNOP_LOGNOT, PREC_PREFIX, 0},
+    {"*", UNOP_IND, PREC_PREFIX, 0},
+    {"&", UNOP_ADDR, PREC_PREFIX, 0},
+    {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
+    {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
+    {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0}
+  };
+\f
+static void print_subexp ();
+
+void
+print_expression (exp, stream)
+     struct expression *exp;
+     FILE *stream;
+{
+  int pc = 0;
+  print_subexp (exp, &pc, stream, PREC_NULL);
+}
+
+/* Print the subexpression of EXP that starts in position POS, on STREAM.
+   PREC is the precedence of the surrounding operator;
+   if the precedence of the main operator of this subexpression is less,
+   parentheses are needed here.  */
+
+static void
+print_subexp (exp, pos, stream, prec)
+     register struct expression *exp;
+     register int *pos;
+     FILE *stream;
+     enum precedence prec;
+{
+  register int tem;
+  register int pc;
+  int nargs;
+  register char *op_str;
+  int assign_modify = 0;
+  enum exp_opcode opcode;
+  enum precedence myprec;
+  /* Set to 1 for a right-associative operator.  */
+  int assoc;
+
+  pc = (*pos)++;
+  opcode = exp->elts[pc].opcode;
+  switch (opcode)
+    {
+    case OP_LONG:
+      (*pos) += 3;
+      value_print (value_from_long (exp->elts[pc + 1].type,
+                                   exp->elts[pc + 2].longconst),
+                  stream);
+      return;
+
+    case OP_DOUBLE:
+      (*pos) += 3;
+      value_print (value_from_double (exp->elts[pc + 1].type,
+                                     exp->elts[pc + 2].doubleconst),
+                  stream);
+      return;
+
+    case OP_VAR_VALUE:
+      (*pos) += 2;
+      fprintf (stream, "%s", SYMBOL_NAME (exp->elts[pc + 1].symbol));
+      return;
+
+    case OP_LAST:
+      (*pos) += 2;
+      fprintf (stream, "$%d", exp->elts[pc + 1].longconst);
+      return;
+
+    case OP_REGISTER:
+      (*pos) += 2;
+      fprintf (stream, "$%s", reg_names[exp->elts[pc + 1].longconst]);
+      return;
+
+    case OP_INTERNALVAR:
+      (*pos) += 2;
+      fprintf (stream, "$%s",
+              internalvar_name (exp->elts[pc + 1].internalvar));
+      return;
+
+    case OP_FUNCALL:
+      (*pos) += 2;
+      nargs = exp->elts[pc + 1].longconst;
+      print_subexp (exp, pos, stream, PREC_SUFFIX);
+      fprintf (stream, " (");
+      for (tem = 0; tem < nargs; tem++)
+       {
+         if (tem > 0)
+           fprintf (stream, ", ");
+         print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+       }
+      fprintf (stream, ")");
+      return;
+
+    case OP_STRING:
+      nargs = strlen (&exp->elts[pc + 1].string);
+      (*pos) += 2 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
+      fprintf (stream, "\"");
+      for (tem = 0; tem < nargs; tem++)
+       printchar ((&exp->elts[pc + 1].string)[tem], stream);
+      fprintf (stream, "\"");
+      return;
+
+    case TERNOP_COND:
+      if ((int) prec > (int) PREC_COMMA)
+       fprintf (stream, "(");
+      /* Print the subexpressions, forcing parentheses
+        around any binary operations within them.
+        This is more parentheses than are strictly necessary,
+        but it looks clearer.  */
+      print_subexp (exp, pos, stream, PREC_HYPER);
+      fprintf (stream, " ? ");
+      print_subexp (exp, pos, stream, PREC_HYPER);
+      fprintf (stream, " : ");
+      print_subexp (exp, pos, stream, PREC_HYPER);
+      if ((int) prec > (int) PREC_COMMA)
+       fprintf (stream, ")");
+      return;
+
+    case STRUCTOP_STRUCT:
+      tem = strlen (&exp->elts[pc + 1].string);
+      (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
+      print_subexp (exp, pos, stream, PREC_SUFFIX);
+      fprintf (stream, ".%s", &exp->elts[pc + 1].string);
+      return;
+
+    case STRUCTOP_PTR:
+      tem = strlen (&exp->elts[pc + 1].string);
+      (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
+      print_subexp (exp, pos, stream, PREC_SUFFIX);
+      fprintf (stream, "->%s", &exp->elts[pc + 1].string);
+      return;
+
+    case BINOP_SUBSCRIPT:
+      print_subexp (exp, pos, stream, PREC_SUFFIX);
+      fprintf (stream, "[");
+      print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+      fprintf (stream, "]");
+      return;
+
+    case UNOP_POSTINCREMENT:
+      print_subexp (exp, pos, stream, PREC_SUFFIX);
+      fprintf (stream, "++");
+      return;
+
+    case UNOP_POSTDECREMENT:
+      print_subexp (exp, pos, stream, PREC_SUFFIX);
+      fprintf (stream, "--");
+      return;
+
+    case UNOP_CAST:
+      (*pos) += 2;
+      if ((int) prec > (int) PREC_PREFIX)
+       fprintf (stream, "(");
+      fprintf (stream, "(");
+      type_print (exp->elts[pc + 1].type, "", stream, 0);
+      fprintf (stream, ") ");
+      print_subexp (exp, pos, stream, PREC_PREFIX);
+      if ((int) prec > (int) PREC_PREFIX)
+       fprintf (stream, ")");
+      return;
+
+    case UNOP_MEMVAL:
+      (*pos) += 2;
+      if ((int) prec > (int) PREC_PREFIX)
+       fprintf (stream, "(");
+      fprintf (stream, "{");
+      type_print (exp->elts[pc + 1].type, "", stream, 0);
+      fprintf (stream, "} ");
+      print_subexp (exp, pos, stream, PREC_PREFIX);
+      if ((int) prec > (int) PREC_PREFIX)
+       fprintf (stream, ")");
+      return;
+
+    case BINOP_ASSIGN_MODIFY:
+      opcode = exp->elts[pc + 1].opcode;
+      (*pos) += 2;
+      myprec = PREC_ASSIGN;
+      assoc = 1;
+      assign_modify = 1;
+      for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
+       if (op_print_tab[tem].opcode == opcode)
+         {
+           op_str = op_print_tab[tem].string;
+           break;
+         }
+
+    default:
+      for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
+       if (op_print_tab[tem].opcode == opcode)
+         {
+           op_str = op_print_tab[tem].string;
+           myprec = op_print_tab[tem].precedence;
+           assoc = op_print_tab[tem].right_assoc;
+           break;
+         }
+    }
+
+  if ((int) myprec < (int) prec)
+    fprintf (stream, "(");
+  if ((int) opcode > (int) BINOP_END)
+    {
+      /* Unary prefix operator.  */
+      fprintf (stream, "%s", op_str);
+      print_subexp (exp, pos, stream, PREC_PREFIX);
+    }
+  else
+    {
+      /* Binary operator.  */
+      /* Print left operand.
+        If operator is right-associative,
+        increment precedence for this operand.  */
+      print_subexp (exp, pos, stream, (int) myprec + assoc);
+      /* Print the operator itself.  */
+      if (assign_modify)
+       fprintf (stream, " %s= ", op_str);
+      else if (op_str[0] == ',')
+       fprintf (stream, "%s ", op_str);
+      else
+       fprintf (stream, " %s ", op_str);
+      /* Print right operand.
+        If operator is left-associative,
+        increment precedence for this operand.  */
+      print_subexp (exp, pos, stream, (int) myprec + !assoc);
+    }
+  if ((int) myprec < (int) prec)
+    fprintf (stream, ")");
+}
diff --git a/gdb/expread.y b/gdb/expread.y
new file mode 100644 (file)
index 0000000..468d409
--- /dev/null
@@ -0,0 +1,1189 @@
+/* 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!
+*/
+\f
+/* Parse a C expression from text in a string,
+   and return the result as a  struct expression  pointer.
+   That structure contains arithmetic operations in reverse polish,
+   with constants represented by operations that are followed by special data.
+   See expression.h for the details of the format.
+   What is important here is that it can be built up sequentially
+   during the process of parsing; the lower levels of the tree always
+   come first in the result.  */
+   
+%{
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "expression.h"
+
+#include <stdio.h>
+
+static struct expression *expout;
+static int expout_size;
+static int expout_ptr;
+
+static int yylex ();
+static yyerror ();
+static void write_exp_elt ();
+static void write_exp_string ();
+static void start_arglist ();
+static int end_arglist ();
+static void free_funcalls ();
+static char *copy_name ();
+
+/* If this is nonzero, this block is used as the lexical context
+   for symbol names.  */
+
+static struct block *expression_context_block;
+
+/* Number of arguments seen so far in innermost function call.  */
+static int arglist_len;
+
+/* Data structure for saving values of arglist_len
+   for function calls whose arguments contain other function calls.  */
+
+struct funcall
+  {
+    struct funcall *next;
+    int arglist_len;
+  };
+
+struct funcall *funcall_chain;
+
+/* This kind of datum is used to represent the name
+   of a symbol token.  */
+
+struct stoken
+  {
+    char *ptr;
+    int length;
+  };
+%}
+
+/* Although the yacc "value" of an expression is not used,
+   since the result is stored in the structure being created,
+   other node types do have values.  */
+
+%union
+  {
+    long lval;
+    double dval;
+    struct symbol *sym;
+    struct type *tval;
+    struct stoken sval;
+    int voidval;
+    struct block *bval;
+    enum exp_opcode opcode;
+    struct internalvar *ivar;
+  }
+
+%type <voidval> exp exp1 start variable
+%type <tval> type typebase
+%type <bval> block
+
+%token <lval> INT CHAR
+%token <dval> FLOAT
+
+/* Both NAME and TYPENAME tokens represent symbols in the input,
+   and both convey their data as strings.
+   But a TYPENAME is a string that happens to be defined as a typedef
+   or builtin type name (such as int or char)
+   and a NAME is any other symbol.
+
+   Contexts where this distinction is not important can use the
+   nonterminal "name", which matches either NAME or TYPENAME.  */
+
+%token <sval> NAME TYPENAME STRING
+%type <sval> name
+
+%token STRUCT UNION ENUM SIZEOF UNSIGNED COLONCOLON
+
+%token <lval> LAST REGNAME
+
+%token <ivar> VARIABLE
+
+%token <opcode> ASSIGN_MODIFY
+
+%left ','
+%left ABOVE_COMMA
+%right '=' ASSIGN_MODIFY
+%left OR
+%left AND
+%left '|'
+%left '^'
+%left '&'
+%left EQUAL NOTEQUAL
+%left '<' '>' LEQ GEQ
+%left LSH RSH
+%left '+' '-'
+%left '*' '/' '%'
+%left '@'
+%right UNARY INCREMENT DECREMENT
+%right ARROW '.' '['
+%left COLONCOLON
+\f
+%%
+
+start   :      exp1
+       ;
+
+/* Expressions, including the comma operator.  */
+exp1   :       exp
+       |       exp1 ',' exp
+                       { write_exp_elt (BINOP_COMMA); }
+       ;
+
+/* Expressions, not including the comma operator.  */
+exp    :       '*' exp    %prec UNARY
+                       { write_exp_elt (UNOP_IND); }
+
+exp    :       '&' exp    %prec UNARY
+                       { write_exp_elt (UNOP_ADDR); }
+
+exp    :       '-' exp    %prec UNARY
+                       { write_exp_elt (UNOP_NEG); }
+       ;
+
+exp    :       '!' exp    %prec UNARY
+                       { write_exp_elt (UNOP_ZEROP); }
+       ;
+
+exp    :       '~' exp    %prec UNARY
+                       { write_exp_elt (UNOP_LOGNOT); }
+       ;
+
+exp    :       INCREMENT exp    %prec UNARY
+                       { write_exp_elt (UNOP_PREINCREMENT); }
+       ;
+
+exp    :       DECREMENT exp    %prec UNARY
+                       { write_exp_elt (UNOP_PREDECREMENT); }
+       ;
+
+exp    :       exp INCREMENT    %prec UNARY
+                       { write_exp_elt (UNOP_POSTINCREMENT); }
+       ;
+
+exp    :       exp DECREMENT    %prec UNARY
+                       { write_exp_elt (UNOP_POSTDECREMENT); }
+       ;
+
+exp    :       SIZEOF exp       %prec UNARY
+                       { write_exp_elt (UNOP_SIZEOF); }
+       ;
+
+exp    :       exp ARROW name
+                       { write_exp_elt (STRUCTOP_PTR);
+                         write_exp_string ($3);
+                         write_exp_elt (STRUCTOP_PTR); }
+       ;
+
+exp    :       exp '.' name
+                       { write_exp_elt (STRUCTOP_STRUCT);
+                         write_exp_string ($3);
+                         write_exp_elt (STRUCTOP_STRUCT); }
+       ;
+
+exp    :       exp '[' exp1 ']'
+                       { write_exp_elt (BINOP_SUBSCRIPT); }
+       ;
+
+exp    :       exp '(' 
+                       /* This is to save the value of arglist_len
+                          being accumulated by an outer function call.  */
+                       { start_arglist (); }
+               arglist ')'
+                       { write_exp_elt (OP_FUNCALL);
+                         write_exp_elt (end_arglist ());
+                         write_exp_elt (OP_FUNCALL); }
+       ;
+
+arglist        :
+       ;
+
+arglist        :       exp
+                       { arglist_len = 1; }
+       ;
+
+arglist        :       arglist ',' exp   %prec ABOVE_COMMA
+                       { arglist_len++; }
+       ;
+
+exp    :       '{' type '}' exp  %prec UNARY
+                       { write_exp_elt (UNOP_MEMVAL);
+                         write_exp_elt ($2);
+                         write_exp_elt (UNOP_MEMVAL); }
+       ;
+
+exp    :       '(' type ')' exp  %prec UNARY
+                       { write_exp_elt (UNOP_CAST);
+                         write_exp_elt ($2);
+                         write_exp_elt (UNOP_CAST); }
+       ;
+
+exp    :       '(' exp1 ')'
+                       { }
+       ;
+
+/* Binary operators in order of decreasing precedence.  */
+
+exp    :       exp '@' exp
+                       { write_exp_elt (BINOP_REPEAT); }
+       ;
+
+exp    :       exp '*' exp
+                       { write_exp_elt (BINOP_MUL); }
+       ;
+
+exp    :       exp '/' exp
+                       { write_exp_elt (BINOP_DIV); }
+       ;
+
+exp    :       exp '%' exp
+                       { write_exp_elt (BINOP_REM); }
+       ;
+
+exp    :       exp '+' exp
+                       { write_exp_elt (BINOP_ADD); }
+       ;
+
+exp    :       exp '-' exp
+                       { write_exp_elt (BINOP_SUB); }
+       ;
+
+exp    :       exp LSH exp
+                       { write_exp_elt (BINOP_LSH); }
+       ;
+
+exp    :       exp RSH exp
+                       { write_exp_elt (BINOP_RSH); }
+       ;
+
+exp    :       exp EQUAL exp
+                       { write_exp_elt (BINOP_EQUAL); }
+       ;
+
+exp    :       exp NOTEQUAL exp
+                       { write_exp_elt (BINOP_NOTEQUAL); }
+       ;
+
+exp    :       exp LEQ exp
+                       { write_exp_elt (BINOP_LEQ); }
+       ;
+
+exp    :       exp GEQ exp
+                       { write_exp_elt (BINOP_GEQ); }
+       ;
+
+exp    :       exp '<' exp
+                       { write_exp_elt (BINOP_LESS); }
+       ;
+
+exp    :       exp '>' exp
+                       { write_exp_elt (BINOP_GTR); }
+       ;
+
+exp    :       exp '&' exp
+                       { write_exp_elt (BINOP_LOGAND); }
+       ;
+
+exp    :       exp '^' exp
+                       { write_exp_elt (BINOP_LOGXOR); }
+       ;
+
+exp    :       exp '|' exp
+                       { write_exp_elt (BINOP_LOGIOR); }
+       ;
+
+exp    :       exp AND exp
+                       { write_exp_elt (BINOP_AND); }
+       ;
+
+exp    :       exp OR exp
+                       { write_exp_elt (BINOP_OR); }
+       ;
+
+exp    :       exp '?' exp ':' exp
+                       { write_exp_elt (TERNOP_COND); }
+       ;
+                         
+exp    :       exp '=' exp
+                       { write_exp_elt (BINOP_ASSIGN); }
+       ;
+
+exp    :       exp ASSIGN_MODIFY exp
+                       { write_exp_elt (BINOP_ASSIGN_MODIFY);
+                         write_exp_elt ($2);
+                         write_exp_elt (BINOP_ASSIGN_MODIFY); }
+       ;
+
+exp    :       INT
+                       { write_exp_elt (OP_LONG);
+                         write_exp_elt (builtin_type_long);
+                         write_exp_elt ($1);
+                         write_exp_elt (OP_LONG); }
+       ;
+
+exp    :       CHAR
+                       { write_exp_elt (OP_LONG);
+                         write_exp_elt (builtin_type_char);
+                         write_exp_elt ($1);
+                         write_exp_elt (OP_LONG); }
+       ;
+
+exp    :       FLOAT
+                       { write_exp_elt (OP_DOUBLE);
+                         write_exp_elt (builtin_type_double);
+                         write_exp_elt ($1);
+                         write_exp_elt (OP_DOUBLE); }
+       ;
+
+exp    :       variable
+       ;
+
+exp    :       LAST
+                       { write_exp_elt (OP_LAST);
+                         write_exp_elt ($1);
+                         write_exp_elt (OP_LAST); }
+       ;
+
+exp    :       REGNAME
+                       { write_exp_elt (OP_REGISTER);
+                         write_exp_elt ($1);
+                         write_exp_elt (OP_REGISTER); }
+       ;
+
+exp    :       VARIABLE
+                       { write_exp_elt (OP_INTERNALVAR);
+                         write_exp_elt ($1);
+                         write_exp_elt (OP_INTERNALVAR); }
+       ;
+
+exp    :       SIZEOF '(' type ')'
+                       { write_exp_elt (OP_LONG);
+                         write_exp_elt (builtin_type_int);
+                         write_exp_elt ((long) TYPE_LENGTH ($3));
+                         write_exp_elt (OP_LONG); }
+       ;
+
+exp    :       STRING
+                       { write_exp_elt (OP_STRING);
+                         write_exp_string ($1);
+                         write_exp_elt (OP_STRING); }
+       ;
+
+block  :       name
+                       { struct symtab *tem = lookup_symtab (copy_name ($1));
+                         struct symbol *sym;
+                         
+                         if (tem)
+                           $$ = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), 1);
+                         else
+                           {
+                             sym = lookup_symbol (copy_name ($1),
+                                                  expression_context_block,
+                                                  VAR_NAMESPACE);
+                             if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+                               $$ = SYMBOL_BLOCK_VALUE (sym);
+                             else
+                               error ("No file or function \"%s\".",
+                                      copy_name ($1));
+                           }}
+       ;
+
+block  :       block COLONCOLON name
+                       { struct symbol *tem
+                           = lookup_symbol (copy_name ($3), $1, VAR_NAMESPACE);
+                         if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
+                           error ("No function \"%s\" in specified context.",
+                                  copy_name ($3));
+                         $$ = SYMBOL_BLOCK_VALUE (tem); }
+       ;
+
+variable:      block COLONCOLON name
+                       { struct symbol *sym;
+                         sym = lookup_symbol ($3, copy_name ($1), VAR_NAMESPACE);
+                         if (sym == 0)
+                           error ("No symbol \"%s\" in specified context.",
+                                  copy_name ($3));
+                         write_exp_elt (OP_VAR_VALUE);
+                         write_exp_elt (sym);
+                         write_exp_elt (OP_VAR_VALUE); }
+       ;
+
+variable:      NAME
+                       { struct symbol *sym;
+                         sym = lookup_symbol (copy_name ($1),
+                                             expression_context_block,
+                                             VAR_NAMESPACE);
+                         if (sym)
+                           {
+                             write_exp_elt (OP_VAR_VALUE);
+                             write_exp_elt (sym);
+                             write_exp_elt (OP_VAR_VALUE);
+                           }
+                         else
+                           {
+                             register char *arg = copy_name ($1);
+                             register int i;
+                             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 (OP_LONG);
+                                 write_exp_elt (builtin_type_int);
+                                 write_exp_elt (misc_function_vector[i].address);
+                                 write_exp_elt (OP_LONG);
+                                 write_exp_elt (UNOP_MEMVAL);
+                                 write_exp_elt (builtin_type_char);
+                                 write_exp_elt (UNOP_MEMVAL);
+                               }
+                             else
+                               if (symtab_list == 0)
+                                 error ("No symbol table is loaded.  Use the \"symbol-file\" command.");
+                               else
+                                 error ("No symbol \"%s\" in current context.",
+                                        copy_name ($1));
+                           }
+                       }
+       ;
+
+type   :       typebase
+       |       type '*'
+                       { $$ = lookup_pointer_type ($1); }
+       ;
+
+typebase
+       :       TYPENAME
+                       { $$ = lookup_typename (copy_name ($1),
+                                               expression_context_block, 0); }
+       |       STRUCT name
+                       { $$ = lookup_struct (copy_name ($2),
+                                             expression_context_block); }
+       |       UNION name
+                       { $$ = lookup_union (copy_name ($2),
+                                            expression_context_block); }
+       |       ENUM name
+                       { $$ = lookup_enum (copy_name ($2),
+                                           expression_context_block); }
+       |       UNSIGNED name
+                       { $$ = lookup_unsigned_typename (copy_name ($2)); }
+       ;
+
+name   :       NAME
+       |       TYPENAME
+       ;
+%%
+\f
+/* Begin counting arguments for a function call,
+   saving the data about any containing call.  */
+
+static void
+start_arglist ()
+{
+  register struct funcall *new = (struct funcall *) xmalloc (sizeof (struct funcall));
+
+  new->next = funcall_chain;
+  new->arglist_len = arglist_len;
+  arglist_len = 0;
+  funcall_chain = new;
+}
+
+/* Return the number of arguments in a function call just terminated,
+   and restore the data for the containing function call.  */
+
+static int
+end_arglist ()
+{
+  register int val = arglist_len;
+  register struct funcall *call = funcall_chain;
+  funcall_chain = call->next;
+  arglist_len = call->arglist_len;
+  free (call);
+  return val;
+}
+
+/* Free everything in the funcall chain.
+   Used when there is an error inside parsing.  */
+
+static void
+free_funcalls ()
+{
+  register struct funcall *call, *next;
+
+  for (call = funcall_chain; call; call = next)
+    {
+      next = call->next;
+      free (call);
+    }
+}
+\f
+/* This page contains the functions for adding data to the  struct expression
+   being constructed.  */
+
+/* Add one element to the end of the expression.  */
+
+static void
+write_exp_elt (expelt)
+     union exp_element expelt;
+{
+  if (expout_ptr >= expout_size)
+    {
+      expout_size *= 2;
+      expout = (struct expression *) xrealloc (expout,
+                                              sizeof (struct expression)
+                                              + expout_size * sizeof (union exp_element));
+    }
+  expout->elts[expout_ptr++] = expelt;
+}
+
+/* Add a string constant to the end of the expression.
+   Follow it by its length in bytes, as a separate exp_element.  */
+
+static void
+write_exp_string (str)
+     struct stoken str;
+{
+  register int len = str.length;
+  register int lenelt
+    = (len + sizeof (union exp_element)) / sizeof (union exp_element);
+
+  expout_ptr += lenelt;
+
+  if (expout_ptr >= expout_size)
+    {
+      expout_size = max (expout_size * 2, expout_ptr + 10);
+      expout = (struct expression *) xrealloc (expout,
+                                              sizeof (struct expression)
+                                              + expout_size * sizeof (union exp_element));
+    }
+  bcopy (str.ptr, (char *) &expout->elts[expout_ptr - lenelt], len);
+  ((char *) &expout->elts[expout_ptr - lenelt])[len] = 0;
+  write_exp_elt (len);
+}
+\f
+/* During parsing of a C expression, the pointer to the next character
+   is in this variable.  */
+
+static char *lexptr;
+
+/* Tokens that refer to names do so with explicit pointer and length,
+   so they can share the storage that lexptr is parsing.
+
+   When it is necessary to pass a name to a function that expects
+   a null-terminated string, the substring is copied out
+   into a block of storage that namecopy points to.
+
+   namecopy is allocated once, guaranteed big enough, for each parsing.  */
+
+static char *namecopy;
+
+/* Take care of parsing a number (anything that starts with a digit).
+   Set yylval and return the token type; update lexptr.
+   LEN is the number of characters in it.  */
+
+/*** Needs some error checking for the float case ***/
+
+static int
+parse_number (olen)
+     int olen;
+{
+  register char *p = lexptr;
+  register long n = 0;
+  register int c;
+  register int base = 10;
+  register int len = olen;
+  char *err_copy;
+
+  extern double atof ();
+
+  for (c = 0; c < len; c++)
+    if (p[c] == '.')
+      {
+       /* It's a float since it contains a point.  */
+       yylval.dval = atof (p);
+       lexptr += len;
+       return FLOAT;
+      }
+
+  if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2)))
+    {
+      p += 2;
+      base = 16;
+      len -= 2;
+    }
+  else if (*p == '0')
+    base = 8;
+
+  while (len-- > 0)
+    {
+      c = *p++;
+      n *= base;
+      if (c >= '0' && c <= '9')
+       n += c - '0';
+      else
+       {
+         if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
+         if (base == 16 && c >= 'a' && c <= 'f')
+           n += c - 'a' + 10;
+         else if (len == 0 && c == 'l')
+           ;
+         else
+           {
+             err_copy = (char *) alloca (olen + 1);
+             bcopy (lexptr, err_copy, olen);
+             err_copy[olen] = 0;
+             error ("Invalid number \"%s\".", err_copy);
+           }
+       }
+    }
+
+  lexptr = p;
+  yylval.lval = n;
+  return INT;
+}
+
+struct token
+{
+  char *operator;
+  int token;
+  enum exp_opcode opcode;
+};
+
+static struct token tokentab3[] =
+  {
+    {">>=", ASSIGN_MODIFY, BINOP_RSH},
+    {"<<=", ASSIGN_MODIFY, BINOP_LSH}
+  };
+
+static struct token tokentab2[] =
+  {
+    {"+=", ASSIGN_MODIFY, BINOP_ADD},
+    {"-=", ASSIGN_MODIFY, BINOP_SUB},
+    {"*=", ASSIGN_MODIFY, BINOP_MUL},
+    {"/=", ASSIGN_MODIFY, BINOP_DIV},
+    {"%=", ASSIGN_MODIFY, BINOP_REM},
+    {"|=", ASSIGN_MODIFY, BINOP_LOGIOR},
+    {"&=", ASSIGN_MODIFY, BINOP_LOGAND},
+    {"^=", ASSIGN_MODIFY, BINOP_LOGXOR},
+    {"++", INCREMENT, BINOP_END},
+    {"--", DECREMENT, BINOP_END},
+    {"->", ARROW, BINOP_END},
+    {"&&", AND, BINOP_END},
+    {"||", OR, BINOP_END},
+    {"::", COLONCOLON, BINOP_END},
+    {"<<", LSH, BINOP_END},
+    {">>", RSH, BINOP_END},
+    {"==", EQUAL, BINOP_END},
+    {"!=", NOTEQUAL, BINOP_END},
+    {"<=", LEQ, BINOP_END},
+    {">=", GEQ, BINOP_END}
+  };
+
+/* Read one token, getting characters through lexptr.  */
+
+static int
+yylex ()
+{
+  register int c;
+  register int namelen;
+  register int i;
+  register char *tokstart;
+
+ retry:
+
+  tokstart = lexptr;
+  /* See if it is a special token of length 3.  */
+  for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
+    if (!strncmp (tokstart, tokentab3[i].operator, 3))
+      {
+       lexptr += 3;
+       yylval.opcode = tokentab3[i].opcode;
+       return tokentab3[i].token;
+      }
+
+  /* See if it is a special token of length 2.  */
+  for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++)
+    if (!strncmp (tokstart, tokentab2[i].operator, 2))
+      {
+       lexptr += 2;
+       yylval.opcode = tokentab2[i].opcode;
+       return tokentab2[i].token;
+      }
+
+  switch (c = *tokstart)
+    {
+    case 0:
+      return 0;
+
+    case ' ':
+    case '\t':
+    case '\n':
+      lexptr++;
+      goto retry;
+
+    case '\'':
+      lexptr++;
+      c = *lexptr++;
+      if (c == '\\')
+       c = parse_escape (&lexptr);
+      yylval.lval = c;
+      c = *lexptr++;
+      if (c != '\'')
+       error ("Invalid character constant.");
+      return CHAR;
+
+    case '+':
+    case '-':
+    case '*':
+    case '/':
+    case '%':
+    case '|':
+    case '&':
+    case '^':
+    case '~':
+    case '!':
+    case '@':
+    case '<':
+    case '>':
+    case '(':
+    case ')':
+    case '[':
+    case ']':
+    case '.':
+    case '?':
+    case ':':
+    case '=':
+    case '{':
+    case '}':
+    case ',':
+      lexptr++;
+      return c;
+
+    case '"':
+      for (namelen = 1; (c = tokstart[namelen]) != '"'; namelen++)
+       if (c == '\\')
+         {
+           c = tokstart[++namelen];
+           if (c >= '0' && c <= '9')
+             {
+               c = tokstart[++namelen];
+               if (c >= '0' && c <= '9')
+                 c = tokstart[++namelen];
+             }
+         }
+      yylval.sval.ptr = tokstart + 1;
+      yylval.sval.length = namelen - 1;
+      lexptr += namelen + 1;
+      return STRING;
+    }
+  if (c >= '0' && c <= '9')
+    {
+      /* 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);
+    }
+
+  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],
+       (c == '_' || c == '$' || (c >= '0' && c <= '9')
+       || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
+       namelen++)
+    ;
+
+  /* The token "if" terminates the expression and is NOT 
+     removed from the input stream.  */
+  if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
+    {
+      return 0;
+    }
+
+  lexptr += namelen;
+
+  /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1)
+     and $$digits (equivalent to $<-digits> if you could type that).
+     Make token type LAST, and put the number (the digits) in yylval.  */
+
+  if (*tokstart == '$')
+    {
+      register int negate = 0;
+      c = 1;
+      /* Double dollar means negate the number and add -1 as well.
+        Thus $$ alone means -1.  */
+      if (namelen >= 2 && tokstart[1] == '$')
+       {
+         negate = 1;
+         c = 2;
+       }
+      if (c == namelen)
+       {
+         /* Just dollars (one or two) */
+         yylval.lval = - negate;
+         return LAST;
+       }
+      /* Is the rest of the token digits?  */
+      for (; c < namelen; c++)
+       if (!(tokstart[c] >= '0' && tokstart[c] <= '9'))
+         break;
+      if (c == namelen)
+       {
+         yylval.lval = atoi (tokstart + 1 + negate);
+         if (negate)
+           yylval.lval = - yylval.lval;
+         return LAST;
+       }
+    }
+
+  /* Handle tokens that refer to machine registers:
+     $ followed by a register name.  */
+
+  if (*tokstart == '$')
+    for (c = 0; c < NUM_REGS; c++)
+      if (namelen - 1 == strlen (reg_names[c])
+         && !strncmp (tokstart + 1, reg_names[c], namelen - 1))
+       {
+         yylval.lval = c;
+         return REGNAME;
+       }
+
+  if (namelen == 6 && !strncmp (tokstart, "struct", 6))
+    {
+      return STRUCT;
+    }
+  if (namelen == 5 && !strncmp (tokstart, "union", 5))
+    {
+      return UNION;
+    }
+  if (namelen == 4 && !strncmp (tokstart, "enum", 4))
+    {
+      return ENUM;
+    }
+  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;
+
+  /* Any other names starting in $ are debugger internal variables.  */
+
+  if (*tokstart == '$')
+    {
+      yylval.ivar = (struct internalvar *) lookup_internalvar (copy_name (yylval.sval) + 1);
+      return VARIABLE;
+    }
+
+  /* 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;
+}
+
+static
+yyerror ()
+{
+  error ("Invalid syntax in expression.");
+}
+
+/* Return a null-terminated temporary copy of the name
+   of a string token.  */
+
+static char *
+copy_name (token)
+     struct stoken token;
+{
+  bcopy (token.ptr, namecopy, token.length);
+  namecopy[token.length] = 0;
+  return namecopy;
+}
+\f
+/* Reverse an expression from suffix form (in which it is constructed)
+   to prefix form (in which we can conveniently print or execute it).  */
+
+static void prefixify_subexp ();
+
+static void
+prefixify_expression (expr)
+     register struct expression *expr;
+{
+  register int len = sizeof (struct expression) +
+                                   expr->nelts * sizeof (union exp_element);
+  register struct expression *temp;
+  register int inpos = expr->nelts, outpos = 0;
+
+  temp = (struct expression *) alloca (len);
+
+  /* Copy the original expression into temp.  */
+  bcopy (expr, temp, len);
+
+  prefixify_subexp (temp, expr, inpos, outpos);
+}
+
+/* Return the number of exp_elements in the subexpression of EXPR
+   whose last exp_element is at index ENDPOS - 1 in EXPR.  */
+
+static int
+length_of_subexp (expr, endpos)
+     register struct expression *expr;
+     register int endpos;
+{
+  register int oplen = 1;
+  register int args = 0;
+  register int i;
+
+  i = (int) expr->elts[endpos - 1].opcode;
+
+  switch (i)
+    {
+    case OP_LONG:
+    case OP_DOUBLE:
+      oplen = 4;
+      break;
+
+    case OP_VAR_VALUE:
+    case OP_LAST:
+    case OP_REGISTER:
+    case OP_INTERNALVAR:
+      oplen = 3;
+      break;
+
+    case OP_FUNCALL:
+      oplen = 3;
+      args = 1 + expr->elts[endpos - 2].longconst;
+      break;
+
+    case UNOP_CAST:
+    case UNOP_MEMVAL:
+      oplen = 3;
+      args = 1;
+      break;
+
+    case STRUCTOP_STRUCT:
+    case STRUCTOP_PTR:
+      args = 1;
+    case OP_STRING:
+      oplen = 3 + ((expr->elts[endpos - 2].longconst
+                   + sizeof (union exp_element))
+                  / sizeof (union exp_element));
+                  
+      break;
+
+    case TERNOP_COND:
+      args = 3;
+      break;
+
+    case BINOP_ASSIGN_MODIFY:
+      oplen = 3;
+      args = 2;
+      break;
+
+    default:
+      args = 1 + (i < (int) BINOP_END);
+    }
+
+  while (args > 0)
+    {
+      oplen += length_of_subexp (expr, endpos - oplen);
+      args--;
+    }
+
+  return oplen;
+}
+
+/* Copy the subexpression ending just before index INEND in INEXPR
+   into OUTEXPR, starting at index OUTBEG.
+   In the process, convert it from suffix to prefix form.  */
+
+static void
+prefixify_subexp (inexpr, outexpr, inend, outbeg)
+     register struct expression *inexpr;
+     struct expression *outexpr;
+     register int inend;
+     int outbeg;
+{
+  register int oplen = 1;
+  register int args = 0;
+  register int i;
+  int *arglens;
+  enum exp_opcode opcode;
+
+  /* Compute how long the last operation is (in OPLEN),
+     and also how many preceding subexpressions serve as
+     arguments for it (in ARGS).  */
+
+  opcode = inexpr->elts[inend - 1].opcode;
+  switch (opcode)
+    {
+    case OP_LONG:
+    case OP_DOUBLE:
+      oplen = 4;
+      break;
+
+    case OP_VAR_VALUE:
+    case OP_LAST:
+    case OP_REGISTER:
+    case OP_INTERNALVAR:
+      oplen = 3;
+      break;
+
+    case OP_FUNCALL:
+      oplen = 3;
+      args = 1 + inexpr->elts[inend - 2].longconst;
+      break;
+
+    case UNOP_CAST:
+    case UNOP_MEMVAL:
+      oplen = 3;
+      args = 1;
+      break;
+
+    case STRUCTOP_STRUCT:
+    case STRUCTOP_PTR:
+      args = 1;
+    case OP_STRING:
+      oplen = 3 + ((inexpr->elts[inend - 2].longconst
+                   + sizeof (union exp_element))
+                  / sizeof (union exp_element));
+                  
+      break;
+
+    case TERNOP_COND:
+      args = 3;
+      break;
+
+    case BINOP_ASSIGN_MODIFY:
+      oplen = 3;
+      args = 2;
+      break;
+
+    default:
+      args = 1 + ((int) opcode < (int) BINOP_END);
+    }
+
+  /* Copy the final operator itself, from the end of the input
+     to the beginning of the output.  */
+  inend -= oplen;
+  bcopy (&inexpr->elts[inend], &outexpr->elts[outbeg],
+        oplen * sizeof (union exp_element));
+  outbeg += oplen;
+
+  /* Find the lengths of the arg subexpressions.  */
+  arglens = (int *) alloca (args * sizeof (int));
+  for (i = args - 1; i >= 0; i--)
+    {
+      oplen = length_of_subexp (inexpr, inend);
+      arglens[i] = oplen;
+      inend -= oplen;
+    }
+
+  /* Now copy each subexpression, preserving the order of
+     the subexpressions, but prefixifying each one.
+     In this loop, inend starts at the beginning of
+     the expression this level is working on
+     and marches forward over the arguments.
+     outbeg does similarly in the output.  */
+  for (i = 0; i < args; i++)
+    {
+      oplen = arglens[i];
+      inend += oplen;
+      prefixify_subexp (inexpr, outexpr, inend, outbeg);
+      outbeg += oplen;
+    }
+}
+\f
+/* This page contains the two entry points to this file.  */
+
+/* Read a C expression from the string *STRINGPTR points to,
+   parse it, and return a pointer to a  struct expression  that we malloc.
+   Use block BLOCK as the lexical context for variable names;
+   if BLOCK is zero, use the block of the selected stack frame.
+   Meanwhile, advance *STRINGPTR to point after the expression,
+   at the first nonwhite character that is not part of the expression
+   (possibly a null character).  */
+
+struct expression *
+parse_c_1 (stringptr, block)
+     char **stringptr;
+     struct block *block;
+{
+  struct cleanup *old_chain;
+
+  lexptr = *stringptr;
+
+  if (lexptr == 0 || *lexptr == 0)
+    error_no_arg ("expression to compute");
+
+  old_chain = make_cleanup (free_funcalls, 0);
+  funcall_chain = 0;
+
+  expression_context_block = block ? block : get_selected_block ();
+
+  namecopy = (char *) alloca (strlen (lexptr) + 1);
+  expout_size = 10;
+  expout_ptr = 0;
+  expout = (struct expression *) xmalloc (sizeof (struct expression)
+                                         + expout_size * sizeof (union exp_element));
+  make_cleanup (free_current_contents, &expout);
+  if (yyparse ())
+    yyerror ();
+  discard_cleanups (old_chain);
+  expout->nelts = expout_ptr;
+  expout = (struct expression *)
+    xrealloc (expout,
+             sizeof (struct expression)
+             + expout_ptr * sizeof (union exp_element));
+  prefixify_expression (expout);
+  *stringptr = lexptr;
+  return expout;
+}
+
+/* Parse STRING as an expression, and complain if this fails
+   to use up all of the contents of STRING.  */
+
+struct expression *
+parse_c_expression (string)
+     char *string;
+{
+  register struct expression *exp;
+  exp = parse_c_1 (&string, 0);
+  if (*string)
+    error ("Junk after end of expression.");
+  return exp;
+}
diff --git a/gdb/expression.h b/gdb/expression.h
new file mode 100644 (file)
index 0000000..7a7bd83
--- /dev/null
@@ -0,0 +1,167 @@
+/* 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!
+*/
+
+/* Definitions for saved C expressions.  */
+
+/* An expression is represented as a vector of union exp_element's.
+   Each exp_element is an opcode, except that some opcodes cause
+   the following exp_element to be treated as a long or double constant
+   or as a variable.  The opcodes are obeyed, using a stack for temporaries.
+   The value is left on the temporary stack at the end.  */
+
+/* When it is necessary to include a string,
+   it can occupy as many exp_elements as it needs.
+   We find the length of the string using strlen,
+   divide to find out how many exp_elements are used up,
+   and skip that many.  Strings, like numbers, are indicated
+   by the preceding opcode.  */
+
+enum exp_opcode
+{
+/* BINOP_... operate on two values computed by following subexpressions,
+   replacing them by one result value.  They take no immediate arguments.  */
+  BINOP_ADD,           /* + */
+  BINOP_SUB,           /* - */
+  BINOP_MUL,           /* * */
+  BINOP_DIV,           /* / */
+  BINOP_REM,           /* % */
+  BINOP_LSH,           /* << */
+  BINOP_RSH,           /* >> */
+  BINOP_AND,           /* && */
+  BINOP_OR,            /* || */
+  BINOP_LOGAND,                /* & */
+  BINOP_LOGIOR,                /* | */
+  BINOP_LOGXOR,                /* ^ */
+  BINOP_EQUAL,         /* == */
+  BINOP_NOTEQUAL,      /* != */
+  BINOP_LESS,          /* < */
+  BINOP_GTR,           /* > */
+  BINOP_LEQ,           /* <= */
+  BINOP_GEQ,           /* >= */
+  BINOP_REPEAT,                /* @ */
+  BINOP_ASSIGN,                /* = */
+  BINOP_COMMA,         /* , */
+  BINOP_SUBSCRIPT,     /* x[y] */
+  BINOP_EXP,           /* Exponentiation */
+  BINOP_END,
+
+  BINOP_ASSIGN_MODIFY, /* +=, -=, *=, and so on.
+                          The following exp_element is another opcode,
+                          a BINOP_, saying how to modify.
+                          Then comes another BINOP_ASSIGN_MODIFY,
+                          making three exp_elements in total.  */
+
+/* Operates on three values computed by following subexpressions.  */
+  TERNOP_COND,         /* ?: */
+
+/* The OP_... series take immediate following arguments.
+   After the arguments come another OP_... (the same one)
+   so that the grouping can be recognized from the end.  */
+
+/* OP_LONG is followed by a type pointer in the next exp_element
+   and the long constant value in the following exp_element.
+   Then comes another OP_LONG.
+   Thus, the operation occupies four exp_elements.  */
+
+  OP_LONG,
+/* OP_DOUBLE is similar but takes a double constant instead of a long one.  */
+  OP_DOUBLE,
+/* OP_VAR_VALUE takes one struct symbol * in the following exp_element,
+   followed by another OP_VAR_VALUE, making three exp_elements.  */
+  OP_VAR_VALUE,
+/* OP_LAST is followed by an integer in the next exp_element.
+   The integer is zero for the last value printed,
+   or it is the absolute number of a history element.
+   With another OP_LAST at the end, this makes three exp_elements.  */
+  OP_LAST,
+/* OP_REGISTER is followed by an integer in the next exp_element.
+   This is the number of a register to fetch (as an int).
+   With another OP_REGISTER at the end, this makes three exp_elements.  */
+  OP_REGISTER,
+/* OP_INTERNALVAR is followed by an internalvar ptr in the next exp_element.
+   With another OP_INTERNALVAR at the end, this makes three exp_elements.  */
+  OP_INTERNALVAR,
+/* OP_FUNCALL is followed by an integer in the next exp_element.
+   The integer is the number of args to the function call.
+   That many plus one values from following subexpressions
+   are used, the first one being the function.
+   The integer is followed by a repeat of OP_FUNCALL,
+   making three exp_elements.  */
+  OP_FUNCALL,
+/* OP_STRING represents a string constant.
+   Its format is the same as that of a STRUCTOP, but the string
+   data is just made into a string constant when the operation
+   is executed.  */
+  OP_STRING,
+
+/* UNOP_CAST is followed by a type pointer in the next exp_element.
+   With another UNOP_CAST at the end, this makes three exp_elements.
+   It casts the value of the following subexpression.  */
+  UNOP_CAST,
+/* UNOP_MEMVAL is followed by a type pointer in the next exp_element
+   With another UNOP_MEMVAL at the end, this makes three exp_elements.
+   It casts the contents of the word addressed by the value of the
+   following subexpression.  */
+  UNOP_MEMVAL,
+/* UNOP_... operate on one value from a following subexpression
+   and replace it with a result.  They take no immediate arguments.  */
+  UNOP_NEG,            /* Unary - */
+  UNOP_ZEROP,          /* Unary ! */
+  UNOP_LOGNOT,         /* Unary ~ */
+  UNOP_IND,            /* Unary * */
+  UNOP_ADDR,           /* Unary & */
+  UNOP_PREINCREMENT,   /* ++ before an expression */
+  UNOP_POSTINCREMENT,  /* ++ after an expression */
+  UNOP_PREDECREMENT,   /* -- before an expression */
+  UNOP_POSTDECREMENT,  /* -- after an expression */
+  UNOP_SIZEOF,         /* Unary sizeof (followed by expression) */
+
+/* STRUCTOP_... operate on a value from a following subexpression
+   by extracting a structure component specified by a string
+   that appears in the following exp_elements (as many as needed).
+   STRUCTOP_STRUCT is used for "." and STRUCTOP_PTR for "->".
+   They differ only in the error message given in case the value is
+   not suitable or the structure component specified is not found.
+
+   The length of the string follows in the next exp_element,
+   (after the string), followed by another STRUCTOP_... code.  */
+  STRUCTOP_STRUCT,
+  STRUCTOP_PTR,
+};
+
+union exp_element
+{
+  enum exp_opcode opcode;
+  struct symbol *symbol;
+  long longconst;
+  double doubleconst;
+  char string;
+  struct type *type;
+  struct internalvar *internalvar;
+};
+
+struct expression
+{
+  int nelts;
+  union exp_element elts[1];
+};
+
+struct expression *parse_c_expression ();
+struct expression *parse_c_1 ();
diff --git a/gdb/findvar.c b/gdb/findvar.c
new file mode 100644 (file)
index 0000000..1f92b16
--- /dev/null
@@ -0,0 +1,409 @@
+/* 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 "initialize.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "value.h"
+
+CORE_ADDR read_register ();
+
+START_FILE
+\f
+/* 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.  */
+
+static 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;
+
+  while (1)
+    {
+      QUIT;
+      fi = get_prev_frame_info (frame1);
+      if (fi.frame == 0 || fi.frame == frame)
+       break;
+      get_frame_saved_regs (&fi, &saved_regs);
+      if (saved_regs.regs[regnum])
+       addr = saved_regs.regs[regnum];
+      frame1 = fi.frame;
+    }
+
+  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 (&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 = find_saved_register (selected_frame, regnum);
+  register value val;
+  char raw_buffer[MAX_REGISTER_RAW_SIZE];
+  char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+
+  if (addr)
+    {
+      if (regnum == SP_REGNUM)
+       return value_from_long (builtin_type_int, 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;
+}
+\f
+/* 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.  */
+
+read_register_bytes (regbyte, myaddr, len)
+     int regbyte;
+     char *myaddr;
+     int len;
+{
+  bcopy (&registers[regbyte], myaddr, len);
+}
+
+/* Copy LEN bytes of consecutive data from memory at MYADDR
+   into registers starting with the REGBYTE'th byte of register data.  */
+
+write_register_bytes (regbyte, myaddr, len)
+     int regbyte;
+     char *myaddr;
+     int len;
+{
+  bcopy (myaddr, &registers[regbyte], len);
+  if (have_inferior_p ())
+    store_inferior_registers (-1);
+}
+
+/* Return the contents of register REGNO,
+   regarding it as an integer.  */
+
+CORE_ADDR
+read_register (regno)
+     int regno;
+{
+  /* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
+  return *(int *) &registers[REGISTER_BYTE (regno)];
+}
+
+/* Store VALUE in the register number REGNO, regarded as an integer.  */
+
+void
+write_register (regno, val)
+     int regno, val;
+{
+  /* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
+  *(int *) &registers[REGISTER_BYTE (regno)] = val;
+
+  if (have_inferior_p ())
+    store_inferior_registers (regno);
+}
+
+/* Record that register REGNO contains VAL.
+   This is used when the value is obtained from the inferior or core dump,
+   so there is no need to store the value there.  */
+
+void
+supply_register (regno, val)
+     int regno;
+     char *val;
+{
+  bcopy (val, &registers[REGISTER_BYTE (regno)], REGISTER_RAW_SIZE (regno));
+}
+\f
+/* 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;
+
+  if (SYMBOL_CLASS (var) == LOC_BLOCK)
+    type = lookup_function_type (type);
+
+  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:
+      {
+       char raw_buffer[MAX_REGISTER_RAW_SIZE];
+       char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+
+       VALUE_REGNO (v) = val;
+
+       /* Locate the register's contents in a real register or in core;
+          read the data in raw format.  */
+
+       addr = find_saved_register (frame, val);
+       if (addr == 0)
+         {
+           /* Value is really in a register.  */
+
+           VALUE_LVAL (v) = lval_register;
+           VALUE_ADDRESS (v) = REGISTER_BYTE (val);
+
+           read_register_bytes (REGISTER_BYTE (val),
+                                raw_buffer, REGISTER_RAW_SIZE (val));
+         }
+       else
+         {
+           /* Value was in a register that has been saved in memory.  */
+
+           read_memory (addr, raw_buffer, REGISTER_RAW_SIZE (val));
+           VALUE_ADDRESS (v) = addr;
+         }
+
+       /* Convert the raw contents to virtual contents.
+          (Just copy them if the formats are the same.)  */
+
+       REGISTER_CONVERT_TO_VIRTUAL (val, raw_buffer, virtual_buffer);
+
+       if (REGISTER_CONVERTIBLE (val))
+         {
+           /* 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 (val))
+             {
+               /* 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 (val));
+               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.  */
+
+           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 (val))
+             {
+               /* Big-endian, and we want less than full size.  */
+               VALUE_OFFSET (v) = REGISTER_RAW_SIZE (val) - len;
+             }
+
+           bcopy (virtual_buffer + VALUE_OFFSET (v),
+                  VALUE_CONTENTS (v), len);
+         }
+
+       return v;
+      }
+    }
+
+  read_memory (addr, VALUE_CONTENTS (v), len);
+  VALUE_ADDRESS (v) = addr;
+  return v;
+}
+\f
+/* 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;
+
+  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:
+      addr = find_saved_register (frame, val);
+      if (addr != 0)
+       {
+         union { int i; char c; } test;
+         int len = TYPE_LENGTH (SYMBOL_TYPE (var));
+         /* 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))
+           /* Big-endian, and we want less than full size.  */
+           addr+ = REGISTER_RAW_SIZE (val) - len;
+         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 (SYMBOL_TYPE (var)),
+                    value_from_long (builtin_type_long, addr));
+}
+
+static
+initialize ()
+{}
+
+END_FILE
diff --git a/gdb/firstfile.c b/gdb/firstfile.c
new file mode 100644 (file)
index 0000000..60d6bf8
--- /dev/null
@@ -0,0 +1,154 @@
+/* Find the initialization functions of following files.
+   This goes with initialize.h and lastfile.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 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.
+
+  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) cause each such copy to be accompanied by the
+    corresponding machine-readable source code, which must
+    be distributed under the terms of Paragraphs 1 and 2 above; or,
+
+    b) cause each such copy to be accompanied by a
+    written offer, with no time limit, to give any third party
+    free (except for a nominal shipping charge) a machine readable
+    copy of the corresponding source code, to be distributed
+    under the terms of Paragraphs 1 and 2 above; or,
+
+    c) in the case of a recipient of this program in compiled, executable
+    or object code form (without the corresponding source code) you
+    shall cause copies you distribute to be accompanied by a copy
+    of the written offer of source code which you received along
+    with the copy you received.
+
+  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!  */
+
+
+
+/* This is a magical hack for finding, automatically,
+   all the files that are linked together
+   and calling an initialization function in each one
+   without requiring the main file to know which other
+   files there are.
+
+   Call initialize_all_files to run the initialization functions
+   of all the files.  Each initialization function can enter
+   the commands of its file into a global data base so that the
+   contents of the file can be used.
+
+   The files to be found must follow this file.  Each of them
+   must start START_FILE, before any other functions,
+   and end with END_FILE, after any other functions.
+   These macros are defined in initialize.h.
+   In addition, each file must contain a function named
+   `initialize', which will be called with no arguments.
+
+   After the files to be found must come the file `lastfile'
+   which ends the chain of calls.  */
+
+#include "initialize.h"
+
+static initialize_next_file ();
+static initialize_dummy_1 ();
+static initialize_dummy_2 ();
+
+initialize_all_files ()
+{
+  initialize_next_file ((char *) initialize_dummy_2
+                       - (char *) initialize_dummy_1);
+}
+
+/* The next two functions exist just so we can find
+   out how long the first of them is.
+   That tells us how long initialize_next_file is,
+   since that function has the same definition as this one.  */
+
+static
+initialize_dummy_1 (offset)
+     int offset;
+{
+  long addr = FILEADDR_ROUND ((int) initialize_next_file + offset);
+  (*(void (*) ()) addr) (offset);
+}
+
+static
+initialize_dummy_2 ()
+{
+}
+
+/* This makes the function initialize_next_file.  */
+
+END_FILE
diff --git a/gdb/foo.c b/gdb/foo.c
new file mode 100644 (file)
index 0000000..59e559f
--- /dev/null
+++ b/gdb/foo.c
@@ -0,0 +1,13 @@
+main() {
+       int i;
+
+       for (i = 0; i >= 0; i++)
+               bar();
+}
+
+bar()
+{
+       int i;
+
+       i = 10;
+}
diff --git a/gdb/foo.nm b/gdb/foo.nm
new file mode 100644 (file)
index 0000000..7a14364
--- /dev/null
@@ -0,0 +1,39 @@
+
+
+Symbols from foo:
+
+Name                  Value   Class        Type         Size   Line  Section
+
+crt0.s              |        | file |                  |      |     |
+foo.c               |        | file |                  |      |     |
+main                |     228|extern|            int( )|    66|     |.text
+.bf                 |     228|fcn   |                  |      |    1|.text
+i                   |      -4|auto  |               int|      |     |
+.ef                 |     274|fcn   |                  |      |    6|.text
+bar                 |     294|extern|            int( )|    50|     |.text
+.bf                 |     294|fcn   |                  |      |    9|.text
+i                   |      -4|auto  |               int|      |     |
+.ef                 |     324|fcn   |                  |      |    5|.text
+dbxxx.s             |        | file |                  |      |     |
+initfpu.s           |        | file |                  |      |     |
+cuexit.s            |        | file |                  |      |     |
+fakcu.c             |        | file |                  |      |     |
+_cleanup            |     404|extern|               ( )|    42|     |.text
+.bf                 |     404|fcn   |                  |      |   23|.text
+.ef                 |     426|fcn   |                  |      |    2|.text
+_ac_r               | 4194760|static|             *char|      |     |.data
+copyright.c         |        | file |                  |      |     |
+_ac_r               | 4194764|static|             *char|      |     |.data
+_start              |     168|extern|                  |      |     |.text
+_dbargs             | 4195016|extern|                  |      |     |.bss
+exit                |     388|extern|                  |      |     |.text
+initfpu             |     380|extern|                  |      |     |.text
+environ             | 4194756|extern|                  |      |     |.data
+splimit%            | 4194752|extern|                  |      |     |.data
+_dbsubc             |     344|extern|                  |      |     |.text
+_dbsubn             |     376|extern|                  |      |     |.text
+_ac_s               | 4194768|extern|           char[0]|      |     |.data
+etext               |     448|extern|                  |      |     |
+edata               | 4195016|extern|                  |      |     |
+end                 | 4195528|extern|                  |      |     |
+_sorigin            | 4195528|extern|                  |      |     |
diff --git a/gdb/foo.od b/gdb/foo.od
new file mode 100644 (file)
index 0000000..ce2a186
--- /dev/null
@@ -0,0 +1,213 @@
+0000000    0150    0003    21fc    7629    0000    0310    0000    0032
+       001   P  \0 003   ! 374   v   )  \0  \0 003 020  \0  \0  \0   2
+0000020    001c    0103    010b    0000    0000    0118    0000    0108
+        \0 034 001 003 001 013  \0  \0  \0  \0 001 030  \0  \0 001  \b
+0000040    0000    0200    0000    00a8    0000    00a8    0040    01c0
+        \0  \0 002  \0  \0  \0  \0 250  \0  \0  \0 250  \0   @ 001 300
+0000060    2e74    6578    7400    0000    0000    00a8    0000    00a8
+         .   t   e   x   t  \0  \0  \0  \0  \0  \0 250  \0  \0  \0 250
+0000100    0000    0118    0000    00a8    0000    0000    0000    02c8
+        \0  \0 001 030  \0  \0  \0 250  \0  \0  \0  \0  \0  \0 002 310
+0000120    0000    000c    0000    0020    2e64    6174    6100    0000
+        \0  \0  \0  \f  \0  \0  \0       .   d   a   t   a  \0  \0  \0
+0000140    0040    01c0    0040    01c0    0000    0108    0000    01c0
+        \0   @ 001 300  \0   @ 001 300  \0  \0 001  \b  \0  \0 001 300
+0000160    0000    0000    0000    0000    0000    0000    0000    0040
+        \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0   @
+0000200    2e62    7373    0000    0000    0040    02c8    0040    02c8
+         .   b   s   s  \0  \0  \0  \0  \0   @ 002 310  \0   @ 002 310
+0000220    0000    0200    0000    0000    0000    0000    0000    0000
+        \0  \0 002  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
+0000240    0000    0000    0000    0080    23c0    0040    01c0    518f
+        \0  \0  \0  \0  \0  \0  \0 200   # 300  \0   @ 001 300   Q 217
+0000260    2eaf    0008    41ef    000c    2f48    0004    2248    4a98
+         . 257  \0  \b   A 357  \0  \f   /   H  \0 004   "   H   J 230
+0000300    66fc    2f48    0008    23c8    0040    01c4    4eb9    0000
+         f 374   /   H  \0  \b   # 310  \0   @ 001 304   N 271  \0  \0
+0000320    017c    4eb9    0000    00e4    2e80    4eb9    0000    0184
+       001   |   N 271  \0  \0  \0 344   . 200   N 271  \0  \0 001 204
+0000340    7001    4e40    480e    ffff    fff8    48ef    0000    0004
+         p 001   N   @   H 016 377 377 377 370   H 357  \0  \0  \0 004
+0000360    f237    f000    0170    0000    0004    42ae    fffc    4aae
+       362   7 360  \0 001   p  \0  \0  \0 004   B 256 377 374   J 256
+0000400    fffc    6d00    000e    4eba    001e    52ae    fffc    6000
+       377 374   m  \0  \0 016   N 272  \0 036   R 256 377 374   `  \0
+0000420    ffee    4cef    0000    0004    f237    d000    0170    0000
+       377 356   L 357  \0  \0  \0 004 362   7 320  \0 001   p  \0  \0
+0000440    0004    4e5e    4e75    480e    ffff    fff8    48ef    0000
+        \0 004   N   ^   N   u   H 016 377 377 377 370   H 357  \0  \0
+0000460    0004    f237    f000    0170    0000    0004    2d7c    0000
+        \0 004 362   7 360  \0 001   p  \0  \0  \0 004   -   |  \0  \0
+0000500    000a    fffc    4cef    0000    0004    f237    d000    0170
+        \0  \n 377 374   L 357  \0  \0  \0 004 362   7 320  \0 001   p
+0000520    0000    0004    4e5e    4e75    4e56    0000    207c    0040
+        \0  \0  \0 004   N   ^   N   u   N   V  \0  \0       |  \0   @
+0000540    02c8    2258    2018    2200    e581    d1c1    6002    2f20
+       002 310   "   X     030   "  \0 345 201 321 301   ` 002   /    
+0000560    51c8    fffc    4e91    4e5e    4e41    4e71    4e56    fffc
+         Q 310 377 374   N 221   N   ^   N   A   N   q   N   V 377 374
+0000600    4e5e    4e75    4eb9    0000    0194    7001    4e40    4e72
+         N   ^   N   u   N 271  \0  \0 001 224   p 001   N   @   N   r
+0000620    0000    4e71    480e    ffff    fffc    48ef    0000    0004
+        \0  \0   N   q   H 016 377 377 377 374   H 357  \0  \0  \0 004
+0000640    f237    f000    0170    0000    0004    4cef    0000    0004
+       362   7 360  \0 001   p  \0  \0  \0 004   L 357  \0  \0  \0 004
+0000660    f237    d000    0170    0000    0004    4e5e    4e75    4e71
+       362   7 320  \0 001   p  \0  \0  \0 004   N   ^   N   u   N   q
+0000700    0000    0000    0000    0000    0040    01d0    0040    01d0
+        \0  \0  \0  \0  \0  \0  \0  \0  \0   @ 001 320  \0   @ 001 320
+0000720    436f    7079    7269    6768    7420    2863    2920    3139
+         C   o   p   y   r   i   g   h   t       (   c   )       1   9
+0000740    3837    2041    7070    6c65    2043    6f6d    7075    7465
+         8   7       A   p   p   l   e       C   o   m   p   u   t   e
+0000760    722c    2049    6e63    2e2c    2031    3938    3520    4164
+         r   ,       I   n   c   .   ,       1   9   8   5       A   d
+0001000    6f62    6520    5379    7374    656d    7320    496e    636f
+         o   b   e       S   y   s   t   e   m   s       I   n   c   o
+0001020    7270    6f72    6174    6564    2c20    3139    3833    2d38
+         r   p   o   r   a   t   e   d   ,       1   9   8   3   -   8
+0001040    3720    4154    2654    2d49    532c    2031    3938    352d
+         7       A   T   &   T   -   I   S   ,       1   9   8   5   -
+0001060    3837    204d    6f74    6f72    6f6c    6120    496e    632e
+         8   7       M   o   t   o   r   o   l   a       I   n   c   .
+0001100    2c20    3139    3830    2d38    3720    5375    6e20    4d69
+         ,       1   9   8   0   -   8   7       S   u   n       M   i
+0001120    6372    6f73    7973    7465    6d73    2049    6e63    2e2c
+         c   r   o   s   y   s   t   e   m   s       I   n   c   .   ,
+0001140    2031    3938    302d    3837    2054    6865    2052    6567
+             1   9   8   0   -   8   7       T   h   e       R   e   g
+0001160    656e    7473    206f    6620    7468    6520    556e    6976
+         e   n   t   s       o   f       t   h   e       U   n   i   v
+0001200    6572    7369    7479    206f    6620    4361    6c69    666f
+         e   r   s   i   t   y       o   f       C   a   l   i   f   o
+0001220    726e    6961    2c20    3139    3835    2d38    3720    556e
+         r   n   i   a   ,       1   9   8   5   -   8   7       U   n
+0001240    6973    6f66    7420    436f    7270    6f72    6174    696f
+         i   s   o   f   t       C   o   r   p   o   r   a   t   i   o
+0001260    6e2c    2041    6c6c    2052    6967    6874    7320    5265
+         n   ,       A   l   l       R   i   g   h   t   s       R   e
+0001300    7365    7276    6564    2e00    0000    0004    0000    0000
+         s   e   r   v   e   d   .  \0  \0  \0  \0 004  \0  \0  \0  \0
+0001320    00e4    0001    0000    00fa    0004    0000    0106    0005
+        \0 344  \0 001  \0  \0  \0 372  \0 004  \0  \0 001 006  \0 005
+0001340    0000    0112    0006    0000    000b    0000    0000    0126
+        \0  \0 001 022  \0 006  \0  \0  \0 013  \0  \0  \0  \0 001   &
+0001360    0001    0000    013c    0004    0000    0144    0005    0000
+        \0 001  \0  \0 001   <  \0 004  \0  \0 001   D  \0 005  \0  \0
+0001400    001a    0000    0000    0194    0001    0000    01aa    0002
+        \0 032  \0  \0  \0  \0 001 224  \0 001  \0  \0 001 252  \0 002
+0001420    2e66    696c    6500    0000    0000    0002    fffe    0000
+         .   f   i   l   e  \0  \0  \0  \0  \0  \0 002 377 376  \0  \0
+0001440    6701    6372    7430    2e73    0000    0000    0000    0000
+         g 001   c   r   t   0   .   s  \0  \0  \0  \0  \0  \0  \0  \0
+0001460    0000    0000    2e66    696c    6500    0000    0000    0012
+        \0  \0  \0  \0   .   f   i   l   e  \0  \0  \0  \0  \0  \0 022
+0001500    fffe    0000    6701    666f    6f2e    6300    0000    0000
+       377 376  \0  \0   g 001   f   o   o   .   c  \0  \0  \0  \0  \0
+0001520    0000    0000    0000    0000    6d61    696e    0000    0000
+        \0  \0  \0  \0  \0  \0  \0  \0   m   a   i   n  \0  \0  \0  \0
+0001540    0000    00e4    0001    0024    0201    0000    0000    0000
+        \0  \0  \0 344  \0 001  \0   $ 002 001  \0  \0  \0  \0  \0  \0
+0001560    0042    0000    02c8    0000    000b    0000    2e62    6600
+        \0   B  \0  \0 002 310  \0  \0  \0 013  \0  \0   .   b   f  \0
+0001600    0000    0000    0000    00e4    0001    0000    6501    0000
+        \0  \0  \0  \0  \0  \0  \0 344  \0 001  \0  \0   e 001  \0  \0
+0001620    0000    0001    0000    0000    0000    0000    0000    0000
+        \0  \0  \0 001  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
+0001640    6900    0000    0000    0000    ffff    fffc    ffff    0004
+         i  \0  \0  \0  \0  \0  \0  \0 377 377 377 374 377 377  \0 004
+0001660    0100    2e65    6600    0000    0000    0000    0112    0001
+       001  \0   .   e   f  \0  \0  \0  \0  \0  \0  \0 001 022  \0 001
+0001700    0000    6501    0000    0000    0006    0000    0000    0000
+        \0  \0   e 001  \0  \0  \0  \0  \0 006  \0  \0  \0  \0  \0  \0
+0001720    0000    0000    0000    6261    7200    0000    0000    0000
+        \0  \0  \0  \0  \0  \0   b   a   r  \0  \0  \0  \0  \0  \0  \0
+0001740    0126    0001    0024    0201    0000    0000    0000    0032
+       001   &  \0 001  \0   $ 002 001  \0  \0  \0  \0  \0  \0  \0   2
+0001760    0000    02e6    0000    0012    0000    2e62    6600    0000
+        \0  \0 002 346  \0  \0  \0 022  \0  \0   .   b   f  \0  \0  \0
+0002000    0000    0000    0126    0001    0000    6501    0000    0000
+        \0  \0  \0  \0 001   &  \0 001  \0  \0   e 001  \0  \0  \0  \0
+0002020    0009    0000    0000    0000    0000    0000    0000    6900
+        \0  \t  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0   i  \0
+0002040    0000    0000    0000    ffff    fffc    ffff    0004    0100
+        \0  \0  \0  \0  \0  \0 377 377 377 374 377 377  \0 004 001  \0
+0002060    2e65    6600    0000    0000    0000    0144    0001    0000
+         .   e   f  \0  \0  \0  \0  \0  \0  \0 001   D  \0 001  \0  \0
+0002100    6501    0000    0000    0005    0000    0000    0000    0000
+         e 001  \0  \0  \0  \0  \0 005  \0  \0  \0  \0  \0  \0  \0  \0
+0002120    0000    0000    2e66    696c    6500    0000    0000    0014
+        \0  \0  \0  \0   .   f   i   l   e  \0  \0  \0  \0  \0  \0 024
+0002140    fffe    0000    6701    6462    7878    782e    7300    0000
+       377 376  \0  \0   g 001   d   b   x   x   x   .   s  \0  \0  \0
+0002160    0000    0000    0000    0000    2e66    696c    6500    0000
+        \0  \0  \0  \0  \0  \0  \0  \0   .   f   i   l   e  \0  \0  \0
+0002200    0000    0016    fffe    0000    6701    696e    6974    6670
+        \0  \0  \0 026 377 376  \0  \0   g 001   i   n   i   t   f   p
+0002220    752e    7300    0000    0000    0000    0000    2e66    696c
+         u   .   s  \0  \0  \0  \0  \0  \0  \0  \0  \0   .   f   i   l
+0002240    6500    0000    0000    0018    fffe    0000    6701    6375
+         e  \0  \0  \0  \0  \0  \0 030 377 376  \0  \0   g 001   c   u
+0002260    6578    6974    2e73    0000    0000    0000    0000    0000
+         e   x   i   t   .   s  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
+0002300    2e66    696c    6500    0000    0000    0021    fffe    0000
+         .   f   i   l   e  \0  \0  \0  \0  \0  \0   ! 377 376  \0  \0
+0002320    6701    6661    6b63    752e    6300    0000    0000    0000
+         g 001   f   a   k   c   u   .   c  \0  \0  \0  \0  \0  \0  \0
+0002340    0000    0000    5f63    6c65    616e    7570    0000    0194
+        \0  \0  \0  \0   _   c   l   e   a   n   u   p  \0  \0 001 224
+0002360    0001    0020    0201    0000    0000    0000    002a    0000
+        \0 001  \0     002 001  \0  \0  \0  \0  \0  \0  \0   *  \0  \0
+0002400    02fe    0000    0020    0000    2e62    6600    0000    0000
+       002 376  \0  \0  \0      \0  \0   .   b   f  \0  \0  \0  \0  \0
+0002420    0000    0194    0001    0000    6501    0000    0000    0017
+        \0  \0 001 224  \0 001  \0  \0   e 001  \0  \0  \0  \0  \0 027
+0002440    0000    0000    0000    0000    0000    0000    2e65    6600
+        \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0   .   e   f  \0
+0002460    0000    0000    0000    01aa    0001    0000    6501    0000
+        \0  \0  \0  \0  \0  \0 001 252  \0 001  \0  \0   e 001  \0  \0
+0002500    0000    0002    0000    0000    0000    0000    0000    0000
+        \0  \0  \0 002  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
+0002520    5f61    635f    7200    0000    0040    01c8    0002    0012
+         _   a   c   _   r  \0  \0  \0  \0   @ 001 310  \0 002  \0 022
+0002540    0300    2e66    696c    6500    0000    0000    0024    fffe
+       003  \0   .   f   i   l   e  \0  \0  \0  \0  \0  \0   $ 377 376
+0002560    0000    6701    636f    7079    7269    6768    742e    6300
+        \0  \0   g 001   c   o   p   y   r   i   g   h   t   .   c  \0
+0002600    0000    0000    0000    5f61    635f    7200    0000    0040
+        \0  \0  \0  \0  \0  \0   _   a   c   _   r  \0  \0  \0  \0   @
+0002620    01cc    0002    0012    0300    5f73    7461    7274    0000
+       001 314  \0 002  \0 022 003  \0   _   s   t   a   r   t  \0  \0
+0002640    0000    00a8    0001    0000    0200    5f64    6261    7267
+        \0  \0  \0 250  \0 001  \0  \0 002  \0   _   d   b   a   r   g
+0002660    7300    0040    02c8    0003    0000    0200    6578    6974
+         s  \0  \0   @ 002 310  \0 003  \0  \0 002  \0   e   x   i   t
+0002700    0000    0000    0000    0184    0001    0000    0200    696e
+        \0  \0  \0  \0  \0  \0 001 204  \0 001  \0  \0 002  \0   i   n
+0002720    6974    6670    7500    0000    017c    0001    0000    0200
+         i   t   f   p   u  \0  \0  \0 001   |  \0 001  \0  \0 002  \0
+0002740    656e    7669    726f    6e00    0040    01c4    0002    0000
+         e   n   v   i   r   o   n  \0  \0   @ 001 304  \0 002  \0  \0
+0002760    0200    7370    6c69    6d69    7425    0040    01c0    0002
+       002  \0   s   p   l   i   m   i   t   %  \0   @ 001 300  \0 002
+0003000    0000    0200    5f64    6273    7562    6300    0000    0158
+        \0  \0 002  \0   _   d   b   s   u   b   c  \0  \0  \0 001   X
+0003020    0001    0000    0200    5f64    6273    7562    6e00    0000
+        \0 001  \0  \0 002  \0   _   d   b   s   u   b   n  \0  \0  \0
+0003040    0178    0001    0000    0200    5f61    635f    7300    0000
+       001   x  \0 001  \0  \0 002  \0   _   a   c   _   s  \0  \0  \0
+0003060    0040    01d0    0002    0032    0201    0000    0000    0000
+        \0   @ 001 320  \0 002  \0   2 002 001  \0  \0  \0  \0  \0  \0
+0003100    0000    0000    0000    0000    0000    0000    6574    6578
+        \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0   e   t   e   x
+0003120    7400    0000    0000    01c0    ffff    0000    0200    6564
+         t  \0  \0  \0  \0  \0 001 300 377 377  \0  \0 002  \0   e   d
+0003140    6174    6100    0000    0040    02c8    ffff    0000    0200
+         a   t   a  \0  \0  \0  \0   @ 002 310 377 377  \0  \0 002  \0
+0003160    656e    6400    0000    0000    0040    04c8    ffff    0000
+         e   n   d  \0  \0  \0  \0  \0  \0   @ 004 310 377 377  \0  \0
+0003200    0200    5f73    6f72    6967    696e    0040    04c8    ffff
+       002  \0   _   s   o   r   i   g   i   n  \0   @ 004 310 377 377
+0003220    0000    0200
+        \0  \0 002  \0
+0003224
diff --git a/gdb/foo.s b/gdb/foo.s
new file mode 100644 (file)
index 0000000..a7079d5
--- /dev/null
+++ b/gdb/foo.s
@@ -0,0 +1,65 @@
+       file    "foo.c"
+       data    1
+       text
+       def     main;   val     main;   scl     2;      type    044;    endef
+       global  main
+main:
+       ln      1
+       def     ~bf;    val     ~;      scl     101;    line    1;      endef
+       link.l  %fp,&F%1
+       movm.l  &M%1,(4,%sp)
+       fmovm   &FPM%1,(FPO%1,%sp)
+       def     i;      val     -4+S%1; scl     1;      type    04;     endef
+       ln      4
+       clr.l   ((S%1-4).w,%fp)
+L%15:
+       tst.l   ((S%1-4).w,%fp)
+       blt     L%14
+       ln      5
+       jsr     bar
+L%13:
+       add.l   &1,((S%1-4).w,%fp)
+       bra     L%15
+L%14:
+L%12:
+       def     ~ef;    val     ~;      scl     101;    line    6;      endef
+       ln      6
+       movm.l  (4,%sp),&M%1
+       fmovm   (FPO%1,%sp),&FPM%1
+       unlk    %fp
+       rts
+       def     main;   val     ~;      scl     -1;     endef
+       set     S%1,0
+       set     T%1,0
+       set     F%1,-8
+       set     FPO%1,4
+       set     FPM%1,0x0000
+       set     M%1,0x0000
+       data    1
+       text
+       def     bar;    val     bar;    scl     2;      type    044;    endef
+       global  bar
+bar:
+       ln      1
+       def     ~bf;    val     ~;      scl     101;    line    9;      endef
+       link.l  %fp,&F%2
+       movm.l  &M%2,(4,%sp)
+       fmovm   &FPM%2,(FPO%2,%sp)
+       def     i;      val     -4+S%2; scl     1;      type    04;     endef
+       ln      4
+       mov.l   &10,((S%2-4).w,%fp)
+L%17:
+       def     ~ef;    val     ~;      scl     101;    line    5;      endef
+       ln      5
+       movm.l  (4,%sp),&M%2
+       fmovm   (FPO%2,%sp),&FPM%2
+       unlk    %fp
+       rts
+       def     bar;    val     ~;      scl     -1;     endef
+       set     S%2,0
+       set     T%2,0
+       set     F%2,-8
+       set     FPO%2,4
+       set     FPM%2,0x0000
+       set     M%2,0x0000
+       data    1
diff --git a/gdb/foo.sym b/gdb/foo.sym
new file mode 100644 (file)
index 0000000..4b6595a
--- /dev/null
@@ -0,0 +1,114 @@
+Symtab for file _globals_
+
+Line table:
+
+
+Blockvector:
+
+block #000 (object 0x41a5cc) [0x0..0x0]
+ char _ac_s[0]; static at 0x4001d0,
+ int _dbargs; static at 0x4002c8,
+ int environ; static at 0x4001c4,
+ int splimit%; static at 0x4001c0,
+  block #001 (object 0x41a5a8) [0x0..0x0] (under 0x41a5cc)
+
+
+Symtab for file copyright.c
+
+Line table:
+
+
+Blockvector:
+
+block #000 (object 0x41a460) [0x0..0x0]
+  block #001 (object 0x41a444) [0x0..0x0] (under 0x41a460)
+   char *_ac_r; static at 0x4001cc,
+
+
+Symtab for file fakcu.c
+
+Line table:
+
+ line 23 at 194
+ line 24 at 1aa
+
+Blockvector:
+
+block #000 (object 0x41a3f0) [0x0..0x0]
+ void _cleanup; block (object 0x41a380) starting at 0x194,
+  block #001 (object 0x41a3d4) [0x0..0x0] (under 0x41a3f0)
+   char *_ac_r; static at 0x4001c8,
+    block #002 (object 0x41a380) [0x194..0x1b0] (under 0x41a3d4) _cleanup
+
+
+Symtab for file cuexit.s
+
+Line table:
+
+
+Blockvector:
+
+block #000 (object 0x41f210) [0x0..0x0]
+  block #001 (object 0x41f1ec) [0x0..0x0] (under 0x41f210)
+
+
+Symtab for file initfpu.s
+
+Line table:
+
+
+Blockvector:
+
+block #000 (object 0x41e1c4) [0x0..0x0]
+  block #001 (object 0x41e1a0) [0x0..0x0] (under 0x41e1c4)
+
+
+Symtab for file dbxxx.s
+
+Line table:
+
+
+Blockvector:
+
+block #000 (object 0x41d178) [0x0..0x0]
+  block #001 (object 0x41d154) [0x0..0x0] (under 0x41d178)
+
+
+Symtab for file foo.c
+
+Line table:
+
+ line 1 at e4
+ line 2 at fa
+ line 4 at fa
+ line 5 at 106
+ line 6 at 112
+ line 7 at 126
+ line 9 at 126
+ line 10 at 13c
+ line 12 at 13c
+ line 13 at 144
+
+Blockvector:
+
+block #000 (object 0x41a2d8) [0x0..0x0]
+ int bar; block (object 0x41a2b0) starting at 0x126,
+ int main; block (object 0x41a220) starting at 0xe4,
+  block #001 (object 0x41a23c) [0x0..0x0] (under 0x41a2d8)
+    block #002 (object 0x41a220) [0xe4..0x120] (under 0x41a23c) main
+     int i; local at 0xfffffffc,
+    block #003 (object 0x41a2b0) [0x126..0x150] (under 0x41a23c) bar
+     int i; local at 0xfffffffc,
+
+
+Symtab for file crt0.s
+
+Line table:
+
+
+Blockvector:
+
+block #000 (object 0x41b178) [0x0..0x0]
+  block #001 (object 0x41b154) [0x0..0x0] (under 0x41b178)
+
+
diff --git a/gdb/frame.h b/gdb/frame.h
new file mode 100644 (file)
index 0000000..3f51c45
--- /dev/null
@@ -0,0 +1,64 @@
+/* Definitions for dealing with stack frames, 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!
+*/
+
+/* Note that frame.h requires param.h! */
+
+#define FRAME CORE_ADDR
+
+struct frame_info
+  {
+    /* Nominal address of the frame described.  */
+    FRAME frame;
+    /* Address at which execution is occurring in this frame.
+       For the innermost frame, it's the current pc.
+       For other frames, it is a pc saved in the next frame.  */
+    CORE_ADDR pc;
+    /* The frame called by the frame we are describing, or 0.  */
+    FRAME next_frame;
+  };
+
+/* Describe the saved registers of a frame.  */
+
+struct frame_saved_regs
+  {
+    /* For each register, address of where it was saved on entry to the frame,
+       or zero if it was not saved on entry to this frame.  */
+    CORE_ADDR regs[NUM_REGS];
+  };
+
+/* The stack frame that the user has specified for commands to act on.
+   Note that one cannot assume this is the address of valid data.  */
+
+extern FRAME selected_frame;
+
+extern struct frame_info get_frame_info ();
+extern struct frame_info get_prev_frame_info ();
+
+extern void get_frame_saved_regs ();
+
+extern FRAME get_prev_frame ();
+
+extern FRAME get_current_frame ();
+
+extern struct block *get_frame_block ();
+extern struct block *get_current_block ();
+extern struct block *get_selected_block ();
+extern struct symbol *get_frame_function ();
+extern struct symbol *get_pc_function ();
diff --git a/gdb/gdb.1 b/gdb/gdb.1
new file mode 100644 (file)
index 0000000..11a42a6
--- /dev/null
+++ b/gdb/gdb.1
@@ -0,0 +1,91 @@
+.TH GDB 1 "13 April 1987"
+.UC 4
+.SH NAME
+gdb \- Project GNU's DeBugger
+.SH SYNOPSIS
+\fBgdb\fP [ \fBoptions\fP ]   See documentation mentioned below.
+.SH DESCRIPTION
+\fIgdb\fP is a source level symbolic debugger for C programs, created by
+Richard M. Stallman (rms) for the GNU Project, and distributed by the
+Free Software Foundation.  Eventually GNU (Gnu's Not Unix) will be a
+complete replacement for Berkeley Unix, all of which everyone will be
+able to use freely.  See the \fIGNU Emacs\fP man page for pointers to more
+information.
+.PP
+\fIgdb\fP has something of the flavor of \fIdbx\fP,
+but has more features and power.  It can also be used to debug o/s
+kernels, but needs to be configured differently for that task.
+.PP
+Project GNU isn't using Unix man pages.  Its style of complete
+documentation can be found by:
+.PP
+The help and info commands inside \fIgdb\fP.
+.PP
+In the Info system in \fIGNU Emacs\fP.  Type C-h i, and follow the
+directions.  This is equivalent to the reference manual for 
+\fIgdb\fP, and has about 55 pages of text.
+.PP
+\fIgdb\fP could be extended to work with other languages (e.g. Pascal) and
+machines (e.g. encores).  If you like, copy the sources and give it a
+try.  When you have it working send \fIdiff -c\fP's of the changed files to
+bug-gdb@prep.ai.mit.edu (fuller details below), so they can benefit everyone.
+.SH DISTRIBUTION
+\fIgdb\fP is free; anyone may redistribute copies of
+\fIgdb\fP to anyone under the terms stated in the
+\fIgdb\fP General Public License, a copy of which accompanies each copy of
+\fIgdb\fP, is readable with the info command inside \fIgdb\fP,
+and which also appears in the \fIgdb\fP reference manual.
+.PP
+Copies of \fIgdb\fP may sometimes be received packaged with
+distributions of Unix systems, but it is never included in the scope
+of any license covering those systems.  Such inclusion would violate
+the terms on which distribution is permitted.  In fact, the primary
+purpose of the General Public License is to prohibit anyone from
+attaching any other restrictions to redistribution of \fIgdb\fP.
+.PP
+You can order printed copies of the \fIgdb\fP reference manual for $10.00/copy
+postpaid from the Free Software Foundation, which develops GNU software
+(contact them for quantity prices on the manual).  Their address is:
+.nf
+    Free Software Foundation
+    1000 Mass Ave.
+    Cambridge, MA  02138
+.fi
+As with all software and publications from FSF, everyone is permitted to
+make and distribute copies of the \fIgdb\fP reference manual.
+The TeX source to the \fIgdb\fP reference
+manual is also included in the \fIGNU Emacs\fP source distribution.
+.PP
+.SH OPTIONS
+See documentation.
+.SH EXAMPLES
+See documentation.
+.SH "SEE ALSO"
+adb(1), sdb(1), dbx(1)
+.SH BUGS
+There is a mailing list, bug-gdb@prep.ai.mit.edu on the internet
+(ucbvax!prep.ai.mit.edu!bug-gdb on UUCPnet), for reporting \fIgdb\fP
+bugs and fixes.  But before reporting something as a bug, please try
+to be sure that it really is a bug, not a misunderstanding or a
+deliberate feature.  We ask you to read the section ``Reporting Emacs
+Bugs'' near the end of the \fIGNU Emacs\fP reference manual
+(or Info system) for hints
+on how and when to report bugs.  Also, include the version number of
+the \fIgdb\fP you are running in \fIevery\fR bug report that you send in.
+.PP
+Do not expect a personal answer to a bug report.  The purpose of reporting
+bugs is to get them fixed for everyone in the next release, if possible.
+For personal assistance, look in the SERVICE file
+(see the \fIGNU Emacs\fP man page) for
+a list of people who offer it.
+.PP
+Please do not send anything but bug reports to this mailing list.
+Send other stuff to gnu@prep.ai.mit.edu (or the
+corresponding UUCP address).  For more information about GNU mailing
+lists, see the file MAILINGLISTS (see the \fIGNU Emacs\fP man page).  Bugs tend
+actually to be fixed if they can be isolated, so it is in your
+interest to report them in such a way that they can be easily
+reproduced.
+.PP
+No bugs are known at this time.
+
diff --git a/gdb/gdb.ideas b/gdb/gdb.ideas
new file mode 100644 (file)
index 0000000..7b9e976
--- /dev/null
@@ -0,0 +1,694 @@
+BABYL OPTIONS:
+Version: 5
+Labels:
+Note:   This is the header of an rmail file.
+Note:   If you are seeing it in rmail,
+Note:    it means the file has no messages in it.
+\1f\f
+From: mly@MICHAEL.AI.MIT.EDU (Richard Mlynarik)
+To: rms@prep.ai.mit.edu
+Subject: gdb suggestions (from hpux cdb)
+Reply-To: mly-prep@prep.ai.mit.edu
+
+"find-bug" command says "I can see the problem, but it will do you
+good to find it yourself"
+
+The gdb manual should explicitly state that gdb has no control over
+forked (or execed or whatever) subprocesses.
+
+I'd still like it if "delete" said what it had done.
+
+\f
+Date: Tuesday, 13 May 1986, 00:40-EDT
+From: <rms@LMI-ANGEL>
+Sender: JC@LMI-ANGEL
+Subject: interesting sdb features
+To: rms@angel
+
+output format p = pointer to procedure.
+
+foo/x or foo/4x uses size of foo as size to print.
+
+foo[1;4] to get elements 1 thru 4.
+
+Continue to specified line number.
+
+Interactively delete all breakpoints (asking about each one).
+
+
+\f
+Command to write backtrace into a file, or even better to duplicate all
+output to a file.  This could work by playing with descriptor 1,
+making it a pipe to `tee'.  The original descriptor 1 is saved and
+this mode can be turned off by putting it back.
+  Date: Wed, 18 Feb 87 15:37:14 EST
+  From: rms (Richard M. Stallman)
+  Message-Id: <8702182037.AA16492@prep.ai.mit.edu>
+  To: mly-prep@prep.ai.mit.edu
+  In-Reply-To: <8702181913.AA16118@prep.ai.mit.edu>
+  Subject: gdb "photo" command
+
+  I don't think all this is worth the trouble to do now,
+  because the right way to do it on TRIX is totally different
+  and much easier.
+
+
+Commands to enable and disable the autodisplays.  Associate
+autodisplays with breakpoints perhaps, so they only display
+at those breakpoints; this is easier than using breakpoint commands.
+
+Remember how each breakpoint's position was specified.
+Have command to reread symbol table and respecify each
+breakpoint using same args (line number or function name) as before.
+
+Have way to proceed process in background so that can then suspend
+gdb but have subprocess continue
+
+\f
+Date: Fri, 24 Jul 87 21:30:25 EDT
+From: phr@PREP.AI.MIT.EDU (Paul Rubin)
+To: bug-gdb@PREP.AI.MIT.EDU
+
+After rereading the symbol table when user runs the "symbol-file"
+command, when GDB notices that some of the source files are newer
+it should reload them rather than just printing a message saying
+they are newer.
+
+
+\f
+Message-Id: <8704171941.AA05045@orville.arpa>
+To: mly@prep.ai.mit.edu
+Cc: raible@orville.arpa, fouts@orville.arpa, creon@orville.arpa
+Subject: gdb hack/questions, etc
+Date: 17 Apr 87 11:41:42 PST (Fri)
+From: raible@orville.arpa
+
+
+A couple of things:
+
+1) Will gdb ever get dbx-sytly tracing?  Wouldn't it be fairly easy to add?
+
+2) How about an xemacs gdb mode which has various windows, perhaps using
+   terminal.el for generality?
+
+3) Any word about that stupid IRIS SIGIOT problem?  Do you know of anyone
+   else who has gotten IRIS subprocesses to work more reliably?
+
+4) Below is a hack adapted from ramsdell@linus.uucp which can be pretty
+   useful in gdb.  Instead of using gdb to patch extensive changes to a
+   particular function, you can do the following (assuming the 50 lines
+   of code below is part of your executable):
+       1) create a new file (foo.c) containing the new function
+       2) run cc -c foo.c
+       3) in gdb, and patch in the new function as follows:
+
+(gdb) info breakpoints
+/* Load in the new object code... */
+#1   y  0x00000125  in main (dyn.c line 46)
+       break only if $function = funload ("foo"), 1
+       silent
+       echo new code for func ($function) initialized\n
+       cont
+
+/* ...and use it instead of the old code. */
+#2   y  0x000001c2  in func (dyn.c line 59)
+       break only if $ret = $function (a), 1
+       silent
+       set a = $ret
+       j 60            /* func has a return on line 60 */
+
+       This is more complicated than it has to be because of 2 bugs in v2.1:
+       1) function calls in a breakpoint command list seem to abort
+          the execution of the rest of the command list.  This is
+          why all function calls are in the conditional part.
+          (gdb reference manual section 5.5).
+
+       2) A 'return' in a command list also aborts the execution, and
+          in addition, prompts you for a y/n.
+          (gdb reference manual section 11.1).
+
+       On the other hand, after doing 'cc -c foo.c' (which is pretty fast),
+       you can simply rerun your program to check out the changes.
+       This can be a big win!
+
+The code for this is included below (compile with cc -g):
+========================================================
+
+#include <stdio.h>
+#include <a.out.h>
+
+typedef int (*intfun)();
+char *myname;
+
+intfun funload (filename)      /* Dynamically load 1st function from a .o */
+     char *filename;
+{
+  int fd, size;
+  struct exec hdr;
+  char buf[100];
+  intfun fun;
+
+  /* -A => incremental loading - use dyn as the base symbol table
+     -T => set the text segment origin to the following hex address
+     -N => magic number 407 (text not read-only)
+  */
+  sprintf (buf, "ld -A %s -T %x -N %s.o -o %s -lc",
+          myname, sbrk (0), filename, filename);
+
+  /* NOTE: if anything mallocs space between here and below, this will fail */
+  system (buf);
+
+  fd = open (filename, 0);
+  read (fd, &hdr, sizeof(hdr));
+  size = hdr.a_text + hdr.a_data + hdr.a_bss;
+
+  if ((fun = (intfun) sbrk (size)) < 0)
+    printf ("Couldn't find the space"), exit();
+
+  read (fd, fun, size);                /* Load code. */
+  /* NOTE: if anything mallocs space between here and above, this will fail */
+
+  close (fd);
+  return ((intfun) fun);
+}
+  
+main (argc, argv)
+     char **argv;
+{
+  intfun fun1, fun2;
+
+  myname = *argv;
+
+  fun1 = funload("fun1");
+  printf ("The answer is %d.\n", (*fun1)(11) );
+
+  fun2 = funload("fun2");
+  printf ("The answer is %d.\n", (*fun2)() );
+}\f
+1,edited,,
+Received: by PREP.AI.MIT.EDU; Tue, 16 Jun 87 03:12:54 EDT
+Date: Tue, 16 Jun 87 03:12:54 EDT
+From: rms (Richard M. Stallman)
+Message-Id: <8706160712.AA07910@prep.ai.mit.edu>
+To: rms
+Subject: GDB ideas
+
+*** EOOH ***
+Date: Tue, 16 Jun 87 03:12:54 EDT
+From: rms (Richard M. Stallman)
+To: rms
+Subject: GDB ideas
+
+* Within a user-defined command, have local convenience variables,
+local functions, local defined commands.
+
+** Optionally echo commands within a user-defined command.
+
+** Optionally record all user-typed commands in a log file.
+Optionally record GDB output there too, marked as output so it
+will not be executed if replayed.
+
+* Execution commands
+
+** Step until next branch, or next call.
+(finish is step until next return).
+
+step branch
+or should it be
+continue branch
+
+** Stop on any branch, call or return
+affecting ordinary step and continue commands.
+
+stop branch
+
+** Trace all branches, calls, returns.
+This could be done by stopping on those events
+and having a continue command to be executed after.
+
+stop branch
+commands branch
+continue
+end
+
+** Commands to continue or step without any display after stop.
+These may be useful in user-defined commands.
+
+Have one prefix command that does this, modifying whatever other
+command you might use.  For example,
+
+silent step 5
+silent cont
+
+** Clear all breakpoint ignore-counts when inferior exits or is killed.
+
+** Trace changes to a location (watchpoint).
+Enable and disable them.
+
+** Info command to show command-line for running the program.
+
+* Auto-display
+
+** Enable and disable display expressions.
+Allow syntax 1d, 2d, etc. in enable, disable and delete commands.
+Then there is no more need for an undisplay command.
+
+** Displaying an auto variable should not do it in the wrong stack frame.
+Either it should search for the proper stack frame to apply to
+or it should deactivate itself when in the wrong frame.
+
+* Printing
+
+** Print an address as <file:line>+offset.
+
+** Abbreviate initial whitespace modulo 16.
+
+** p/x of an array should print each element with /x.
+
+** Change the stack scan so that it has a more general idea
+of what info is needed to describe a frame fully.
+
+* Expressions
+
+** Array slices.  Can replace @.
+
+** %name for use of symbol names containing funny characters.
+
+** User-defined convenience functions that can appear in expressions.
+
+** Expression syntax to convert line number to address.
+
+** Expression syntax to specify a name scope with an address, line number
+or frame number.
+
+Use the line number by itself, or an address with *, just as in b or l cmd:
+38:foo or *0x40a:foo.  No good; the latter would be parsed as
+*(0x40a:foo).
+
+** Expression syntax to convert a frame number to its pc.
+Perhaps unary %.
+
+* Possible bugs
+
+** Does set $pc= cause the current scope to be recalculated?
+It should.
+\1f\f
+1,,
+Received: by PREP.AI.MIT.EDU; Wed, 17 Jun 87 09:59:37 EDT
+From: phr@ATHENA.MIT.EDU
+Received: by ATHENA (5.45/4.7)
+       id AA09084; Wed, 17 Jun 87 08:54:36 EDT
+Received: by ORPHEUS.MIT.EDU (5.45/4.7) id AA02565; Wed, 17 Jun 87 08:54:29 EDT
+Date: Wed, 17 Jun 87 08:54:29 EDT
+Message-Id: <8706171254.AA02565@ORPHEUS.MIT.EDU>
+To: rms@prep.ai.mit.edu
+Subject: gdb suggestion
+Status: RO
+
+*** EOOH ***
+From: phr@ATHENA.MIT.EDU
+Date: Wed, 17 Jun 87 08:54:29 EDT
+To: rms@prep.ai.mit.edu
+Subject: gdb suggestion
+
+Completion of file and function names; e.g. typing
+       break XWriteBi
+prints
+       No such symbol: XWriteBi.
+       Setting default command to "break XWriteBitmapFile"
+so you can set a break at XWriteBitmapFile by hitting return a second
+time.  Other interfaces ("complete to XWriteBitmapFile? (y/n)")
+are also possible.
+
+\1f\f
+1,edited,,
+Received: by PREP.AI.MIT.EDU; Wed, 24 Sep 86 16:33:11 EDT
+Date: Wed, 24 Sep 86 16:33:11 EDT
+From: mly (Richard Mlynarik)
+Message-Id: <8609242033.AA11520@prep.ai.mit.edu>
+To: rms
+Cc: mly-prep
+Subject: gdb gripes/suggestions/requests
+
+*** EOOH ***
+Date: Wed, 24 Sep 86 16:33:11 EDT
+From: mly (Richard Mlynarik)
+To: rms
+Cc: mly-prep
+Subject: gdb gripes/suggestions/requests
+
+If would be really nice to have some way to do conditionals in user
+  commands -- though this is really stretching the functionality of
+  gdb a little too much, perhaps.  (see ~mly/e/.gdbint for some of
+  the contortions I go through with || to get conditional
+  evaluation...)
+
+A -real- win wuold be some way to execute until he next function-call
+  (like c-d in the cadr debugger)  This would even be useful if it
+  were rather slow -- it would probably be faster than setting
+  temporary breakpoints in all the functions which might be called,
+  and would certainly be faster than "step"ping one's way until a
+  funcall happened.
+
+"info source" should mention what the directory search-path is (ie
+  what "info dir" says) and in which directory it found each of the
+  source files (and which source files it cannot locate in the
+  search-path)
+
+\1f\f
+1,,
+Received: by xcssun.Berkeley.EDU (5.57/1.25)
+       id AA22869; Thu, 22 Oct 87 09:50:30 PDT
+Received: from prep.ai.mit.edu by wheaties.ai.mit.edu; Thu, 22 Oct 87 12:17:59 EDT
+Received: by PREP.AI.MIT.EDU; Thu, 22 Oct 87 12:21:00 EDT
+Received: from pp.mcc.com by MCC.COM with TCP; Thu 22 Oct 87 10:54:41-CDT
+Posted-Date: Thu, 22 Oct 87 10:55:13 CDT
+Received: from big-d.aca.mcc.com by pp.mcc.com (4.12/KA70822) 
+       id AA16571; Thu, 22 Oct 87 10:55:19 cdt
+Return-Path: <tiemann@big-d.aca.mcc.com>
+Received: by big-d.aca.mcc.com (3.2/KA70106)
+       id AA04247; Thu, 22 Oct 87 10:55:13 CDT
+Date: Thu, 22 Oct 87 10:55:13 CDT
+From: tiemann%pp.mcc.com@mcc.com (Michael Tiemann)
+Message-Id: <8710221555.AA04247@big-d.aca.mcc.com>
+To: bug-gdb@prep.ai.mit.edu
+Subject: expanding file names
+
+*** EOOH ***
+Posted-Date: Thu, 22 Oct 87 10:55:13 CDT
+Return-Path: <tiemann@big-d.aca.mcc.com>
+Date: Thu, 22 Oct 87 10:55:13 CDT
+From: tiemann%pp.mcc.com@mcc.com (Michael Tiemann)
+To: bug-gdb@prep.ai.mit.edu
+Subject: expanding file names
+
+When running a program, gdb thoughtfully passes the argument list
+through the shell, expanding files and environment variables as
+needed.  It would be nice if the same facility were added to the
+command which adds directories to search paths.  For example, it would
+be nice to say "dir ~/foo" .
+
+Michael
+
+\1f\f
+1,,
+Received: by xcssun.Berkeley.EDU (5.57/1.25)
+       id AA25075; Fri, 23 Oct 87 10:42:52 PDT
+Received: from prep.ai.mit.edu by wheaties.ai.mit.edu; Fri, 23 Oct 87 13:39:37 EDT
+Received: by PREP.AI.MIT.EDU; Fri, 23 Oct 87 13:42:53 EDT
+Received: from relay2.cs.net by RELAY.CS.NET id ac11193; 23 Oct 87 13:03 EDT
+Received: from umb.edu by RELAY.CS.NET id ac05949; 23 Oct 87 13:01 EDT
+Received: by umb.umb.edu; Fri, 23 Oct 87 10:18:40 EDT
+Received: by ileaf.uucp (1.1/SMI-3.0DEV3)
+       id AA00599; Wed, 21 Oct 87 10:56:52 EDT
+Received: from marvin.io.uucp by io.uucp (1.1/SMI-3.0DEV3)
+       id AA01359; Wed, 21 Oct 87 10:58:45 EDT
+Received: by marvin.io.uucp (3.2/SMI-3.2)
+       id AA00334; Wed, 21 Oct 87 11:02:20 EDT
+Date: Wed, 21 Oct 87 11:02:20 EDT
+From: Mark Dionne <io!marvin!md%ileaf.uucp%umb.umb.edu@relay.cs.net>
+Message-Id: <8710211502.AA00334@marvin.io.uucp>
+To: ileaf!umb!bug-gdb@prep.ai.mit.edu
+Subject: gdb bug
+
+*** EOOH ***
+Date: Wed, 21 Oct 87 11:02:20 EDT
+From: Mark Dionne <io!marvin!md%ileaf.uucp%umb.umb.edu@relay.cs.net>
+To: ileaf!umb!bug-gdb@prep.ai.mit.edu
+Subject: gdb bug
+
+The /FMT and @ options of the "print" command seem to interact
+in GDB 2.1. For example:
+
+(gdb) p ($cmpn.buf[-1])@($cmpn.gapb - $cmpn.buf + 1)
+$17 = {-16383, -24285, 55, 27944, -24285, -24285, 55, 28010, -24285,
+-24285, 55, 28076, -24285, -24285, 55, 28142, -24285}
+(gdb) p/x ($cmpn.buf[-1])@($cmpn.gapb - $cmpn.buf + 1)
+$18 = 0xc001
+
+I guess I see what's happening: the /x is applying to the whole
+array rather than to the individual elements. Feature or bug?
+
+       ...!harvard!umb!ileaf!md        Mark Dionne, Interleaf
+         ...!sun!sunne!ileaf!md        Ten Canal Park, Cambridge, MA 02141
+                                       (617) 577-9813 x5551
+
+
+\1f\f
+1,,
+Received: by PREP.AI.MIT.EDU; Sun, 6 Sep 87 14:27:19 EDT
+Message-Id: <8709061827.AA18170@prep.ai.mit.edu>
+Received: from relay2.cs.net by RELAY.CS.NET id af03990; 6 Sep 87 14:22 EDT
+Received: from umb.edu by RELAY.CS.NET id ab03029; 6 Sep 87 14:16 EDT
+Received: by umb.umb.edu; Sun, 6 Sep 87 12:10:34 EDT
+Date: Sun, 6 Sep 87 12:10:34 EDT
+Received: by typo.umb.edu; Sun, 6 Sep 87 12:04:21 EDT
+From: Robert Morris <ram%typo.umb.edu@RELAY.CS.NET>
+To: bug-gdb@PREP.AI.MIT.EDU
+Subject: convenient script
+
+*** EOOH ***
+Date: Sun, 6 Sep 87 12:10:34 EDT
+From: Robert Morris <ram%typo.umb.edu@RELAY.CS.NET>
+To: bug-gdb@PREP.AI.MIT.EDU
+Subject: convenient script
+
+I find it easier to maintain binaries on our heterogenous
+network if I keep this trivial script in gdb source directory. Use it
+if you want.
+
+
+------------
+
+#! /bin/csh -f
+#      SETUP
+#      setup gdb files for presently known machines
+#      ram@umb.edu 
+#              (ram%umb.edu@relay.cs.net if you have an incomplete mailer)
+#      or ...!harvard!umb!ram
+#
+#      e.g.     SETUP sun3
+#      note that sunX means major release X of sun software, generally
+#      sun3 at this writing (gnu 18.41)
+#
+#      note GDB with gnuemacs 18.41 is already configured for vaxen
+
+#              Bob Morris, UMASS-Boston 9/6/87
+switch ($1)
+       case "sun2":
+               ;
+       case "sun3" : 
+               set cputype="m68k";
+               set inittype="suninit";
+               breaksw;
+       default : 
+               set cputype=$1;
+               set inittype=$1init;
+               breaksw;
+endsw
+echo \#include \"m-$1.h\" > param.h
+echo \#include \"$cputype-pinsn.c\" > pinsn.c
+ed initialize.h <<! >& /dev/null
+/init.h/
+c
+#include "m-$inittype.h"
+.
+w
+q
+!
+
+
+
+\1f\f
+1,answered,,
+Received: from prep.ai.mit.edu by wheaties.ai.mit.edu; Sat, 19 Dec 87 18:18:50 EST
+Received: by PREP.AI.MIT.EDU; Sat, 19 Dec 87 18:24:38 EST
+Received: from big-d.aca.mcc.com by MCC.COM with TCP; Sat 19 Dec 87 17:19:48-CST
+Date: Sat, 19 Dec 87 17:19:41 CST
+From: tiemann@mcc.com (Michael Tiemann)
+Posted-Date: Sat, 19 Dec 87 17:19:41 CST
+Message-Id: <8712192319.AA26775@big-d.aca.mcc.com>
+Received: by big-d.aca.mcc.com (3.2/ACA-V2.1) 
+       id AA26775; Sat, 19 Dec 87 17:19:41 CST
+To: rms@prep.ai.mit.edu
+Subject: gdb
+
+*** EOOH ***
+Date: Sat, 19 Dec 87 17:19:41 CST
+From: tiemann@mcc.com (Michael Tiemann)
+Posted-Date: Sat, 19 Dec 87 17:19:41 CST
+To: rms@prep.ai.mit.edu
+Subject: gdb
+
+file values.c, function unpack_field_as_long:
+
+  val &= (1 << bitsize) - 1;
+
+This is not as machine independent as it could be.  If you feel like
+fixing this potential problem, there are many other instances to worry
+about.
+
+Michael
+
+\1f\f
+1,,
+Received: by xcssun.Berkeley.EDU (5.57/1.25)
+       id AA04771; Thu, 20 Aug 87 22:33:25 PDT
+Received: from [128.52.22.14] by ucbvax.Berkeley.EDU (5.58/1.27)
+       id AA07119; Thu, 20 Aug 87 00:37:04 PDT
+Received: by PREP.AI.MIT.EDU; Thu, 20 Aug 87 03:37:35 EDT
+Date: Thu, 20 Aug 87 03:37:35 EDT
+From: rms@prep.ai.mit.edu (Richard M. Stallman)
+Message-Id: <8708200737.AA15589@prep.ai.mit.edu>
+To: rms@prep.ai.mit.edu
+Subject: GDB changes for next version
+
+*** EOOH ***
+Date: Thu, 20 Aug 87 03:37:35 EDT
+From: rms@prep.ai.mit.edu (Richard M. Stallman)
+To: rms@prep.ai.mit.edu
+Subject: GDB changes for next version
+
+1. Use links, rather than editing some files, to configure it.
+
+2. Can misc functions eval as their addresses rather than as
+ a char in that address?  Is this reasonable in all cases
+ given that non-functions cannot be distinguished
+ and that you might use the result in various ways (arithmetic, etc.).
+
+\1f\f
+1,,
+Received: by xcssun.Berkeley.EDU (5.57/1.25)
+       id AA09136; Sat, 29 Aug 87 02:20:15 PDT
+Received: from PREP.AI.MIT.EDU by ucbvax.Berkeley.EDU (5.58/1.27)
+       id AA26072; Sat, 29 Aug 87 02:21:51 PDT
+Received: by PREP.AI.MIT.EDU; Sat, 29 Aug 87 05:22:30 EDT
+Received: by RUTGERS.EDU (5.54/1.14) with UUCP 
+       id AA22247; Sat, 29 Aug 87 05:21:13 EDT
+Received: from sequent.UUCP by spool.wisc.edu; Sat, 29 Aug 87 04:18:41 CDT
+Received: from reed.UUCP by ogcvax.OGC.EDU (5.51/OGC_4.8)
+               id AA08044; Fri, 28 Aug 87 20:06:41 PDT
+Received: by reed.UUCP (5.51/5.17)
+       id AA05059; Fri, 28 Aug 87 19:19:15 PDT
+From: uwvax!sequent!ogcvax!reed!keith@rutgers.edu (Keith Packard)
+Message-Id: <8708290219.AA05059@reed.UUCP>
+To: rms@prep.ai.mit.edu
+Subject: Re: GDB 
+In-Reply-To: Your message of Thu, 20 Aug 87 03:39:37 EDT.
+             <8708200735.AA26546@EDDIE.MIT.EDU> 
+Date: Fri, 28 Aug 87 19:19:13 PDT
+
+*** EOOH ***
+From: uwvax!sequent!ogcvax!reed!keith@rutgers.edu (Keith Packard)
+To: rms@prep.ai.mit.edu
+Subject: Re: GDB 
+In-Reply-To: Your message of Thu, 20 Aug 87 03:39:37 EDT.
+             <8708200735.AA26546@EDDIE.MIT.EDU> 
+Date: Fri, 28 Aug 87 19:19:13 PDT
+
+
+Here is a simple test program for exibiting the trouble with signals:
+
+-----
+# include      <signal.h>
+
+main ()
+{
+       int     handle ();
+       int     i;
+       signal (SIGALRM, handle);
+       alarm (5);
+       for (i = 0; i < 100000; i++)
+               printf ("%d\n", i);
+}
+
+handle ()
+{
+       printf ("signal!\n");
+       alarm (5);
+}
+-----
+
+To demonstrate the problem, simply place a breakpoint before the call to
+alarm and then start stepping through the program:
+
+(gdb) break 7
+(gdb) step
+...
+...
+
+Eventually, the alarm call occurs and the program ends up in some
+signal handling code -- unfortuantely a machine dependent location.  At this
+point, because the fp has moved out of the current function (in fact on
+many machines the frame is not in a consistent state at this point) gdb
+assumes that a new function has started and suspends execution with another
+prompt.
+
+A reasonable solution would be to have gdb insert a breakpoint at the
+expected signal return address and continue to that breakpoint -- I've
+implemented this and found that it works.  There is, however, one nasty
+problem -- longjmp around the suspended frame and the breakpoint is not hit
+at the expected time.
+
+Have fun...
+
+keith packard
+
+tektronix!reed!keith
+
+\1f\f
+1,,
+Received: by xcssun.Berkeley.EDU (5.57/1.25)
+       id AA09143; Sat, 29 Aug 87 02:24:58 PDT
+Received: by neptune.Berkeley.EDU (5.57/1.25)
+       id AA03738; Sat, 29 Aug 87 02:24:50 PDT
+Date: Sat, 29 Aug 87 02:24:50 PDT
+From: rms@neptune.berkeley.edu (Richard Stallman)
+Message-Id: <8708290924.AA03738@neptune.Berkeley.EDU>
+To: rms@neptune.Berkeley.EDU
+Subject: GDB bug
+Reply-To: rms@prep.ai.mit.edu
+
+*** EOOH ***
+Date: Sat, 29 Aug 87 02:24:50 PDT
+From: rms@neptune.berkeley.edu (Richard Stallman)
+To: rms@neptune.Berkeley.EDU
+Subject: GDB bug
+Reply-To: rms@prep.ai.mit.edu
+
+Is there any way to make GDB, when stepping across a function call,
+notice any attempt to longjump out of that call?
+Perhaps an implicit breakpoint at longjump.
+If longjump is called, find the pc in the jmp_buf and put
+a self-deleting breakpoint there.
+
+\1f\f
+1,,
+Received: by xcssun.Berkeley.EDU (5.57/1.25)
+       id AA07976; Fri, 28 Aug 87 09:26:12 PDT
+Received: from PREP.AI.MIT.EDU by ucbvax.Berkeley.EDU (5.58/1.27)
+       id AA03230; Fri, 28 Aug 87 09:28:04 PDT
+Received: by PREP.AI.MIT.EDU; Fri, 28 Aug 87 12:28:43 EDT
+Date: Fri, 28 Aug 87 12:28:43 EDT
+From: phr@prep.ai.mit.edu (Paul Rubin)
+Message-Id: <8708281628.AA09926@prep.ai.mit.edu>
+To: rms@prep.ai.mit.edu
+Subject: gdb suggestions
+
+*** EOOH ***
+Date: Fri, 28 Aug 87 12:28:43 EDT
+From: phr@prep.ai.mit.edu (Paul Rubin)
+To: rms@prep.ai.mit.edu
+Subject: gdb suggestions
+
+1. I wish gdb had a command to re-read the sources so that I can edit
+the program and recompile it without having to kill and restart gdb.
+
+2. Would be nice if gdb could somehow connect the subprocess's tty channels
+to a pty, so I can run gdb in an X window and the subprocess in a different
+(xterm) window.
+
+This might need hair to detect if the subprocess is running when you try
+to examine variables, etc. and stop the subproc or report an error if it is.
+
+\1f
\ No newline at end of file
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
new file mode 100644 (file)
index 0000000..f2a9944
--- /dev/null
@@ -0,0 +1,927 @@
+/* Memory-access and commands for inferior process, 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 "defs.h"
+#include "initialize.h"
+#include "symtab.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "environ.h"
+#include "value.h"
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/param.h>
+
+#ifdef mac_aux
+/* Warning!  This table is positional and highly dependent on the local
+   system.  Check it closely against <sys/signal.h> when porting. */
+char *sys_siglist[] = {
+       "Signal 0",
+       "Hangup",
+       "Interrupt",
+       "Quit",
+       "Invalid instruction",
+       "Trace/breakpoint trap",
+       "IOT trap",
+       "EMT trap",
+       "Floating point exception",
+       "Killed",
+       "Bus error",
+       "Segmentation fault",
+       "Bad system call",
+       "Broken pipe",
+       "Alarm clock",
+       "Terminated",
+       "User signal 1",
+       "User signal 2",
+       "Child exited",
+       "Power-fail restart",
+       "Stopped",
+       "Stopped (tty input)",
+       "Stopped (tty output)",
+       "Stopped (signal)",
+       "Cputime limit exceeded",
+       "File size limit exceeded",
+       "Virtual timer expired",
+       "Profiling timer expired",
+       "Window changed",
+       "Continued",
+       "Urgent I/O condition",
+       "I/O possible",
+};
+#else
+/* More portable systems do it for you */
+extern char *sys_siglist[];
+#endif
+
+#define ERROR_NO_INFERIOR \
+   if (inferior_pid == 0) error ("The program is not being run.");
+
+/* String containing arguments to give to the program,
+   with a space added at the front.  Just a space means no args.  */
+
+static char *inferior_args;
+
+/* File name for default use for standard in/out in the inferior.  */
+
+char *inferior_io_terminal;
+
+/* Pid of our debugged inferior, or 0 if no inferior now.  */
+
+int inferior_pid;
+
+/* Last signal that the inferior received (why it stopped).  */
+
+int stop_signal;
+
+/* Address at which inferior stopped.  */
+
+CORE_ADDR stop_pc;
+
+/* Stack frame when program stopped.  */
+
+FRAME stop_frame;
+
+/* Number of breakpoint it stopped at, or 0 if none.  */
+
+int stop_breakpoint;
+
+/* Nonzero if stopped due to a step command.  */
+
+int stop_step;
+
+/* Nonzero if stopped due to completion of a stack dummy routine.  */
+
+int stop_stack_dummy;
+
+/* Range to single step within.
+   If this is nonzero, respond to a single-step signal
+   by continuing to step if the pc is in this range.  */
+
+CORE_ADDR step_range_start; /* Inclusive */
+CORE_ADDR step_range_end; /* Exclusive */
+
+/* Stack frame address as of when stepping command was issued.
+   This is how we know when we step into a subroutine call,
+   and how to set the frame for the breakpoint used to step out.  */
+
+CORE_ADDR step_frame;
+
+/* 1 means step over all subroutine calls.
+   -1 means step over calls to undebuggable functions.  */
+
+int step_over_calls;
+
+/* If stepping, nonzero means step count is > 1
+   so don't print frame next time inferior stops
+   if it stops due to stepping.  */
+
+int step_multi;
+
+/* Environment to use for running inferior,
+   in format described in environ.h.  */
+
+struct environ *inferior_environ;
+
+CORE_ADDR read_pc ();
+struct command_line *get_breakpoint_commands ();
+
+START_FILE
+\f
+int
+have_inferior_p ()
+{
+  return inferior_pid != 0;
+}
+
+static void 
+set_args_command (args)
+     char *args;
+{
+  free (inferior_args);
+  if (!args) args = "";
+  inferior_args = concat (" ", args, "");
+}
+  
+void
+tty_command (file)
+     char *file;
+{
+  if (file == 0)
+    error_no_arg ("terminal name for running target process");
+
+  inferior_io_terminal = savestring (file, strlen (file));
+}
+
+static void
+run_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  extern char **environ;
+  register int i;
+  char *exec_file;
+  char *allargs;
+
+  extern int sys_nerr;
+  extern char *sys_errlist[];
+  extern int errno;
+
+  dont_repeat ();
+
+  if (inferior_pid)
+    {
+      if (query ("The program being debugged has been started already.\n\
+Start it from the beginning? "))
+       kill_inferior ();
+      else
+       error ("Program already started.");
+    }
+
+  if (args)
+    set_args_command (args);
+
+  exec_file = (char *) get_exec_file ();
+  if (from_tty)
+    {
+      printf ("Starting program: %s%s\n",
+             exec_file, inferior_args);
+      fflush (stdout);
+    }
+
+  allargs = concat ("exec ", exec_file, inferior_args);
+  inferior_pid = create_inferior (allargs, environ_vector (inferior_environ));
+
+  clear_proceed_status ();
+
+  start_inferior ();
+}
+\f
+void
+cont_command (proc_count_exp, from_tty)
+     char *proc_count_exp;
+     int from_tty;
+{
+  ERROR_NO_INFERIOR;
+
+  clear_proceed_status ();
+
+  /* If have argument, set proceed count of breakpoint we stopped at.  */
+
+  if (stop_breakpoint && proc_count_exp)
+    {
+      set_ignore_count (stop_breakpoint,
+                       parse_and_eval_address (proc_count_exp) - 1,
+                       from_tty);
+      if (from_tty)
+       printf ("  ");
+    }
+
+  if (from_tty)
+    printf ("Continuing.\n");
+
+  proceed (-1, -1, 0);
+}
+\f
+/* Step until outside of current statement.  */
+static void step_1 ();
+
+static void
+step_command (count_string)
+{
+  step_1 (0, 0, count_string);
+}
+
+/* Likewise, but skip over subroutine calls as if single instructions.  */
+
+static void
+next_command (count_string)
+{
+  step_1 (1, 0, count_string);
+}
+
+/* Likewise, but step only one instruction.  */
+
+static void
+stepi_command (count_string)
+{
+  step_1 (0, 1, count_string);
+}
+
+static void
+nexti_command (count_string)
+{
+  step_1 (1, 1, count_string);
+}
+
+static void
+step_1 (skip_subroutines, single_inst, count_string)
+     int skip_subroutines;
+     int single_inst;
+     char *count_string;
+{
+  register int count = 1;
+
+  ERROR_NO_INFERIOR;
+  count = count_string ? parse_and_eval_address (count_string) : 1;
+
+  for (; count > 0; count--)
+    {
+      clear_proceed_status ();
+
+      step_frame = get_current_frame ();
+
+      if (! single_inst)
+       {
+         find_pc_line_pc_range (stop_pc, &step_range_start, &step_range_end);
+         if (step_range_end == 0)
+           {
+             terminal_ours ();
+             error ("Current function has no line number information.");
+           }
+       }
+      else
+       {
+         /* Say we are stepping, but stop after one insn whatever it does.
+            Don't step through subroutine calls even to undebuggable functions.  */
+         step_range_start = step_range_end = 1;
+         if (!skip_subroutines)
+           step_over_calls = 0;
+       }
+
+      if (skip_subroutines)
+       step_over_calls = 1;
+
+      step_multi = (count > 1);
+      proceed (-1, -1, 1);
+      if (! stop_step)
+       break;
+    }
+}
+\f
+/* Continue program at specified address.  */
+
+static void
+jump_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  register CORE_ADDR addr;
+  struct symtab_and_line sal;
+
+  ERROR_NO_INFERIOR;
+
+  if (!arg)
+    error_no_arg ("starting address");
+
+  sal = decode_line_spec (arg, 1);
+
+  if (sal.symtab == 0 && sal.pc == 0)
+    error ("No source file has been specified.");
+
+  if (sal.pc == 0)
+    sal.pc = find_line_pc (sal.symtab, sal.line);
+
+  {
+    struct symbol *fn = get_frame_function (get_current_frame ());
+    struct symbol *sfn = find_pc_function (sal.pc);
+    if (fn != 0 && sfn != fn
+       && ! query ("That is not in function %s.  Continue there? ",
+                   sal.line, SYMBOL_NAME (fn)))
+      error ("Not confirmed.");
+  }
+
+  if (sal.pc == 0)
+    error ("No line %d in file \"%s\".", sal.line, sal.symtab->filename);
+
+  addr = sal.pc;
+
+  clear_proceed_status ();
+
+  if (from_tty)
+    printf ("Continuing at 0x%x.\n", addr);
+
+  proceed (addr, 0, 0);
+}
+
+/* Continue program giving it specified signal.  */
+
+static void
+signal_command (signum_exp, from_tty)
+     char *signum_exp;
+     int from_tty;
+{
+  register int signum;
+
+  dont_repeat ();              /* Too dangerous.  */
+  ERROR_NO_INFERIOR;
+
+  if (!signum_exp)
+    error_no_arg ("signal number");
+
+  signum = parse_and_eval_address (signum_exp);
+
+  clear_proceed_status ();
+
+  if (from_tty)
+    printf ("Continuing with signal %d.\n", signum);
+
+  proceed (stop_pc, signum, 0);
+}
+
+/* Execute a "stack dummy", a piece of code stored in the stack
+   by the debugger to be executed in the inferior.
+
+   To call: first, do PUSH_DUMMY_FRAME.
+   Then push the contents of the dummy.  It should end with a breakpoint insn.
+   Then call here, passing address at which to start the dummy.
+
+   The contents of all registers are saved before the dummy frame is popped
+   and copied into the buffer BUFFER.
+
+   The dummy's frame is automatically popped whenever that break is hit.
+   If that is the first time the program stops, run_stack_dummy
+   returns to its caller with that frame already gone.
+   Otherwise, the caller never gets returned to.  */
+
+/* 4 => return instead of letting the stack dummy run.  */
+
+static int stack_dummy_testing = 0;
+
+void
+run_stack_dummy (addr, buffer)
+     CORE_ADDR addr;
+     REGISTER_TYPE *buffer;
+{
+  int saved_pc_changed = pc_changed;
+  int saved_stop_signal = stop_signal;
+  int saved_stop_pc = stop_pc;
+  int saved_stop_frame = stop_frame;
+  int saved_stop_breakpoint = stop_breakpoint;
+  int saved_stop_step = stop_step;
+  int saved_stop_stack_dummy = stop_stack_dummy;
+  FRAME saved_selected_frame;
+  int saved_selected_level;
+  struct command_line *saved_breakpoint_commands
+    = get_breakpoint_commands ();
+
+  record_selected_frame (&saved_selected_frame, &saved_selected_level);
+
+  /* Now proceed, having reached the desired place.  */
+  clear_proceed_status ();
+  if (stack_dummy_testing & 4)
+    {
+      POP_FRAME;
+      return;
+    }
+  proceed (addr, 0, 0);
+
+  if (!stop_stack_dummy)
+    error ("Cannot continue previously requested operation.");
+
+  set_breakpoint_commands (saved_breakpoint_commands);
+  select_frame (saved_selected_frame, saved_selected_level);
+  stop_signal = saved_stop_signal;
+  stop_pc = saved_stop_pc;
+  stop_frame = saved_stop_frame;
+  stop_breakpoint = saved_stop_breakpoint;
+  stop_step = saved_stop_step;
+  stop_stack_dummy = saved_stop_stack_dummy;
+  pc_changed = saved_pc_changed;
+
+  /* On return, the stack dummy has been popped already.  */
+
+  bcopy (stop_registers, buffer, sizeof stop_registers);
+}
+\f
+/* "finish": Set a temporary breakpoint at the place
+   the selected frame will return to, then continue.  */
+
+static void
+finish_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  struct symtab_and_line sal;
+  register FRAME frame;
+  struct frame_info fi;
+
+  register struct symbol *function;
+
+  if (!have_inferior_p ())
+    error ("The program is not being run.");
+  if (arg)
+    error ("The \"finish\" command does not take any arguments.");
+
+  frame = get_prev_frame (selected_frame);
+  if (frame == 0)
+    error ("\"finish\" not meaningful in the outermost frame.");
+
+  clear_proceed_status ();
+
+  fi = get_frame_info (frame);
+  sal = find_pc_line (fi.pc, 0);
+  sal.pc = fi.pc;
+  set_momentary_breakpoint (sal, frame);
+
+  /* Find the function we will return from.  */
+
+  fi = get_frame_info (fi.next_frame);
+  function = find_pc_function (fi.pc);
+
+  if (from_tty)
+    {
+      printf ("Run till exit from ");
+      print_selected_frame ();
+    }
+
+  proceed (-1, -1, 0);
+
+  if (stop_breakpoint == -3 && function != 0)
+    {
+      struct type *value_type;
+      register value val;
+
+      if (TYPE_CODE (SYMBOL_TYPE (function)) != TYPE_CODE_VOID)
+       value_type = SYMBOL_TYPE (function);
+      else
+       return;
+
+      val = value_being_returned (value_type, stop_registers);
+      printf ("Value returned is $%d = ", record_latest_value (val));
+      value_print (val, stdout);
+      putchar ('\n');
+    }
+}
+\f
+static void
+program_info ()
+{
+  if (inferior_pid == 0)
+    {
+      printf ("The program being debugged is not being run.\n");
+      return;
+    }
+
+  printf ("Program being debugged is in process %d, stopped at 0x%x.\n",
+         inferior_pid, stop_pc);
+  if (stop_step)
+    printf ("It stopped after being stepped.\n");
+  else if (stop_breakpoint)
+    printf ("It stopped at breakpoint %d.\n", stop_breakpoint);
+  else if (stop_signal)
+    printf ("It stopped with signal %d (%s).\n",
+           stop_signal, sys_siglist[stop_signal]);
+
+  printf ("\nType \"info stack\" or \"info reg\" for more information.\n");
+}
+\f
+static void
+environment_info (var)
+     char *var;
+{
+  if (var)
+    {
+      register char *val = get_in_environ (inferior_environ, var);
+      if (val)
+       printf ("%s = %s\n", var, val);
+      else
+       printf ("Environment variable \"%s\" not defined.\n", var);
+    }
+  else
+    {
+      register char **vector = environ_vector (inferior_environ);
+      while (*vector)
+       printf ("%s\n", *vector++);
+    }
+}
+
+static void
+set_environment_command (arg)
+     char *arg;
+{
+  register char *p, *val, *var;
+
+  if (arg == 0)
+    error_no_arg ("environment variable and value");
+
+  p = (char *) index (arg, '=');
+  val = (char *) index (arg, ' ');
+  if (p != 0 && val != 0)
+    p = arg + min (p - arg, val - arg);
+  else if (val != 0 && p == 0)
+    p = val;
+
+  if (p == 0)
+    error ("Space or \"=\" must separate variable name and its value");
+  if (p[1] == 0)
+    error_no_arg ("value for the variable");
+  if (p == arg)
+    error_no_arg ("environment variable to set");
+
+  val = p + 1;
+  while (*val == ' ' || *val == '\t') val++;
+  while (p != arg && (p[-1] == ' ' || p[-1] == '\t')) p--;
+
+  var = savestring (arg, p - arg);
+  set_in_environ (inferior_environ, var, val);
+  free (var);
+}
+
+static void
+unset_environment_command (var)
+     char *var;
+{
+  if (var == 0)
+    error_no_arg ("environment variable");
+
+  unset_in_environ (inferior_environ, var);
+}
+\f
+/* Read an integer from debugged memory, given address and number of bytes.  */
+
+read_memory_integer (memaddr, len)
+     CORE_ADDR memaddr;
+     int len;
+{
+  char cbuf;
+  short sbuf;
+  int ibuf;
+  long lbuf;
+
+  if (len == sizeof (char))
+    {
+      read_memory (memaddr, &cbuf, len);
+      return cbuf;
+    }
+  if (len == sizeof (short))
+    {
+      read_memory (memaddr, &sbuf, len);
+      return sbuf;
+    }
+  if (len == sizeof (int))
+    {
+      read_memory (memaddr, &ibuf, len);
+      return ibuf;
+    }
+  if (len == sizeof (lbuf))
+    {
+      read_memory (memaddr, &lbuf, len);
+      return lbuf;
+    }
+  error ("Cannot handle integers of %d bytes.", len);
+}
+\f
+CORE_ADDR
+read_pc ()
+{
+  return (CORE_ADDR) read_register (PC_REGNUM);
+}
+
+write_pc (val)
+     CORE_ADDR val;
+{
+  write_register (PC_REGNUM, (long) val);
+}
+
+char *reg_names[] = REGISTER_NAMES;
+
+static void
+registers_info (addr_exp)
+     char *addr_exp;
+{
+  register int i;
+  int regnum;
+
+  if (addr_exp)
+    {
+      if (*addr_exp >= '0' && *addr_exp <= '9')
+       regnum = atoi (addr_exp);
+      else
+       {
+         register char *p = addr_exp;
+         if (p[0] == '$')
+           p++;
+         for (regnum = 0; regnum < NUM_REGS; regnum++)
+           if (!strcmp (p, reg_names[regnum]))
+             break;
+         if (regnum == NUM_REGS)
+           error ("%s: invalid register name.", addr_exp);
+       }
+    }
+  else
+    printf ("Reg\tContents\n\n");
+
+  for (i = 0; i < NUM_REGS; i++)
+    {
+      unsigned char raw_buffer[MAX_REGISTER_RAW_SIZE];
+      unsigned char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+      REGISTER_TYPE val;
+
+      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);
+         read_line ();
+       }
+
+      /* 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]);
+
+      /* 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);
+      /* 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");
+         for (j = 0; j < REGISTER_VIRTUAL_SIZE (i); j++)
+           printf ("%02x", virtual_buffer[j]);
+       }
+      /* Else print as integer in hex and in decimal.  */
+      else
+       {
+         long val;
+
+         bcopy (virtual_buffer, &val, sizeof (long));
+         if (val == 0)
+           printf ("0");
+         else
+           printf ("0x%08x  %d", val, val);
+       }
+
+      /* If register has different raw and virtual formats,
+        print the raw format in hex now.  */
+
+      if (REGISTER_CONVERTIBLE (i))
+       {
+         register int j;
+
+         printf ("  (raw 0x");
+         for (j = 0; j < REGISTER_RAW_SIZE (i); j++)
+           printf ("%02x", raw_buffer[j]);
+         printf (")");
+       }
+      printf ("\n");
+    }
+
+  printf ("Contents are relative to selected stack frame.\n");
+}
+\f
+#ifdef ATTACH_DETACH
+/*
+ * TODO:
+ * Should save/restore the tty state since it might be that the
+ * program to be debugged was started on this tty and it wants
+ * 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.
+ */
+
+/*
+ * attach_command --
+ * takes a program started up outside of gdb and ``attaches'' to it.
+ * This stops it cold in it's tracks and allows us to start tracing
+ * it.  For this to work, we must be able to send the process a
+ * signal and we must have the same effective uid as the program.
+ */
+static void
+attach_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  char *exec_file;
+  int pid;
+
+  dont_repeat();
+
+  if (!args)
+    error_no_arg ("process-id to attach");
+  else
+    pid = atoi (args);
+
+  if (inferior_pid)
+    {
+      if (query ("A program is being debugged already.  Kill it? "))
+       kill_inferior ();
+      else
+       error ("Inferior not killed.");
+    }
+
+  exec_file = (char *) get_exec_file ();
+
+  if (from_tty)
+    {
+      printf ("Attaching program: %s pid %d\n",
+             exec_file, pid);
+      fflush (stdout);
+    }
+
+  attach_program (pid);
+}
+
+/*
+ * detach_command --
+ * takes a program previously attached to and detaches it.
+ * The program resumes execution and will no longer stop
+ * on signals, etc.  We better not have left any breakpoints
+ * in the program or it'll die when it hits one.  For this
+ * to work, it may be necessary for the process to have been
+ * previously attached.  It *might* work if the program was
+ * started via the normal ptrace (PTRACE_TRACEME).
+ */
+
+static void
+detach_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  char *exec_file = (char *)get_exec_file ();
+  int signal = 0;
+
+  if (!inferior_pid)
+    error ("Not currently tracing a program\n");
+  if (from_tty)
+    {
+      printf ("Detaching program: %s pid %d\n",
+             exec_file, inferior_pid);
+      fflush (stdout);
+    }
+  if (args)
+    signal = atoi (args);
+
+  detach (signal);
+  inferior_pid = 0;
+}
+#endif /* ATTACH_DETACH */
+\f
+static
+initialize ()
+{
+  add_com ("tty", class_run, tty_command,
+          "Set terminal for future runs of program being debugged.");
+
+  add_com ("set-args", class_run, set_args_command,
+          "Specify arguments to give program being debugged when it is started.\n\
+Follow this command with any number of args, to be passed to the program.");
+
+  add_info ("environment", environment_info,
+           "The environment to give the program, or one variable's value.\n\
+With an argument VAR, prints the value of environment variable VAR to\n\
+give the program being debugged.  With no arguments, prints the entire\n\
+environment to be given to the program.");
+
+  add_com ("unset-environment", class_run, unset_environment_command,
+          "Cancel environment variable VAR for the program.\n\
+This does not affect the program until the next \"run\" command.");
+  add_com ("set-environment", class_run, set_environment_command,
+          "Set environment variable value to give the program.\n\
+Arguments are VAR VALUE where VAR is variable name and VALUE is value.\n\
+VALUES of environment variables are uninterpreted strings.\n\
+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\
+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.");
+  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.");
+
+  add_com ("stepi", class_run, stepi_command,
+          "Step one instruction exactly.\n\
+Argument N means do this N times (or till program stops for another reason).");
+  add_com_alias ("si", "stepi", class_alias, 0);
+
+  add_com ("nexti", class_run, nexti_command,
+          "Step one instruction, but proceed through subroutine calls.\n\
+Argument N means do this N times (or till program stops for another reason).");
+  add_com_alias ("ni", "nexti", class_alias, 0);
+
+  add_com ("finish", class_run, finish_command,
+          "Execute until selected stack frame returns.\n\
+Upon return, the value returned is printed and put in the value history.");
+
+  add_com ("next", class_run, next_command,
+          "Step program, proceeding through subroutine calls.\n\
+Like the \"step\" command as long as subroutine calls do not happen;\n\
+when they do, the call is treated as one instruction.\n\
+Argument N means do this N times (or till program stops for another reason).");
+  add_com_alias ("n", "next", class_run, 1);
+
+  add_com ("step", class_run, step_command,
+          "Step program until it reaches a different source line.\n\
+Argument N means do this N times (or till program stops for another reason).");
+  add_com_alias ("s", "step", class_run, 1);
+
+  add_com ("jump", class_run, jump_command,
+          "Continue program being debugged at specified line or address.\n\
+Give as argument either LINENUM or *ADDR, where ADDR is an expression\n\
+for an address to start at.");
+
+  add_com ("cont", class_run, cont_command,
+          "Continue program being debugged, after signal or breakpoint.\n\
+If proceeding from breakpoint, a number N may be used as an argument:\n\
+then the same breakpoint won't break until the Nth time it is reached.");
+  add_com_alias ("c", "cont", class_run, 1);
+
+  add_com ("run", class_run, run_command,
+          "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\
+To cancel previous arguments and run with no arguments,\n\
+use \"set-args\" without arguments.");
+  add_com_alias ("r", "run", class_run, 1);
+
+  add_info ("registers", registers_info,
+           "List of registers and their contents, for selected stack frame.\n\
+Register name as argument means describe only that register.");
+
+  add_info ("program", program_info,
+           "Execution status of the program.");
+
+  inferior_args = savestring (" ", 1); /* By default, no args.  */
+  inferior_environ = make_environ ();
+  init_environ (inferior_environ);
+}
+
+END_FILE
diff --git a/gdb/inferior.h b/gdb/inferior.h
new file mode 100644 (file)
index 0000000..21c937c
--- /dev/null
@@ -0,0 +1,85 @@
+/* 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.
+
+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 name for default use for standard in/out in the inferior.  */
+
+extern char *inferior_io_terminal;
+
+/* Pid of our debugged inferior, or 0 if no inferior now.  */
+
+extern int inferior_pid;
+
+/* Last signal that the inferior received (why it stopped).  */
+
+extern int stop_signal;
+
+/* Address at which inferior stopped.  */
+
+extern CORE_ADDR stop_pc;
+
+/* Stack frame when program stopped.  */
+
+extern FRAME stop_frame;
+
+/* Number of breakpoint it stopped at, or 0 if none.  */
+
+extern int stop_breakpoint;
+
+/* Nonzero if stopped due to a step command.  */
+
+extern int stop_step;
+
+/* Nonzero if stopped due to completion of a stack dummy routine.  */
+
+extern int stop_stack_dummy;
+
+/* Range to single step within.
+   If this is nonzero, respond to a single-step signal
+   by continuing to step if the pc is in this range.  */
+
+extern CORE_ADDR step_range_start; /* Inclusive */
+extern CORE_ADDR step_range_end; /* Exclusive */
+
+/* Stack frame address as of when stepping command was issued.
+   This is how we know when we step into a subroutine call,
+   and how to set the frame for the breakpoint used to step out.  */
+
+extern CORE_ADDR step_frame;
+
+/* 1 means step over all subroutine calls.
+   -1 means step over calls to undebuggable functions.  */
+
+extern int step_over_calls;
+
+/* If stepping, nonzero means step count is > 1
+   so don't print frame next time inferior stops
+   if it stops due to stepping.  */
+
+extern int step_multi;
+
+/* Save register contents here when about to pop a stack dummy frame.  */
+
+extern char stop_registers[REGISTER_BYTES];
+
+/* Nonzero if pc has been changed by the debugger
+   since the inferior stopped.  */
+
+extern int pc_changed;
diff --git a/gdb/inflow.c b/gdb/inflow.c
new file mode 100644 (file)
index 0000000..7bed594
--- /dev/null
@@ -0,0 +1,661 @@
+/* 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 "initialize.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include <fcntl.h>
+
+#ifdef mac_aux
+#include <sys/seg.h>
+#include <sys/mmu.h>
+#include <sys/signal.h>
+#include <sys/time.h>
+#include <sys/user.h>
+#else
+#include <sys/user.h>
+#endif /* mac_aux */
+
+
+#ifdef UMAX_PTRACE
+#include <a.out.h>
+#endif
+
+#ifdef NEW_SUN_PTRACE
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+#endif
+
+#ifdef SYSV_TTYS
+#include <termio.h>
+#endif
+
+extern int errno;
+
+/* Nonzero if we are debugging an attached outside process
+   rather than an inferior.  */
+
+static int attach_flag;
+
+#define        UPAGE_MASK      0x00003FFF
+
+START_FILE
+\f
+/* Record terminal status separately for debugger and inferior.  */
+
+#ifdef SYSV_TTYS
+static struct termio ti_inferior;
+#else
+static struct sgttyb sg_inferior;
+static struct tchars tc_inferior;
+static struct ltchars ltc_inferior;
+static int lmode_inferior;
+#endif
+static int tflags_inferior;
+static int pgrp_inferior;
+
+#ifdef SYSV_TTYS
+static struct termio ti_ours;
+#else
+static struct sgttyb sg_ours;
+static struct tchars tc_ours;
+static struct ltchars ltc_ours;
+static int lmode_ours;
+#endif
+static int tflags_ours;
+static int pgrp_ours;
+
+/* 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 ()
+{
+
+#ifdef SYSV_TTYS
+  ti_inferior = ti_ours;
+#else
+  sg_inferior = sg_ours;
+  tc_inferior = tc_ours;
+  ltc_inferior = ltc_ours;
+  lmode_inferior = lmode_ours;
+#endif
+  tflags_inferior = tflags_ours;
+  pgrp_inferior = inferior_pid;
+
+  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 (terminal_is_ours)   /*  && inferior_thisrun_terminal == 0) */
+    {
+      fcntl (0, F_SETFL, tflags_inferior);
+      fcntl (0, F_SETFL, tflags_inferior);
+#ifdef SYSV_TTYS
+      ioctl (0, TCSETA, &ti_inferior);
+#else
+      ioctl (0, TIOCSETN, &sg_inferior);
+      ioctl (0, TIOCSETC, &tc_inferior);
+      ioctl (0, TIOCSLTC, &ltc_inferior);
+      ioctl (0, TIOCLSET, &lmode_inferior);
+#endif
+      ioctl (0, TIOCSPGRP, &pgrp_inferior);
+    }
+  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 ()
+{
+  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 ()
+{
+  terminal_ours_1 (0);
+}
+
+static void
+terminal_ours_1 (output_only)
+     int output_only;
+{
+  /* Ignore this signal since it will happen when we try to set the pgrp.  */
+  int (*osigttou) ();
+
+  if (!terminal_is_ours)  /*   && inferior_thisrun_terminal == 0)  */
+    {
+      terminal_is_ours = 1;
+
+      osigttou = signal (SIGTTOU, SIG_IGN);
+
+      ioctl (0, TIOCGPGRP, &pgrp_inferior);
+      ioctl (0, TIOCSPGRP, &pgrp_ours);
+
+      signal (SIGTTOU, osigttou);
+
+      tflags_inferior = fcntl (0, F_GETFL, 0);
+#ifdef SYSV_TTYS
+      ioctl (0, TCGETA, &ti_inferior);
+#else
+      ioctl (0, TIOCGETP, &sg_inferior);
+      ioctl (0, TIOCGETC, &tc_inferior);
+      ioctl (0, TIOCGLTC, &ltc_inferior);
+      ioctl (0, TIOCLGET, &lmode_inferior);
+#endif
+    }
+
+  fcntl (0, F_SETFL, tflags_ours);
+  fcntl (0, F_SETFL, tflags_ours);
+
+
+#ifdef SYSV_TTYS
+  ti_ours.c_lflag |= ICANON | ISIG;
+  if (output_only)
+    ti_ours.c_lflag &= ~((ICANON|ISIG)&ti_inferior.c_lflag);
+  ioctl (0, TCSETA, &ti_ours);
+  ti_ours.c_lflag |= ICANON | ISIG;
+#else
+  sg_ours.sg_flags &= ~RAW & ~CBREAK;
+  if (output_only)
+    sg_ours.sg_flags |= (RAW | CBREAK) & sg_inferior.sg_flags;
+  ioctl (0, TIOCSETN, &sg_ours);
+  ioctl (0, TIOCSETC, &tc_ours);
+  ioctl (0, TIOCSLTC, &ltc_ours);
+  ioctl (0, TIOCLSET, &lmode_ours);
+  sg_ours.sg_flags &= ~RAW & ~CBREAK;
+#endif
+}
+
+static void
+term_status_command ()
+{
+  register int i;
+  printf ("Inferior's terminal status (currently saved by GDB):\n");
+#ifdef SYSV_TTYS
+  printf ("fcntl flags = 0x%x, owner pid = %d.\n",
+         tflags_inferior, pgrp_inferior);
+  printf ("iflag = 0x%04x, oflag = 0x%04x, cflag = 0x%04x, lflag = 0x%04x\n",
+         ti_inferior.c_iflag, ti_inferior.c_oflag,
+         ti_inferior.c_cflag, ti_inferior.c_lflag);
+  printf ("line discipline = %d\n", ti_inferior.c_line);
+  printf ("control chars: ");
+  for (i = 0; i < NCC; i++)
+    printf ("0x%x ", ti_inferior.c_cc[i]);
+  printf ("\n");
+#else
+  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);
+  printf ("tchars: ");
+  for (i = 0; i < sizeof (struct tchars); i++)
+    printf ("0x%x ", ((char *)&tc_inferior)[i]);
+  printf ("\n");
+  printf ("ltchars: ");
+  for (i = 0; i < sizeof (struct ltchars); i++)
+    printf ("0x%x ", ((char *)&ltc_inferior)[i]);
+  printf ("\n");
+#endif
+}
+\f
+static void
+new_tty (ttyname)
+     char *ttyname;
+{
+  register int tty;
+  register int fd;
+
+#if 0
+  /* I think it is better not to do this.  Then C-z on the GDB terminal
+     will still stop the program, while C-z on the data terminal
+     will be input.  */
+
+  /* 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);
+}
+\f
+/* 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 ());
+
+      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);  */
+
+      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.  */
+
+static void
+kill_command ()
+{
+  if (inferior_pid == 0)
+    error ("The program is not being run.");
+  if (!query ("Kill the inferior process? "))
+    error ("Not confirmed.");
+  kill_inferior ();
+}
+
+kill_inferior ()
+{
+  if (inferior_pid == 0)
+    return;
+  ptrace (8, inferior_pid, 0, 0);
+  wait (0);
+  inferior_died ();
+}
+
+inferior_died ()
+{
+  inferior_pid = 0;
+  attach_flag = 0;
+  mark_breakpoints_out ();
+  reopen_exec_file ();
+  if (have_core_file_p ())
+    set_current_frame (read_register (FP_REGNUM));
+}
+
+/* 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;
+  ptrace (step ? 9 : 7, inferior_pid, 1, signal);
+  if (errno)
+    perror_with_name ("ptrace");
+}
+\f
+#ifdef NEW_SUN_PTRACE
+
+/* 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
+\f
+#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);
+  ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers);
+
+  bcopy (&inferior_registers, registers, 16 * 4);
+  bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
+        sizeof inferior_fp_registers.fps_regs);
+  *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+  *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+  bcopy (&inferior_fp_registers.fps_control,
+        &registers[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 (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+        sizeof inferior_fp_registers.fps_regs);
+  inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
+  inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
+  bcopy (&registers[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);
+  ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
+}
+
+#else
+
+void
+fetch_inferior_registers ()
+{
+  register int regno;
+  register unsigned int regaddr;
+  char buf[MAX_REGISTER_RAW_SIZE];
+  register int i;
+
+#ifdef UMAX_PTRACE
+  unsigned int offset = 0;
+#else
+  struct user u;
+  unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
+  offset = ptrace (3, inferior_pid, offset, 0) & UPAGE_MASK;
+#endif
+
+  for (regno = 0; regno < NUM_REGS; regno++)
+    {
+      regaddr = register_addr (regno, offset);
+      for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+       {
+         *(int *) &buf[i] = ptrace (3, inferior_pid, regaddr, 0);
+         regaddr += sizeof (int);
+       }
+      supply_register (regno, buf);
+    }
+}
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+
+store_inferior_registers (regno)
+     int regno;
+{
+  register unsigned int regaddr;
+  char buf[80];
+
+#ifdef UMAX_PTRACE
+  unsigned int offset = 0;
+#else
+  struct user u;
+  unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
+  offset = ptrace (3, inferior_pid, offset, 0) & UPAGE_MASK;
+#endif
+
+  if (regno >= 0)
+    {
+      regaddr = register_addr (regno, offset);
+      errno = 0;
+      ptrace (6, inferior_pid, regaddr, read_register (regno));
+      if (errno != 0)
+       {
+         sprintf (buf, "writing register number %d", regno);
+         perror_with_name (buf);
+       }
+    }
+  else for (regno = 0; regno < NUM_REGS; regno++)
+    {
+      regaddr = register_addr (regno, offset);
+      errno = 0;
+      ptrace (6, inferior_pid, regaddr, read_register (regno));
+      if (errno != 0)
+       {
+         sprintf (buf, "writing register number %d", regno);
+         perror_with_name (buf);
+       }
+    }
+}
+
+#endif /* not NEW_SUN_PTRACE */
+\f
+/* 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 memnory 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;
+}
+\f
+static void
+try_writing_regs_command ()
+{
+  register int i;
+  register int value;
+  extern int errno;
+
+  if (inferior_pid == 0)
+    error ("The program is not being run.");
+
+  for (i = 0; ; i += 2)
+    {
+      QUIT;
+      errno = 0;
+      value = ptrace (3, inferior_pid, i, 0);
+      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);
+    }
+}
+\f
+static
+initialize ()
+{
+  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;
+
+#ifdef SYSV_TTYS
+  ioctl (0, TCGETA, &ti_ours);
+#else
+  ioctl (0, TIOCGETP, &sg_ours);
+  ioctl (0, TIOCGETC, &tc_ours);
+  ioctl (0, TIOCGLTC, &ltc_ours);
+  ioctl (0, TIOCLGET, &lmode_ours);
+#endif
+  fcntl (0, F_GETFL, tflags_ours);
+  ioctl (0, TIOCGPGRP, &pgrp_ours);
+
+  terminal_is_ours = 1;
+}
+
+END_FILE
diff --git a/gdb/infrun.c b/gdb/infrun.c
new file mode 100644 (file)
index 0000000..e980cec
--- /dev/null
@@ -0,0 +1,943 @@
+/* Start and stop the inferior process, 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 "defs.h"
+#include "initialize.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+
+#include <stdio.h>
+#include <signal.h>
+#include <a.out.h>
+
+#ifdef UMAX_PTRACE
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#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 means expecting a trace trap
+   and should stop the inferior and return silently when it happens.  */
+
+static int stop_after_trap;
+
+/* Nonzero means expecting a trace trap due to attaching to a process.  */
+
+static int stop_after_attach;
+
+/* Nonzero if pc has been changed by the debugger
+   since the inferior stopped.  */
+
+int pc_changed;
+
+/* 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;
+
+static void insert_step_breakpoint ();
+static void remove_step_breakpoint ();
+static void wait_for_inferior ();
+static void normal_stop ();
+
+START_FILE
+\f
+/* 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 = 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;
+         /* We will get a trace trap after one instruction.
+            Continue it automatically and insert breakpoints then.  */
+         trap_expected = 1;
+       }
+    }
+  else
+    write_register (PC_REGNUM, addr);
+
+  if (!oneproc)
+    {
+      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.  */
+
+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.  */
+
+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.  */
+  trap_expected = 2;
+  running_in_shell = 0;                /* Set to 1 at first SIGTRAP, 0 at second.  */
+  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 ();
+
+  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 */
+\f
+/* 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;
+  int stop_step_resume_break;
+  int newmisc;
+  int newfun_pc;
+  struct symbol *newfun;
+  struct symtab_and_line sal;
+  int prev_pc;
+
+  while (1)
+    {
+      prev_pc = read_pc ();
+      pid = wait (&w);
+      pc_changed = 0;
+      fetch_inferior_registers ();
+      stop_pc = read_pc ();
+      set_current_frame (read_register (FP_REGNUM));
+      stop_frame = get_current_frame ();
+      stop_sp = read_register (SP_REGNUM);
+      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;
+      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.  */
+
+      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);
+
+         /* 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
+             || (breakpoints_inserted &&
+                 (stop_signal == SIGILL
+                  || stop_signal == SIGEMT))
+             || 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 */
+                 {
+                   select_frame (stop_frame, 0); /* For condition exprs. */
+                   stop_breakpoint = breakpoint_stop_status (stop_pc, stop_frame);
+                   /* 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);
+                       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
+                     || (stop_sp INNER_THAN stop_pc && stop_pc INNER_THAN stop_frame)
+                     || (step_range_end && !step_resume_break_address));
+             else
+               {
+                 random_signal
+                   = !(stop_breakpoint || stop_step_resume_break);
+                 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;
+
+             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)
+               {
+                 /* 0x1000000 is set in stop_breakpoint as returned by
+                    breakpoint_status_p to indicate a silent breakpoint.  */
+                 if (stop_breakpoint > 0 && stop_breakpoint & 0x1000000)
+                   {
+                     stop_breakpoint &= ~0x1000000;
+                     stop_print_frame = 0;
+                   }
+                 break;
+               }
+             /* But if we have hit the step-resumption breakpoint,
+                remove it.  It has done its job getting us here.  */
+             if (stop_step_resume_break
+                 && (step_frame == 0 || stop_frame == step_frame))
+               {
+                 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.  */
+         if (stop_sp INNER_THAN stop_pc && stop_pc INNER_THAN stop_frame)
+           {
+             stop_print_frame = 0;
+             stop_stack_dummy = 1;
+             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)
+           {
+             /* 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)
+           {
+             newfun = find_pc_function (stop_pc);
+             if (newfun)
+               {
+                 newfun_pc = BLOCK_START (SYMBOL_BLOCK_VALUE (newfun))
+                   + FUNCTION_START_OFFSET;
+               }
+             else
+               {
+                 newmisc = find_pc_misc_function (stop_pc);
+                 if (newmisc >= 0)
+                   newfun_pc = misc_function_vector[newmisc].address
+                     + FUNCTION_START_OFFSET;
+                 else newfun_pc = 0;
+               }
+             if (stop_pc == newfun_pc
+                 && (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 (stop_frame);
+                 step_resume_break_duplicate
+                   = breakpoint_here_p (step_resume_break_address);
+                 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 (stop_pc == newfun_pc && step_over_calls)
+               {
+                 SKIP_PROLOGUE (newfun_pc);
+                 sal = find_pc_line (newfun_pc, 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.  */
+                 if (sal.end && sal.pc != newfun_pc)
+                   step_resume_break_address = sal.end;
+                 else
+                   step_resume_break_address = newfun_pc;
+
+                 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 = 0;
+                 /* And make sure stepping stops right away then.  */
+                 step_range_end = step_range_start;
+               }
+             /* No subroutince call; stop now.  */
+             else
+               {
+                 stop_step = 1;
+                 break;
+               }
+           }
+       }
+
+      /* 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);
+       }
+    }
+}
+\f
+/* 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.  */
+
+static void
+normal_stop ()
+{
+  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 (step_multi && stop_step)
+    return;
+
+  terminal_ours ();
+
+  if (running_in_shell)
+    {
+      if (stop_signal == SIGSEGV)
+       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 (stop_frame, 0);
+
+      if (stop_print_frame)
+       {
+         if (stop_breakpoint > 0)
+           printf ("\nBpt %d, ", stop_breakpoint);
+         print_sel_frame (stop_step
+                          && step_frame == stop_frame
+                          && 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;
+      select_frame (read_register (FP_REGNUM), 0);
+    }
+}
+\f
+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);
+}
+\f
+/* 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;
+  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 == 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);
+         read_line ();
+       }
+      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");
+}
+\f
+static
+initialize ()
+{
+  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 */
+}
+
+END_FILE
diff --git a/gdb/initialize.h b/gdb/initialize.h
new file mode 100644 (file)
index 0000000..e727c80
--- /dev/null
@@ -0,0 +1,126 @@
+/* Macros to enable automatic execution of an initialization function
+   in each object file without having to include a list of all object files
+   anywhere in the source code.  This goes with firstfile.c and lastfile.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 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.
+
+  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) cause each such copy to be accompanied by the
+    corresponding machine-readable source code, which must
+    be distributed under the terms of Paragraphs 1 and 2 above; or,
+
+    b) cause each such copy to be accompanied by a
+    written offer, with no time limit, to give any third party
+    free (except for a nominal shipping charge) a machine readable
+    copy of the corresponding source code, to be distributed
+    under the terms of Paragraphs 1 and 2 above; or,
+
+    c) in the case of a recipient of this program in compiled, executable
+    or object code form (without the corresponding source code) you
+    shall cause copies you distribute to be accompanied by a copy
+    of the written offer of source code which you received along
+    with the copy you received.
+
+  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!  */
+
+
+/* Here a machine-specific header file must be included to define
+   the macro FILEADDR_ROUND which we use to round up from the address
+   of the end of one object file's text to the start of the next
+   object file's text.  */
+
+#include "m-suninit.h"
+
+/* This is used to make a file's initialization function.
+   It calls another function named `initialize', which must
+   appear later in the file.  */
+
+#define START_FILE   \
+  static initialize (), initialize_next_file ();   \
+  static initialize_1 (offset)  \
+  { initialize (); initialize_next_file (offset); }
+
+/* The argument OFFSET is the size of this function.
+   By adding it to the address of this function,
+   we find the next function, which is the next file's
+   initialization function.  */
+
+#define END_FILE    \
+  static initialize_next_file (offset)   \
+     int offset;   \
+  { long addr = FILEADDR_ROUND ((int) initialize_next_file + offset);   \
+    (*(void (*) ()) addr) (offset);  }
diff --git a/gdb/kdb-start.c b/gdb/kdb-start.c
new file mode 100644 (file)
index 0000000..bdbc272
--- /dev/null
@@ -0,0 +1,21 @@
+#include "defs.h"
+#include "param.h"
+
+static char *args[] = {"kdb", "kdb-symbols", 0};
+
+static char *environment[] = {0};
+
+char **environ;
+
+start ()
+{
+#ifdef NAMES_HAVE_UNDERSCORE
+  INIT_STACK (_kdb_stack_beg, _kdb_stack_end);
+#else /* not NAMES_HAVE_UNDERSCORE */
+  INIT_STACK (kdb_stack_beg, kdb_stack_end);
+#endif /* not NAMES_HAVE_UNDERSCORE */
+
+  environ = environment;
+
+  main (2, args, environment);
+}
diff --git a/gdb/lastfile.c b/gdb/lastfile.c
new file mode 100644 (file)
index 0000000..2ac8cb7
--- /dev/null
@@ -0,0 +1,6 @@
+/* This ends the chain of files for the purpose of initialization,
+   because it does not attempt to find the start of the following file.  */
+
+initialize_last_file ()
+{
+}
diff --git a/gdb/m-isi-ov.h b/gdb/m-isi-ov.h
new file mode 100644 (file)
index 0000000..46c1816
--- /dev/null
@@ -0,0 +1,524 @@
+/*
+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. "<function + offset>", 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!
+*/
+
+
+/* Identify this machine */
+#ifndef ISI68K
+#define ISI68K
+#endif
+
+/* 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.  */
+
+#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 */                   \
+  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 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 0x10800000
+
+/* Address of end of stack space.  */
+
+#define STACK_END_ADDR 0x10000000
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {0x4e, 0x4f}
+
+/* Data segment starts at etext rounded up to DATAROUND in {N,Z}MAGIC files */
+
+#define DATAROUND      0x20000
+#define N_DATADDR(hdr) (hdr.a_magic != OMAGIC ? \
+       (hdr.a_text + DATAROUND) & ~(DATAROUND-1) : hdr.a_text)
+
+/* Text segment starts at sizeof (struct exec) in {N,Z}MAGIC files */
+
+#define N_TXTADDR(hdr) (hdr.a_magic != OMAGIC ? sizeof (struct exec) : 0)
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.  
+   On the ISI, the kernel resets the pc to the trap instr */
+
+#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) == 0x4e76)
+
+/* Return 1 if P points to an invalid floating point value.  */
+
+#define INVALID_FLOAT(p, len) 0   /* Just a first guess; not checked */
+
+/* Say how long 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 */
+
+#define REGISTER_U_ADDR(addr, blockend, regno)         \
+{      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;                        \
+}
+
+/* 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.  */
+
+#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)
+
+/* 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))
+\f
+/* 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 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, 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 + 4, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) (fi.frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) (fi.frame)
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.  */
+
+#define FRAME_NUM_ARGS(val, 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 */ \
+    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; }
+
+/* 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;                                               \
+  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;         \
+}
+\f
+/* 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 registers.  */
+
+#define POP_FRAME  \
+{ register CORE_ADDR fp = read_register (FP_REGNUM);                   \
+  register int regnum;                                                 \
+  struct frame_saved_regs fsr;                                         \
+  struct frame_info fi;                                                        \
+  char raw_buffer[12];                                                 \
+  fi = get_frame_info (fp);                                            \
+  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);                                  \
+}
+
+/* This sequence of words is the instructions
+     fmovem #<f0-f7>,-(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
+     bpt
+     nop
+Note this is 24 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, fun, nargs)     \
+{ *(int *)((char *) dummyname + 20) = nargs * 4;  \
+  *(int *)((char *) dummyname + 14) = fun; }
+\f
+/* 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 ("movl $ end, sp");      \
+  asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR        \
+  asm ("movel fp, -(sp)");
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR  \
+  asm ("movl (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 ("clrw -(sp)");        \
+  asm ("pea 10(sp)");        \
+  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,28(sp)");     \
+  asm ("movem (sp),$ 0xffff"); \
+  asm ("rte"); }
diff --git a/gdb/m-mac-aux.h b/gdb/m-mac-aux.h
new file mode 100644 (file)
index 0000000..2f1f84d
--- /dev/null
@@ -0,0 +1,485 @@
+/* Parameters for execution on Macintosh under A/UX, 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 mac_aux
+#define mac_aux
+#endif
+
+/* Get rid of any system-imposed stack limit if possible.  */
+
+#undef 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.  */
+
+#undef NAMES_HAVE_UNDERSCORE
+
+/* COFF format object files */
+
+#define COFF_FORMAT
+
+/* System eVil ttys */
+
+#define SYSV_TTYS
+
+/* Debugger information will not be in DBX format.  */
+
+#undef 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.  */
+
+#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.  */
+
+#define BREAKPOINT {0x4e, 0x4f}
+
+/* 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 2
+
+/* Nonzero if instruction at PC is a return instruction.  */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e76)
+
+/* Return 1 if P points to an invalid floating point value.  */
+
+#define INVALID_FLOAT(p, len) 0   /* Just a first guess; not checked */
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 31
+
+/* 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", "fpcode", "fpflags" }
+
+/* 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 */
+
+/* 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.  */
+
+#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)
+
+/* 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))
+
+/* Enable use of alternate code to read and write registers.  */
+
+#undef NEW_SUN_PTRACE
+
+/* Enable use of alternate code for Sun's format of core dump file.  */
+
+#undef NEW_SUN_CORE
+
+/* Do implement the attach and detach commands.  */
+
+#undef 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
+\f
+/* 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 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, 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 + 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.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 */ \
+    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;         \
+}
+\f
+/* 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 CORE_ADDR fp = read_register (FP_REGNUM);            \
+  register int regnum;                                          \
+  struct frame_saved_regs fsr;                                  \
+  struct frame_info fi;                                                 \
+  char raw_buffer[12];                                          \
+  fi = get_frame_info (fp);                                     \
+  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);                           \
+  set_current_frame (read_register (FP_REGNUM)); }
+
+/* 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
+     bpt
+     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, fun, nargs)     \
+{ *(int *)((char *) dummyname + 20) = nargs * 4;  \
+  *(int *)((char *) dummyname + 14) = fun; }
+\f
+/* 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"); }
diff --git a/gdb/m-mac-auxinit.h b/gdb/m-mac-auxinit.h
new file mode 100644 (file)
index 0000000..bd420ef
--- /dev/null
@@ -0,0 +1,5 @@
+
+/* This is how the size of an individual .o file's text segment
+   is rounded on a mac under a/ux.  */
+
+#define FILEADDR_ROUND(addr) (addr)
diff --git a/gdb/m-merlin.h b/gdb/m-merlin.h
new file mode 100644 (file)
index 0000000..7f87979
--- /dev/null
@@ -0,0 +1,437 @@
+/* Definitions to make GDB run on a merlin under utek 2.1
+   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 ns16000
+#define ns16000
+#endif
+
+# include      <machine/reg.h>
+
+/* 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.  */
+
+#define SKIP_PROLOGUE(pc)                              \
+{ register int op = read_memory_integer (pc, 1);       \
+  if (op == 0x82)                                      \
+    { op = read_memory_integer (pc+2,1);               \
+      if ((op & 0x80) == 0) pc += 3;                   \
+      else if ((op & 0xc0) == 0x80) pc += 4;           \
+      else pc += 6;                                    \
+    }}
+
+/* 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 (0xfef000)
+
+/* Address of end of stack space.  */
+
+#define STACK_END_ADDR (0x800000)
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {0xf2}
+
+/* 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, 1) == 0x12)
+
+/* Return 1 if P points to an invalid floating point value.  */
+
+#define INVALID_FLOAT(p, len) 0
+
+/* Define this to say that the "svc" insn is followed by
+   codes in memory saying which kind of system call it is.  */
+
+#define NS32K_SVC_IMMED_OPERANDS
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS               25
+
+#define NUM_GENERAL_REGS       8
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",        \
+                       "pc", "sp", "fp", "ps",                         \
+                       "fsr",                                          \
+                       "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+                       "l0", "l1", "l2", "l3", "l4",                   \
+                       }
+
+/* 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 AP_REGNUM FP_REGNUM
+#define FP_REGNUM 10           /* Contains address of executing stack frame */
+#define SP_REGNUM 9            /* Contains address of top of stack */
+#define PC_REGNUM 8            /* Contains program counter */
+#define PS_REGNUM 11           /* Contains processor status */
+#define FPS_REGNUM 12          /* Floating point status register */
+#define FP0_REGNUM 13          /* Floating point register 0 */
+#define LP0_REGNUM 21          /* Double register 0 (same as FP0) */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{                                                                      \
+  switch (regno) {                                                     \
+  case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:      \
+       addr = blockend + (R0 - regno) * sizeof (int); break;           \
+  case PC_REGNUM:                                                      \
+       addr = blockend + PC * sizeof (int); break;                     \
+  case SP_REGNUM:                                                      \
+       addr = blockend + SP * sizeof (int); break;                     \
+  case FP_REGNUM:                                                      \
+       addr = blockend + FP * sizeof (int); break;                     \
+  case PS_REGNUM:                                                      \
+       addr = blockend + 12 * sizeof (int); break;                     \
+  case FPS_REGNUM:                                                     \
+       addr = 108; break;                                              \
+  case FP0_REGNUM + 0: case FP0_REGNUM + 1:                            \
+  case FP0_REGNUM + 2: case FP0_REGNUM + 3:                            \
+  case FP0_REGNUM + 4: case FP0_REGNUM + 5:                            \
+  case FP0_REGNUM + 6: case FP0_REGNUM + 7:                            \
+       addr = 76 + (regno - FP0_REGNUM) * sizeof (float); break;       \
+  case LP0_REGNUM + 0: case LP0_REGNUM + 1:                            \
+  case LP0_REGNUM + 2: case LP0_REGNUM + 3:                            \
+       addr = 76 + (regno - LP0_REGNUM) * sizeof (double); break;      \
+  default:                                                             \
+       printf ("bad argument to REGISTER_U_ADDR %d\n", regno);         \
+       abort ();                                                       \
+  }                                                                    \
+}
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES ((NUM_REGS - 4) * sizeof (int) + 4 * sizeof (double))
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N) ((N) >= LP0_REGNUM ? \
+       LP0_REGNUM * 4 + ((N) - LP0_REGNUM) * 8 : (N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  On the 32000, all regs are 4 bytes
+   except for the doubled floating registers. */
+
+#define REGISTER_RAW_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
+
+/* Number of bytes of storage in the program's representation
+   for register N.  On the 32000, all regs are 4 bytes
+   except for the doubled floating registers. */
+
+#define REGISTER_VIRTUAL_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 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), REGISTER_VIRTUAL_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_VIRTUAL_SIZE(REGNUM));
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+  ((N) >= FP0_REGNUM ?         \
+    ((N) >= LP0_REGNUM ?       \
+     builtin_type_double       \
+     : builtin_type_float)     \
+   : builtin_type_int) 
+
+/* 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))
+\f
+/* 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 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, 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 + 4, 4))
+
+/* compute base of arguments */
+#define FRAME_ARGS_ADDRESS(fi) ((fi).frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi).frame)
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.  */
+
+#define FRAME_NUM_ARGS(numargs, fi)                    \
+{ CORE_ADDR pc;                                                \
+  int insn;                                            \
+  int addr_mode;                                       \
+  int width;                                           \
+                                                       \
+  pc = FRAME_SAVED_PC (fi.frame);                      \
+  insn = read_memory_integer (pc,2);                   \
+  addr_mode = (insn >> 11) & 0x1f;                     \
+  insn = insn & 0x7ff;                                 \
+  if ((insn & 0x7fc) == 0x57c                          \
+      && addr_mode == 0x14) /* immediate */            \
+    { if (insn == 0x57c) /* adjspb */                  \
+       width = 1;                                      \
+      else if (insn == 0x57d) /* adjspw */             \
+       width = 2;                                      \
+      else if (insn == 0x57f) /* adjspd */             \
+       width = 4;                                      \
+      numargs = read_memory_integer (pc+2,width);      \
+      if (width > 1)                                   \
+       flip_bytes (&numargs, width);                   \
+      numargs = - sign_extend (numargs, width*8) / 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) \
+{ int regmask,regnum;                                          \
+  int localcount;                                              \
+  CORE_ADDR enter_addr;                                                \
+  CORE_ADDR next_addr;                                         \
+                                                               \
+  enter_addr = get_pc_function_start ((frame_info).pc);                \
+  regmask = read_memory_integer (enter_addr+1, 1);             \
+  localcount = ns32k_localcount (enter_addr);                  \
+  next_addr = (frame_info).frame + localcount;                 \
+  for (regnum = 0; regnum < 8; regnum++, regmask >>= 1)                \
+    (frame_saved_regs).regs[regnum]                            \
+      = (regmask & 1) ? (next_addr -= 4) : 0;                  \
+  (frame_saved_regs).regs[SP_REGNUM] = (frame_info).frame + 4; \
+  (frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 4; \
+  (frame_saved_regs).regs[FP_REGNUM]                           \
+     = read_memory_integer ((frame_info).frame, 4); }
+\f
+/* 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;                                 \
+  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 < 8; regnum++)               \
+    sp = push_word (sp, read_register (regnum));       \
+  write_register (SP_REGNUM, sp);                      \
+}
+
+/* Discard from the stack the innermost frame, restoring all registers.  */
+
+#define POP_FRAME  \
+{ register CORE_ADDR fp = read_register (FP_REGNUM);            \
+  register int regnum;                                          \
+  struct frame_saved_regs fsr;                                  \
+  struct frame_info fi;                                                 \
+  fi = get_frame_info (fp);                                     \
+  get_frame_saved_regs (&fi, &fsr);                             \
+  for (regnum = 0; regnum < 8; regnum++)                        \
+    if (fsr.regs[regnum])                                       \
+      write_register (regnum, read_memory_integer (fsr.regs[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);                           \
+}
+
+/* This sequence of words is the instructions
+     enter     0xff,0          82 ff 00
+     jsr       @0x00010203     7f ae c0 01 02 03
+     adjspd    0x69696969      7f a5 01 02 03 04
+     bpt                       f2
+   Note this is 16 bytes.  */
+
+#define CALL_DUMMY { 0x7f00ff82, 0x0201c0ae, 0x01a57f03, 0xf2040302 }
+
+#define CALL_DUMMY_START_OFFSET        3
+#define CALL_DUMMY_LENGTH      16
+#define CALL_DUMMY_ADDR                5
+#define CALL_DUMMY_NARGS       11
+
+/* 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, fun, nargs)                  \
+{ int flipped = fun | 0xc0000000;                              \
+  flip_bytes (&flipped, 4);                                    \
+  *((int *) (((char *) dummyname)+CALL_DUMMY_ADDR)) = flipped; \
+  flipped = - nargs * 4;                                       \
+  flip_bytes (&flipped, 4);                                    \
+  *((int *) (((char *) dummyname)+CALL_DUMMY_NARGS)) = flipped;        \
+}
+\f
+#ifdef notdef
+/* 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, 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, sp");      \
+  asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR        \
+  asm ("pushl fp");
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR  \
+  asm ("movl (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 ("pushl 8(sp)");        \
+  asm ("pushl 8(sp)");        \
+  asm ("pushal 0x14(sp)");    \
+  asm ("pushr $037777"); }
+
+/* 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 ("popr $037777");    \
+  asm ("subl2 $8,(sp)");   \
+  asm ("movl (sp),sp");    \
+  asm ("rei"); }
+#endif
diff --git a/gdb/m-news800.h b/gdb/m-news800.h
new file mode 100644 (file)
index 0000000..44583e3
--- /dev/null
@@ -0,0 +1,566 @@
+/* Parameters for execution on a Sony/NEWS, for GDB, the GNU debugger.
+
+Here is an m-news800.h file for gdb version 2.1.  It supports the 68881
+registers.
+
+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.
+(hikichi@srava.sra.junet or hikichi%srava.sra.junet%kddlabs%seismo.CSS.GOV) 
+
+Here is IEEE nan routine to use such bug fixed.
+
+       printf("%g\n", Nan);
+
+> struct ieee {                         |* IEEE floating format *|
+>   unsigned int s:1;
+>   unsigned int e:11;
+>   unsigned int f1:20;
+>   unsigned int f2;
+> };
+> 
+> #define ZERO_F(x)  ((x.f1 == 0) && (x.f2 == 0))     |* zero fraction ? *|
+> #define ZERO_E(x)  (x.e == 0)                       |* zero exponential ? *|
+> #define MAX_E(x)   (x.e == 0x7ff)                   |* max exponential ? *|
+> #define MINUS_S(x) (x.s == 1)                       |* minus ? *|
+> 
+> int
+> is_nan(arg)                            |* Not a Number ? *|
+> struct ieee arg;
+> {
+>   if (MAX_E(arg) && !ZERO_F(arg))
+>     return (1);
+>   else
+>     return (0);
+> }
+> 
+> int
+> is_plus_infinity(arg)
+> struct ieee arg;
+> {
+>   if (!MINUS_S(arg) && MAX_E(arg) && ZERO_F(arg))
+>     return (1);
+>   else
+>     return (0);
+> }
+> 
+> int
+> is_minus_infinity(arg)
+> struct ieee arg;
+> {
+>   if (MINUS_S(arg) && MAX_E(arg) && ZERO_F(arg))
+>     return (1);
+>   else
+>     return (0);
+> }
+> 
+> int
+> is_denormal(arg)
+> struct ieee arg;
+> {
+>   if (ZERO_E(arg))
+>     return (1);
+>   else
+>     return (0);
+> }
+
+   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!
+*/
+
+#ifdef 0  /* cannot use RCS id since initialize routine fails. */
+static char *RCSid =
+"$Header: m-news800.h,v 1.1 87/09/21 21:27:52 hikichi Exp $";
+#endif  lint
+
+/*
+ * $Log:       m-news800.h,v $
+ * Revision 1.1  87/09/21  21:27:52  hikichi
+ * Initial revision
+ * 
+ */
+
+/* Identify this machine */
+#ifndef news800
+#define news800
+#endif
+
+/* #define USE_GAS */
+
+/* Motorola assembly format */
+#ifndef USE_GAS
+#define MOTOROLA
+#endif
+
+/* bug when printf special number; NAN */
+#define PRINTF_BUG
+
+/* 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
+
+/* 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 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 UADDR
+
+/* Address of end of stack space.  */
+
+#define STACK_END_ADDR (0x80000000 - ctob(UPAGES + 1))
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {0x4e, 0x4f}
+
+/* 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 2
+
+/* Nonzero if instruction at PC is a return instruction.  */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e76)
+
+/* Return 1 if P points to an invalid floating point value.  */
+
+#define INVALID_FLOAT(p) 0   /* Just a first guess; not checked */
+
+/* Say how long 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", \
+  "pc", "ps",  \
+  "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 PC_REGNUM 16           /* Contains program counter */
+#define PS_REGNUM 17           /* Contains processor status */
+#define FP0_REGNUM 18          /* Floating point register 0 */
+#define FPC_REGNUM 26          /* 68881 control register */
+
+#define REGISTER_U_ADDR(addr, blockend, regno)         \
+{      if (regno <= FP_REGNUM) \
+         addr = blockend + 4 + regno * 4; \
+       else if (regno == SP_REGNUM) \
+         addr = blockend - 4 * 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; \
+       else \
+         addr = blockend + 4 + 4 * 16 + (regno - FPC_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)
+
+/* 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.  */
+
+#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)
+\f
+/* 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 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, 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 + 4, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) (fi.frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) (fi.frame)
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.  */
+
+#define FRAME_NUM_ARGS(val, 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 */ \
+    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; }
+
+/* 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;                                               \
+  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;         \
+}
+\f
+/* 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 registers.  */
+
+#define POP_FRAME  \
+{ register CORE_ADDR fp = read_register (FP_REGNUM);                   \
+  register int regnum;                                                 \
+  struct frame_saved_regs fsr;                                         \
+  struct frame_info fi;                                                        \
+  char raw_buffer[12];                                                 \
+  fi = get_frame_info (fp);                                            \
+  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);                                  \
+}
+
+/* This sequence of words is the instructions
+     fmove.m #<f0-f7>,-(sp)
+     movem.l 0xfffc,-(sp)
+     clr.w -(sp)
+     move.w 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.  *../
+     jbsr (#32323232)
+     add.l #69696969,sp
+     bpt
+     nop
+Note this is 24 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, fun, nargs)     \
+{ *(int *)((char *) dummyname + 20) = nargs * 4;  \
+  *(int *)((char *) dummyname + 14) = fun; }
+\f
+/* 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.  */
+
+#ifdef MOTOROLA
+#define INIT_STACK(beg, end)  \
+{ asm (".globl end");         \
+  asm ("move.l $ end, sp");      \
+  asm ("clr.l fp"); }
+#else
+#define INIT_STACK(beg, end)  \
+{ asm (".globl end");         \
+  asm ("movel $ end, sp");      \
+  asm ("clrl fp"); }
+#endif
+
+/* Push the frame pointer register on the stack.  */
+#ifdef MOTOROLA
+#define PUSH_FRAME_PTR        \
+  asm ("move.l fp, -(sp)");
+#else
+#define PUSH_FRAME_PTR        \
+  asm ("movel fp, -(sp)");
+#endif
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#ifdef MOTOROLA
+#define POP_FRAME_PTR  \
+  asm ("move.l (sp), fp");
+#else
+#define POP_FRAME_PTR  \
+  asm ("movl (sp), fp");
+#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
+#define PUSH_REGISTERS        \
+{ asm ("clrw -(sp)");        \
+  asm ("pea 10(sp)");        \
+  asm ("movem $ 0xfffe,-(sp)"); }
+#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 ("subi.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
+
diff --git a/gdb/m-newsinit.h b/gdb/m-newsinit.h
new file mode 100644 (file)
index 0000000..d902edf
--- /dev/null
@@ -0,0 +1,4 @@
+/* This is how the size of an individual .o file's text segment
+   is rounded on a SONY NEWS.  */
+
+#define FILEADDR_ROUND(addr) ((addr + 3) & -4)
diff --git a/gdb/m-sun2.h b/gdb/m-sun2.h
new file mode 100644 (file)
index 0000000..833c923
--- /dev/null
@@ -0,0 +1,421 @@
+/* Parameters for execution on a Sun, 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 sun2
+#define sun2
+#endif
+
+/* 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.  */
+
+#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)
+
+/* 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 0x2800
+
+/* Address of end of stack space.  */
+
+#define STACK_END_ADDR 0x1000000
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {0x4e, 0x4f}
+
+/* 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 2
+
+/* Nonzero if instruction at PC is a return instruction.  */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e76)
+
+/* Return 1 if P points to an invalid floating point value.  */
+
+#define INVALID_FLOAT(p, len) 0   /* Just a first guess; not checked */
+
+/* Say how long registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 18
+
+/* Number that are really general registers */
+
+#define NUM_GENERAL_REGS 16
+
+/* 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"}
+
+/* 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 */
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES (16*4+8)
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N)  ((N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  On the 68000, 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 68000, all regs are 4 bytes.  */
+
+#define REGISTER_VIRTUAL_SIZE(N) 4
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)  bcopy ((FROM), (TO), 4);
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)  bcopy ((FROM), (TO), 4);
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N)  builtin_type_int
+
+/* 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))
+
+/* 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)         \
+{ addr = blockend + regno * 4; }
+\f
+/* 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 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, 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 + 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.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 */ \
+    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;                                               \
+  bzero (&frame_saved_regs, sizeof frame_saved_regs);                  \
+  if ((frame_info).pc >= (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 4 \
+      && (frame_info).pc <= (frame_info).frame)                                \
+    { next_addr = (frame_info).frame;                                  \
+      pc = (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 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);                           \
+  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); }            \
+  /* 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;         \
+}
+\f
+/* 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;                             \
+  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 CORE_ADDR fp = read_register (FP_REGNUM);            \
+  register int regnum;                                          \
+  struct frame_saved_regs fsr;                                  \
+  struct frame_info fi;                                                 \
+  fi = get_frame_info (fp);                                     \
+  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);                           \
+}
+
+/* This sequence of words is the instructions
+     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
+     bpt
+     nop
+Note this is 24 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 {0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
+
+#define CALL_DUMMY_LENGTH 24
+
+#define CALL_DUMMY_START_OFFSET 8
+
+/* 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, fun, nargs)     \
+{ *(int *)((char *) dummyname + 16) = nargs * 4;  \
+  *(int *)((char *) dummyname + 10) = fun; }
+\f
+/* 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 ("clrl fp"); }
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR        \
+  asm ("movel fp, -(sp)");
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR  \
+  asm ("movl (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 ("clrw -(sp)");        \
+  asm ("pea 10(sp)");        \
+  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,28(sp)");     \
+  asm ("movem (sp),$ 0xffff"); \
+  asm ("rte"); }
diff --git a/gdb/m-sun3.h b/gdb/m-sun3.h
new file mode 100644 (file)
index 0000000..9d703aa
--- /dev/null
@@ -0,0 +1,477 @@
+/* Parameters for execution on a Sun, 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 sun3
+#define sun3
+#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
+
+/* 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 0xf000000
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {0x4e, 0x4f}
+
+/* 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 2
+
+/* Nonzero if instruction at PC is a return instruction.  */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e76)
+
+/* Return 1 if P points to an invalid floating point value.  */
+
+#define INVALID_FLOAT(p, len) 0   /* Just a first guess; not checked */
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 31
+
+/* 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", "fpcode", "fpflags" }
+
+/* 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 */
+
+/* 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.  */
+
+#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)
+
+/* 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))
+
+/* 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
+\f
+/* 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 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, 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 + 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.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 */ \
+    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;         \
+}
+\f
+/* 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 CORE_ADDR fp = read_register (FP_REGNUM);            \
+  register int regnum;                                          \
+  struct frame_saved_regs fsr;                                  \
+  struct frame_info fi;                                                 \
+  char raw_buffer[12];                                          \
+  fi = get_frame_info (fp);                                     \
+  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);                           \
+  set_current_frame (read_register (FP_REGNUM)); }
+
+/* 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
+     bpt
+     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, fun, nargs)     \
+{ *(int *)((char *) dummyname + 20) = nargs * 4;  \
+  *(int *)((char *) dummyname + 14) = fun; }
+\f
+/* 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"); }
diff --git a/gdb/m-suninit.h b/gdb/m-suninit.h
new file mode 100644 (file)
index 0000000..2e2f08c
--- /dev/null
@@ -0,0 +1,5 @@
+
+/* This is how the size of an individual .o file's text segment
+   is rounded on a sun.  */
+
+#define FILEADDR_ROUND(addr) (addr)
diff --git a/gdb/m-umax.h b/gdb/m-umax.h
new file mode 100644 (file)
index 0000000..d894b56
--- /dev/null
@@ -0,0 +1,425 @@
+/* Definitions to make GDB run on an encore under umax 4.2
+   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!
+*/
+
+#ifndef ns16000
+#define ns16000
+#endif
+
+#define HAVE_WAIT_STRUCT
+
+/* Encore's modifications to ptrace format */
+
+#define UMAX_PTRACE
+
+/* Encore's modifications to core-file format */
+
+#define UMAX_CORE
+
+/* 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
+
+/* Exec files and symbol tables are in COFF format */
+
+#define COFF_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.  */
+
+#define SKIP_PROLOGUE(pc)                              \
+{ register unsigned char op = read_memory_integer (pc, 1);     \
+  if (op == 0x82) { op = read_memory_integer (pc+2,1);  \
+                   if ((op & 0x80) == 0) pc += 3;      \
+                   else if ((op & 0xc0) == 0x80) pc += 4;      \
+                   else pc += 6;                       \
+                  }                                    \
+}
+
+/* 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)
+
+/* Address of end of stack space.  */
+
+#define STACK_END_ADDR (0xfffff000)
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {0xf2}
+
+/* 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, 1) == 0x12)
+
+#ifndef NaN
+#include <nan.h>
+#endif NaN
+
+/* Return 1 if P points to an invalid floating point value.  */
+
+#define INVALID_FLOAT(p, s) \
+        ((s == sizeof (float))?        \
+               NaF (*(float *) p) :    \
+               NaD (*(double *) p))
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS               25
+
+#define NUM_GENERAL_REGS       8
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",        \
+                       "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+                       "sp", "fp", "pc", "ps",                         \
+                       "fsr",                                          \
+                       "l0", "l1", "l2", "l3", "xx",                   \
+                       }
+
+/* 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 FP0_REGNUM 8           /* Floating point register 0 */
+#define SP_REGNUM 16           /* Contains address of top of stack */
+#define AP_REGNUM FP_REGNUM
+#define FP_REGNUM 17           /* Contains address of executing stack frame */
+#define PC_REGNUM 18           /* Contains program counter */
+#define PS_REGNUM 19           /* Contains processor status */
+#define FPS_REGNUM 20          /* Floating point status register */
+#define LP0_REGNUM 21          /* Double register 0 (same as FP0) */
+
+/* called from register_addr() -- blockend not used for now */
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{                                                                      \
+  switch (regno) {                                                     \
+  case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:      \
+       addr = PU_R0 - (regno * sizeof (int)); break;                   \
+  case SP_REGNUM:                                                      \
+       addr = PU_SP; break;                                            \
+  case PC_REGNUM:                                                      \
+       addr = PU_PC; break;                                            \
+  case FP_REGNUM:                                                      \
+       addr = PU_FP; break;                                            \
+  case PS_REGNUM:                                                      \
+       addr = PU_PSL; break;                                           \
+  case FPS_REGNUM:                                                     \
+       addr = PU_FSR; break;                                           \
+  case FP0_REGNUM + 0: case FP0_REGNUM + 1:                            \
+  case FP0_REGNUM + 2: case FP0_REGNUM + 3:                            \
+  case FP0_REGNUM + 4: case FP0_REGNUM + 5:                            \
+  case FP0_REGNUM + 6: case FP0_REGNUM + 7:                            \
+       addr = PU_F0 + (regno - FP0_REGNUM) * sizeof (float); break;    \
+  case LP0_REGNUM + 0: case LP0_REGNUM + 1:                            \
+  case LP0_REGNUM + 2: case LP0_REGNUM + 3:                            \
+       addr = PU_F0 + (regno - LP0_REGNUM) * sizeof (double); break;   \
+  default:                                                             \
+       printf ("bad argument to REGISTER_U_ADDR %d\n", regno);         \
+       abort ();                                                       \
+  }                                                                    \
+}
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES ((NUM_REGS - 4) * sizeof (int) + 4 * sizeof (double))
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N) ((N) >= LP0_REGNUM ? \
+       LP0_REGNUM * 4 + ((N) - LP0_REGNUM) * 8 : (N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  On the 32000, all regs are 4 bytes
+   except for the doubled floating registers. */
+
+#define REGISTER_RAW_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
+
+/* Number of bytes of storage in the program's representation
+   for register N.  On the 32000, all regs are 4 bytes
+   except for the doubled floating registers. */
+
+#define REGISTER_VIRTUAL_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 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), REGISTER_VIRTUAL_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_VIRTUAL_SIZE(REGNUM));
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+       (((N) < FP0_REGNUM) ?                           \
+               builtin_type_int :                      \
+               ((N) < FP0_REGNUM + 8) ?                \
+                       builtin_type_float :            \
+                       ((N) < LP0_REGNUM) ?            \
+                               builtin_type_int :      \
+                               builtin_type_double)
+
+/* 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+REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 0), 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 (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 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))
+\f
+/* 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 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, 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 + 4, 4))
+
+/* Compute base of arguments. */
+
+#define FRAME_ARGS_ADDRESS(fi) \
+  ((n32k_get_enter_addr (fi.pc) > 1) ? \
+       ((fi).frame) : (read_register (SP_REGNUM) - 4))
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi).frame)
+
+/* Get the address of the enter opcode for this function, if it is active.
+   Returns positive address > 1 if pc is between enter/exit,
+   1 if pc before enter or after exit, 0 otherwise. */
+
+extern CORE_ADDR n32k_get_enter_addr ();
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.
+   Encore's C compiler often reuses same area on stack for args,
+   so this will often not work properly.  If the arg names
+   are known, it's likely most of them will be printed. */
+
+#define FRAME_NUM_ARGS(numargs, fi)                    \
+{ CORE_ADDR    pc;                                     \
+  CORE_ADDR    enter_addr;                             \
+  unsigned int insn;                                   \
+  unsigned int addr_mode;                              \
+  int width;                                           \
+                                                       \
+  numargs = -1;                                                \
+  enter_addr = n32k_get_enter_addr (fi.pc);            \
+  if (enter_addr > 0)                                  \
+    {                                                  \
+      pc = (enter_addr == 1) ?                         \
+       SAVED_PC_AFTER_CALL () :                        \
+       FRAME_SAVED_PC (fi.frame);                      \
+      insn = read_memory_integer (pc,2);               \
+      addr_mode = (insn >> 11) & 0x1f;                 \
+      insn = insn & 0x7ff;                             \
+      if ((insn & 0x7fc) == 0x57c &&                   \
+               addr_mode == 0x14) /* immediate */      \
+       {                                               \
+         if (insn == 0x57c) /* adjspb */               \
+               width = 1;                              \
+         else if (insn == 0x57d) /* adjspw */          \
+               width = 2;                              \
+         else if (insn == 0x57f) /* adjspd */          \
+               width = 4;                              \
+         numargs = read_memory_integer (pc+2,width);   \
+         if (width > 1)                                \
+           flip_bytes (&numargs, width);               \
+         numargs = - sign_extend (numargs, width*8) / 4;\
+       }                                               \
+    }                                                  \
+}
+
+/* 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 regmask, regnum;                                \
+  int          localcount;                                     \
+  register CORE_ADDR   enter_addr;                             \
+  register CORE_ADDR   next_addr;                              \
+                                                               \
+  bzero (&(frame_saved_regs), sizeof (frame_saved_regs));      \
+  enter_addr = n32k_get_enter_addr ((frame_info).pc);          \
+  if (enter_addr > 1)                                          \
+    {                                                          \
+      regmask = read_memory_integer (enter_addr+1, 1) & 0xff;  \
+      localcount = n32k_localcount (enter_addr);               \
+      next_addr = (frame_info).frame + localcount;             \
+      for (regnum = 0; regnum < 8; regnum++, regmask >>= 1)    \
+       (frame_saved_regs).regs[regnum] = (regmask & 1) ?       \
+                                         (next_addr -= 4) : 0; \
+      (frame_saved_regs).regs[SP_REGNUM] = (frame_info).frame + 4;\
+      (frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 4;\
+      (frame_saved_regs).regs[FP_REGNUM] =                     \
+                 (read_memory_integer ((frame_info).frame, 4));\
+    }                                                          \
+  else if (enter_addr == 1)                                    \
+    {                                                          \
+      CORE_ADDR sp = read_register (SP_REGNUM);                        \
+      (frame_saved_regs).regs[PC_REGNUM] = sp;                 \
+      (frame_saved_regs).regs[SP_REGNUM] = sp + 4;             \
+    }                                                          \
+}
+\f
+/* 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;                             \
+  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 < 8; regnum++)  \
+    sp = push_word (sp, read_register (regnum));    \
+  write_register (SP_REGNUM, sp);                      \
+}
+
+/* Discard from the stack the innermost frame, restoring all registers.  */
+
+#define POP_FRAME  \
+{ register CORE_ADDR fp = read_register (FP_REGNUM);            \
+  register int regnum;                                          \
+  struct frame_saved_regs fsr;                                  \
+  struct frame_info fi;                                                 \
+  fi = get_frame_info (fp);                                     \
+  get_frame_saved_regs (&fi, &fsr);                             \
+  for (regnum = 0; regnum < 8; regnum++)                        \
+    if (fsr.regs[regnum])                                       \
+      write_register (regnum, read_memory_integer (fsr.regs[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);                           \
+}
+
+/* This sequence of words is the instructions
+     enter     0xff,0          82 ff 00
+     jsr       @0x00010203     7f ae c0 01 02 03
+     adjspd    0x69696969      7f a5 01 02 03 04
+     bpt                       f2
+   Note this is 16 bytes.  */
+
+#define CALL_DUMMY { 0x7f00ff82, 0x0201c0ae, 0x01a57f03, 0xf2040302 }
+
+#define CALL_DUMMY_START_OFFSET        3
+#define CALL_DUMMY_LENGTH      16
+#define CALL_DUMMY_ADDR                5
+#define CALL_DUMMY_NARGS       11
+
+/* 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, fun, nargs)                  \
+{                                                              \
+       int     flipped;                                        \
+       flipped = fun | 0xc0000000;                             \
+       flip_bytes (&flipped, 4);                               \
+       *((int *) (((char *) dummyname)+CALL_DUMMY_ADDR)) = flipped;    \
+       flipped = - nargs * 4;                                  \
+       flip_bytes (&flipped, 4);                               \
+       *((int *) (((char *) dummyname)+CALL_DUMMY_NARGS)) = flipped;   \
+}
diff --git a/gdb/m-vax.h b/gdb/m-vax.h
new file mode 100644 (file)
index 0000000..578af44
--- /dev/null
@@ -0,0 +1,375 @@
+/* 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!
+*/
+
+#ifndef vax
+#define vax
+#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
+
+/* Offset from address of function to start of its code.
+   Zero on most machines.  */
+
+#define FUNCTION_START_OFFSET 2
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  */
+
+#define SKIP_PROLOGUE(pc)   \
+{ register int op = read_memory_integer (pc, 1);       \
+  if (op == 0x11) pc += 2;  /* skip brb */             \
+  if (op == 0x31) pc += 3;  /* skip brw */             \
+}
+
+/* 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) FRAME_SAVED_PC(frame)
+
+/* 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 (0x80000000 - (UPAGES * NBPG))
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {3}
+
+/* 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, 1) == 04)
+
+/* Return 1 if P points to an invalid floating point value.
+   LEN is the length in bytes -- not relevant on the Vax.  */
+
+#define INVALID_FLOAT(p, len) ((*(short *) p & 0xff80) == 0x8000)
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 17
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc", "ps"}
+
+/* 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 AP_REGNUM 12
+#define FP_REGNUM 13           /* Contains address of executing stack frame */
+#define SP_REGNUM 14           /* Contains address of top of stack */
+#define PC_REGNUM 15           /* Contains program counter */
+#define PS_REGNUM 16           /* Contains processor status */
+
+#define REGISTER_U_ADDR(addr, blockend, regno)         \
+{ addr = blockend - 0110 + regno * 4;                  \
+  if (regno == PC_REGNUM) addr = blockend - 8;         \
+  if (regno == PS_REGNUM) addr = blockend - 4;         \
+  if (regno == FP_REGNUM) addr = blockend - 0120;      \
+  if (regno == AP_REGNUM) addr = blockend - 0124;      \
+  if (regno == SP_REGNUM) addr = blockend - 20; }
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES (17*4)
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N) ((N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  On the vax, 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 vax, all regs are 4 bytes.  */
+
+#define REGISTER_VIRTUAL_SIZE(N) 4
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)    \
+  bcopy ((FROM), (TO), 4);
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)        \
+  bcopy ((FROM), (TO), 4);
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) builtin_type_int
+
+/* 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))
+\f
+/* 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 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 + 12, 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 + 16, 4))
+
+/* Cannot find the AP register value directly from the FP value.
+   Must find it saved in the frame called by this one, or in the AP register
+   for the innermost frame.  */
+#define FRAME_ARGS_ADDRESS(fi) \
+ (((fi).next_frame                                  \
+   ? read_memory_integer ((fi).next_frame + 8, 4)   \
+   : read_register (AP_REGNUM)))
+
+#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 = (0xff & read_memory_integer (FRAME_ARGS_ADDRESS (fi), 1)); }
+
+/* Return number of bytes at start of arglist that are not really args.  */
+
+#define FRAME_ARGS_SKIP 4
+
+/* 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 = read_memory_integer ((frame_info).frame+4, 4) >> 16; \
+  register CORE_ADDR next_addr;     \
+  bzero (&frame_saved_regs, sizeof frame_saved_regs);     \
+  next_addr = (frame_info).frame + 16;     \
+  /* Regmask's low bit is for register 0,     \
+     which is the first one that would be pushed.  */     \
+  for (regnum = 0; regnum < 12; regnum++, regmask >>= 1)  \
+    (frame_saved_regs).regs[regnum] = (regmask & 1) ? (next_addr += 4) : 0;  \
+  (frame_saved_regs).regs[SP_REGNUM] = next_addr + 4;  \
+  if (read_memory_integer ((frame_info).frame + 4, 4) & 0x20000000)   \
+    (frame_saved_regs).regs[SP_REGNUM] += 4 + 4 * read_memory_integer (next_addr + 4, 4);  \
+  (frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 16;  \
+  (frame_saved_regs).regs[FP_REGNUM] = (frame_info).frame + 12;  \
+  (frame_saved_regs).regs[AP_REGNUM] = (frame_info).frame + 8;  \
+  (frame_saved_regs).regs[PS_REGNUM] = (frame_info).frame + 4;  \
+}
+\f
+/* 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;                             \
+  sp = push_word (sp, 0); /* arglist */                    \
+  for (regnum = 11; regnum >= 0; regnum--)         \
+    sp = push_word (sp, read_register (regnum));    \
+  sp = push_word (sp, read_register (PC_REGNUM));   \
+  sp = push_word (sp, read_register (FP_REGNUM));   \
+  sp = push_word (sp, read_register (AP_REGNUM));   \
+  sp = push_word (sp, (read_register (PS_REGNUM) & 0xffef)   \
+                     + 0x2fff0000);                \
+  sp = push_word (sp, 0);                          \
+  write_register (SP_REGNUM, sp);                  \
+  write_register (FP_REGNUM, sp);                  \
+  write_register (AP_REGNUM, sp + 17 * sizeof (int)); }
+
+/* Discard from the stack the innermost frame, restoring all registers.  */
+
+#define POP_FRAME  \
+{ register CORE_ADDR fp = read_register (FP_REGNUM);            \
+  register int regnum;                                          \
+  register int regmask = read_memory_integer (fp + 4, 4);       \
+  write_register (PS_REGNUM,                                    \
+                 (regmask & 0xffff)                             \
+                 | (read_register (PS_REGNUM) & 0xffff0000));   \
+  write_register (PC_REGNUM, read_memory_integer (fp + 16, 4));  \
+  write_register (FP_REGNUM, read_memory_integer (fp + 12, 4));  \
+  write_register (AP_REGNUM, read_memory_integer (fp + 8, 4));   \
+  fp += 16;                                                     \
+  for (regnum = 0; regnum < 12; regnum++)                       \
+    if (regmask & (0x10000 << regnum))                          \
+      write_register (regnum, read_memory_integer (fp += 4, 4)); \
+  fp = fp + 4 + ((regmask >> 30) & 3);                          \
+  if (regmask & 0x20000000)                                     \
+    { regnum = read_memory_integer (fp, 4);                     \
+      fp += (regnum + 1) * 4; }                                         \
+  write_register (SP_REGNUM, fp);                               \
+  set_current_frame (read_register (FP_REGNUM)); }
+
+/* This sequence of words is the instructions
+     calls #69, @#32323232
+     bpt
+   Note this is 8 bytes.  */
+
+#define CALL_DUMMY {0x329f69fb, 0x03323232}
+
+#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, fun, nargs)   \
+{ *((char *) dummyname + 1) = nargs;           \
+  *(int *)((char *) dummyname + 3) = fun; }
+\f
+/* 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, 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, sp");      \
+  asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR        \
+  asm ("pushl fp");
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR  \
+  asm ("movl (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 ("pushl 8(sp)");        \
+  asm ("pushl 8(sp)");        \
+  asm ("pushal 0x14(sp)");    \
+  asm ("pushr $037777"); }
+
+/* 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 ("popr $037777");    \
+  asm ("subl2 $8,(sp)");   \
+  asm ("movl (sp),sp");    \
+  asm ("rei"); }
diff --git a/gdb/m-vaxinit.h b/gdb/m-vaxinit.h
new file mode 100644 (file)
index 0000000..6044867
--- /dev/null
@@ -0,0 +1,5 @@
+
+/* This is how the size of an individual .o file's text segment
+   is rounded on a vax.  */
+
+#define FILEADDR_ROUND(addr) ((addr + 3) & -4)
diff --git a/gdb/m68k-opcode.h b/gdb/m68k-opcode.h
new file mode 100644 (file)
index 0000000..111fd84
--- /dev/null
@@ -0,0 +1,1272 @@
+/* Opcode table for m68000/m68020 and m68881.  */
+
+struct m68k_opcode
+{
+  char *name;
+  unsigned long opcode;
+  unsigned long  match;
+  char *args;
+};
+
+/* We store four bytes of opcode for all opcodes because that
+   is the most any of them need.  The actual length of an instruction
+   is always at least 2 bytes, and is as much longer as necessary to
+   hold the operands it has.
+
+   The match component is a mask saying which bits must match
+   particular opcode in order for an instruction to be an instance
+   of that opcode.
+
+   The args component is a string containing two characters
+   for each operand of the instruction.  The first specifies
+   the kind of operand; the second, the place it is stored.  */
+
+/* Kinds of operands:
+   D  data register only.  Stored as 3 bits.
+   A  address register only.  Stored as 3 bits.
+   R  either kind of register.  Stored as 4 bits.
+   F  floating point coprocessor register only.   Stored as 3 bits.
+   O  an offset (or width): immediate data 0-31 or data register.
+      Stored as 6 bits in special format for BF... insns.
+   +  autoincrement only.  Stored as 3 bits (number of the address register).
+   -  autodecrement only.  Stored as 3 bits (number of the address register).
+   Q  quick immediate data.  Stored as 3 bits.
+      This matches an immediate operand only when value is in range 1 .. 8.
+   M  moveq immediate data.  Stored as 8 bits.
+      This matches an immediate operand only when value is in range -128..127
+   T  trap vector immediate data.  Stored as 4 bits.
+
+   k  K-factor for fmove.p instruction.   Stored as a 7-bit constant or
+      a three bit register offset, depending on the field type.
+
+   #  immediate data.  Stored in special places (b, w or l)
+      which say how many bits to store.
+   ^  immediate data for floating point instructions.   Special places
+      are offset by 2 bytes from '#'...
+   B  pc-relative address, converted to an offset
+      that is treated as immediate data.
+   d  displacement and register.  Stores the register as 3 bits
+      and stores the displacement in the entire second word.
+
+   C  the CCR.  No need to store it; this is just for filtering validity.
+   S  the SR.  No need to store, just as with CCR.
+   U  the USP.  No need to store, just as with CCR.
+
+   I  Coprocessor ID.   Not printed if 1.   The Coprocessor ID is always
+      extracted from the 'd' field of word one, which means that an extended
+      coprocessor opcode can be skipped using the 'i' place, if needed.
+
+   s  System Control register for the floating point coprocessor.
+
+   J  Misc register for movec instruction, stored in 'j' format.
+       Possible values:
+       000     SFC     Source Function Code reg
+       001     DFC     Data Function Code reg
+       002     CACR    Cache Control Register
+       800     USP     User Stack Pointer
+       801     VBR     Vector Base reg
+       802     CAAR    Cache Address Register
+       803     MSP     Master Stack Pointer
+       804     ISP     Interrupt Stack Pointer
+
+ These specify various classes of addressing modes.
+ They are all stored as 6 bits using an address mode and a register number;
+ they differ in which addressing modes they match.
+
+   *  all                                      (modes 0-6,7.*)
+   ~  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
+   !  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 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)
+*/
+
+/* Places to put an operand, for non-general operands:
+   s  source, low bits of first word.
+   d  dest, shifted 9 in first word
+   1  second word, shifted 12
+   2  second word, shifted 6
+   3  second word, shifted 0
+   4  third word, shifted 12
+   5  third word, shifted 6
+   6  third word, shifted 0
+   7  second word, shifted 7
+   8  second word, shifted 10
+   D  store in both place 1 and place 3; for divul and divsl.
+   b  second word, low byte
+   w  second word (entire)
+   l  second and third word (entire)
+   g  branch offset for bra and similar instructions.
+      The place to store depends on the magnitude of offset.
+   t  store in both place 7 and place 8; for floating point operations
+   c  branch offset for cpBcc operations.
+      The place to store is word two if bit six of word one is zero,
+      and words two and three if bit six of word one is one.
+   i  Increment by two, to skip over coprocessor extended operands.   Only
+      works with the 'I' format.
+   k  Dynamic K-factor field.   Bits 6-4 of word 2, used as a register number.
+      Also used for dynamic fmovem instruction.
+   C  floating point coprocessor constant - 7 bits.  Also used for static
+      K-factors...
+   j  Movec register #, stored in 12 low bits of second word.
+
+ Places to put operand, for general operands:
+   d  destination, shifted 6 bits in first word
+   b  source, at low bit of first word, and immediate uses one byte
+   w  source, at low bit of first word, and immediate uses two bytes
+   l  source, at low bit of first word, and immediate uses four bytes
+   s  source, at low bit of first word.
+      Used sometimes in contexts where immediate is not allowed anyway.
+   f  single precision float, low bit of 1st word, immediate uses 4 bytes
+   F  double precision float, low bit of 1st word, immediate uses 8 bytes
+   x  extended precision float, low bit of 1st word, immediate uses 12 bytes
+   p  packed float, low bit of 1st word, immediate uses 12 bytes
+*/
+
+#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.
+ */
+struct m68k_opcode m68k_opcodes[] =
+{
+{"abcd",       one(0140400),           one(0170770),           "DsDd"},
+{"abcd",       one(0140410),           one(0170770),           "-s-d"},
+
+               /* Add instructions */
+{"addal",      one(0150700),           one(0170700),           "*lAd"},
+{"addaw",      one(0150300),           one(0170700),           "*wAd"},
+{"addib",      one(0003000),           one(0177700),           "#b$b"},
+{"addil",      one(0003200),           one(0177700),           "#l$l"},
+{"addiw",      one(0003100),           one(0177700),           "#w$w"},
+{"addqb",      one(0050000),           one(0170700),           "Qd$b"},
+{"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(0150000),           one(0170700),           ";bDd"},        /* addb <ea>,   Dd */
+{"addb",       one(0150400),           one(0170700),           "Dd~b"},        /* addb Dd,     <ea> */
+
+{"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 <ea>,   Dd */
+{"addw",       one(0150500),           one(0170700),           "Dd~w"},        /* addw Dd,     <ea> */
+
+{"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 <ea>,   Dd */
+{"addl",       one(0150600),           one(0170700),           "Dd~l"},        /* addl Dd,     <ea> */
+
+{"addxb",      one(0150400),           one(0170770),           "DsDd"},
+{"addxb",      one(0150410),           one(0170770),           "-s-d"},
+{"addxl",      one(0150600),           one(0170770),           "DsDd"},
+{"addxl",      one(0150610),           one(0170770),           "-s-d"},
+{"addxw",      one(0150500),           one(0170770),           "DsDd"},
+{"addxw",      one(0150510),           one(0170770),           "-s-d"},
+
+{"andib",      one(0001000),           one(0177700),           "#b$b"},
+{"andib",      one(0001074),           one(0177777),           "#bCb"},        /* andi to ccr */
+{"andiw",      one(0001100),           one(0177700),           "#w$w"},
+{"andiw",      one(0001174),           one(0177777),           "#wSw"},        /* andi to sr */
+{"andil",      one(0001200),           one(0177700),           "#l$l"},
+
+{"andb",       one(0001000),           one(0177700),           "#b$b"},        /* andi written as or */
+{"andb",       one(0001074),           one(0177777),           "#bCb"},        /* andi to ccr */
+{"andb",       one(0140000),           one(0170700),           ";bDd"},        /* memory to register */
+{"andb",       one(0140400),           one(0170700),           "Dd~b"},        /* register to memory */
+{"andw",       one(0001100),           one(0177700),           "#w$w"},        /* andi written as or */
+{"andw",       one(0001174),           one(0177777),           "#wSw"},        /* andi to sr */
+{"andw",       one(0140100),           one(0170700),           ";wDd"},        /* memory to register */
+{"andw",       one(0140500),           one(0170700),           "Dd~w"},        /* register to memory */
+{"andl",       one(0001200),           one(0177700),           "#l$l"},        /* andi written as or */
+{"andl",       one(0140200),           one(0170700),           ";lDd"},        /* memory to register */
+{"andl",       one(0140600),           one(0170700),           "Dd~l"},        /* register to memory */
+
+{"aslb",       one(0160400),           one(0170770),           "QdDs"},
+{"aslb",       one(0160440),           one(0170770),           "DdDs"},
+{"asll",       one(0160600),           one(0170770),           "QdDs"},
+{"asll",       one(0160640),           one(0170770),           "DdDs"},
+{"aslw",       one(0160500),           one(0170770),           "QdDs"},
+{"aslw",       one(0160540),           one(0170770),           "DdDs"},
+{"aslw",       one(0160700),           one(0177700),           "~s"},  /* Shift memory */
+{"asrb",       one(0160000),           one(0170770),           "QdDs"},
+{"asrb",       one(0160040),           one(0170770),           "DdDs"},
+{"asrl",       one(0160200),           one(0170770),           "QdDs"},
+{"asrl",       one(0160240),           one(0170770),           "DdDs"},
+{"asrw",       one(0160100),           one(0170770),           "QdDs"},
+{"asrw",       one(0160140),           one(0170770),           "DdDs"},
+{"asrw",       one(0160300),           one(0177700),           "~s"},  /* Shift memory */
+
+{"bhi",                one(0061000),           one(0177400),           "Bg"},
+{"bls",                one(0061400),           one(0177400),           "Bg"},
+{"bcc",                one(0062000),           one(0177400),           "Bg"},
+{"bcs",                one(0062400),           one(0177400),           "Bg"},
+{"bne",                one(0063000),           one(0177400),           "Bg"},
+{"beq",                one(0063400),           one(0177400),           "Bg"},
+{"bvc",                one(0064000),           one(0177400),           "Bg"},
+{"bvs",                one(0064400),           one(0177400),           "Bg"},
+{"bpl",                one(0065000),           one(0177400),           "Bg"},
+{"bmi",                one(0065400),           one(0177400),           "Bg"},
+{"bge",                one(0066000),           one(0177400),           "Bg"},
+{"blt",                one(0066400),           one(0177400),           "Bg"},
+{"bgt",                one(0067000),           one(0177400),           "Bg"},
+{"ble",                one(0067400),           one(0177400),           "Bg"},
+
+{"bchg",       one(0000500),           one(0170700),           "Dd$s"},
+{"bchg",       one(0004100),           one(0177700),           "#b$s"},
+{"bclr",       one(0000600),           one(0170700),           "Dd$s"},
+{"bclr",       one(0004200),           one(0177700),           "#b$s"},
+{"bfchg",      two(0165300, 0),        two(0177700, 0170000),  "?sO2O3"},
+{"bfclr",      two(0166300, 0),        two(0177700, 0170000),  "?sO2O3"},
+{"bfexts",     two(0165700, 0),        two(0177700, 0100000),  "/sO2O3D1"},
+{"bfextu",     two(0164700, 0),        two(0177700, 0100000),  "/sO2O3D1"},
+{"bfffo",      two(0166700, 0),        two(0177700, 0100000),  "/sO2O3D1"},
+{"bfins",      two(0167700, 0),        two(0177700, 0100000),  "D1?sO2O3"},
+{"bfset",      two(0167300, 0),        two(0177700, 0170000),  "?sO2O3"},
+{"bftst",      two(0164300, 0),        two(0177700, 0170000),  "/sO2O3"},
+{"bset",       one(0000700),           one(0170700),           "Dd$s"},
+{"bset",       one(0004300),           one(0177700),           "#b$s"},
+{"btst",       one(0000400),           one(0170700),           "Dd@s"},
+{"btst",       one(0004000),           one(0177700),           "#b@s"},
+
+{"bkpt",       one(0044110),           one(0177770),           "Qs"},
+{"bra",                one(0060000),           one(0177400),           "Bg"},
+{"bsr",                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 */
+{"casb",       two(0005300, 0),        two(0177700, 0177070),  "D3D2~s"},
+{"casl",       two(0007300, 0),        two(0177700, 0177070),  "D3D2~s"},
+{"casw",       two(0006300, 0),        two(0177700, 0177070),  "D3D2~s"},
+
+/*  {"chk",    one(0040600),           one(0170700),           ";wDd"}, JF FOO this looks wrong */
+{"chk2b",      two(0000300, 0004000),  two(0177700, 07777),    "!sR1"},
+{"chk2l",      two(0002300, 0004000),  two(0177700, 07777),    "!sR1"},
+{"chk2w",      two(0001300, 0004000),  two(0177700, 07777),    "!sR1"},
+{"chkl",       one(0040400),           one(0170700),           ";lDd"},
+{"chkw",       one(0040600),           one(0170700),           ";wDd"},
+{"clrb",       one(0041000),           one(0177700),           "$s"},
+{"clrl",       one(0041200),           one(0177700),           "$s"},
+{"clrw",       one(0041100),           one(0177700),           "$s"},
+
+{"cmp2b",      two(0000300, 0),        two(0177700, 07777),    "!sR1"},
+{"cmp2l",      two(0002300, 0),        two(0177700, 07777),    "!sR1"},
+{"cmp2w",      two(0001300, 0),        two(0177700, 07777),    "!sR1"},
+{"cmpal",      one(0130700),           one(0170700),           "*lAd"},
+{"cmpaw",      one(0130300),           one(0170700),           "*wAd"},
+{"cmpib",      one(0006000),           one(0177700),           "#b;b"},
+{"cmpil",      one(0006200),           one(0177700),           "#l;l"},
+{"cmpiw",      one(0006100),           one(0177700),           "#w;w"},
+{"cmpb",       one(0006000),           one(0177700),           "#b;b"},        /* cmpi written as cmp */
+{"cmpb",       one(0130000),           one(0170700),           ";bDd"},
+{"cmpw",       one(0006100),           one(0177700),           "#w;w"},
+{"cmpw",       one(0130100),           one(0170700),           "*wDd"},
+{"cmpw",       one(0130300),           one(0170700),           "*wAd"},        /* cmpa written as cmp */
+{"cmpl",       one(0006200),           one(0177700),           "#l;l"},
+{"cmpl",       one(0130200),           one(0170700),           "*lDd"},
+{"cmpl",       one(0130700),           one(0170700),           "*lAd"},
+{"cmpmb",      one(0130410),           one(0170770),           "+s+d"},
+{"cmpml",      one(0130610),           one(0170770),           "+s+d"},
+{"cmpmw",      one(0130510),           one(0170770),           "+s+d"},
+
+{"dbcc",       one(0052310),           one(0177770),           "DsBw"},
+{"dbcs",       one(0052710),           one(0177770),           "DsBw"},
+{"dbeq",       one(0053710),           one(0177770),           "DsBw"},
+{"dbf",                one(0050710),           one(0177770),           "DsBw"},
+{"dbge",       one(0056310),           one(0177770),           "DsBw"},
+{"dbgt",       one(0057310),           one(0177770),           "DsBw"},
+{"dbhi",       one(0051310),           one(0177770),           "DsBw"},
+{"dble",       one(0057710),           one(0177770),           "DsBw"},
+{"dbls",       one(0051710),           one(0177770),           "DsBw"},
+{"dblt",       one(0056710),           one(0177770),           "DsBw"},
+{"dbmi",       one(0055710),           one(0177770),           "DsBw"},
+{"dbne",       one(0053310),           one(0177770),           "DsBw"},
+{"dbpl",       one(0055310),           one(0177770),           "DsBw"},
+{"dbra",       one(0050710),           one(0177770),           "DsBw"},
+{"dbt",                one(0050310),           one(0177770),           "DsBw"},
+{"dbvc",       one(0054310),           one(0177770),           "DsBw"},
+{"dbvs",       one(0054710),           one(0177770),           "DsBw"},
+
+{"divsl",      two(0046100, 0006000),  two(0177700, 0107770),  ";lD3D1"},
+{"divsl",      two(0046100, 0004000),  two(0177700, 0107770),  ";lDD"},
+{"divsll",     two(0046100, 0004000),  two(0177700, 0107770),  ";lD3D1"},
+{"divsw",      one(0100700),           one(0170700),           ";wDd"},
+{"divs",       one(0100700),           one(0170700),           ";wDd"},
+{"divul",      two(0046100, 0002000),  two(0177700, 0107770),  ";lD3D1"},
+{"divul",      two(0046100, 0000000),  two(0177700, 0107770),  ";lDD"},
+{"divull",     two(0046100, 0000000),  two(0177700, 0107770),  ";lD3D1"},
+{"divuw",      one(0100300),           one(0170700),           ";wDd"},
+{"divu",       one(0100300),           one(0170700),           ";wDd"},
+{"eorb",       one(0005000),           one(0177700),           "#b$s"},        /* eori written as or */
+{"eorb",       one(0005074),           one(0177777),           "#bCs"},        /* eori to ccr */
+{"eorb",       one(0130400),           one(0170700),           "Dd$s"},        /* register to memory */
+{"eorib",      one(0005000),           one(0177700),           "#b$s"},
+{"eorib",      one(0005074),           one(0177777),           "#bCs"},        /* eori to ccr */
+{"eoril",      one(0005200),           one(0177700),           "#l$s"},
+{"eoriw",      one(0005100),           one(0177700),           "#w$s"},
+{"eoriw",      one(0005174),           one(0177777),           "#wSs"},        /* eori to sr */
+{"eorl",       one(0005200),           one(0177700),           "#l$s"},
+{"eorl",       one(0130600),           one(0170700),           "Dd$s"},
+{"eorw",       one(0005100),           one(0177700),           "#w$s"},
+{"eorw",       one(0005174),           one(0177777),           "#wSs"},        /* eori to sr */
+{"eorw",       one(0130500),           one(0170700),           "Dd$s"},
+
+{"exg",                one(0140500),           one(0170770),           "DdDs"},
+{"exg",                one(0140510),           one(0170770),           "AdAs"},
+{"exg",                one(0140610),           one(0170770),           "DdAs"},
+{"exg",                one(0140610),           one(0170770),           "AsDd"},
+
+{"extw",       one(0044200),           one(0177770),           "Ds"},
+{"extl",       one(0044300),           one(0177770),           "Ds"},
+{"extbl",      one(0044700),           one(0177770),           "Ds"},
+{"extb.l",     one(0044700),           one(0177770),           "Ds"},  /* Not sure we should support this one*/
+
+{"illegal",    one(0045374),           one(0177777),           ""},
+{"jmp",                one(0047300),           one(0177700),           "!s"},
+{"jsr",                one(0047200),           one(0177700),           "!s"},
+{"lea",                one(0040700),           one(0170700),           "!sAd"},
+{"linkw",      one(0047120),           one(0177770),           "As#w"},
+{"linkl",      one(0044010),           one(0177770),           "As#l"},
+{"link",       one(0047120),           one(0177770),           "As#w"},
+{"link",       one(0044010),           one(0177770),           "As#l"},
+
+{"lslb",       one(0160410),           one(0170770),           "QdDs"},        /* lsrb #Q,     Ds */
+{"lslb",       one(0160450),           one(0170770),           "DdDs"},        /* lsrb Dd,     Ds */
+{"lslw",       one(0160510),           one(0170770),           "QdDs"},        /* lsrb #Q,     Ds */
+{"lslw",       one(0160550),           one(0170770),           "DdDs"},        /* lsrb Dd,     Ds */
+{"lslw",       one(0161700),           one(0177700),           "~s"},  /* Shift memory */
+{"lsll",       one(0160610),           one(0170770),           "QdDs"},        /* lsrb #Q,     Ds */
+{"lsll",       one(0160650),           one(0170770),           "DdDs"},        /* lsrb Dd,     Ds */
+
+{"lsrb",       one(0160010),           one(0170770),           "QdDs"} /* lsrb #Q,     Ds */,
+{"lsrb",       one(0160050),           one(0170770),           "DdDs"},        /* lsrb Dd,     Ds */
+{"lsrl",       one(0160210),           one(0170770),           "QdDs"},        /* lsrb #Q,     Ds */
+{"lsrl",       one(0160250),           one(0170770),           "DdDs"},        /* lsrb #Q,     Ds */
+{"lsrw",       one(0160110),           one(0170770),           "QdDs"},        /* lsrb #Q,     Ds */
+{"lsrw",       one(0160150),           one(0170770),           "DdDs"},        /* lsrb #Q,     Ds */
+{"lsrw",       one(0161300),           one(0177700),           "~s"},  /* Shift memory */
+
+{"moveal",     one(0020100),           one(0170700),           "*lAd"},
+{"moveaw",     one(0030100),           one(0170700),           "*wAd"},
+{"moveb",      one(0010000),           one(0170000),           ";b$d"},        /* move */
+
+{"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 */
+
+{"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. */
+
+{"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. */
+{"movemw",     one(0046230),           one(0177770),           "+s#w"},        /* movem autoinc to reg. */
+
+{"movepl",     one(0000510),           one(0170770),           "dsDd"},        /* memory to register */
+{"movepl",     one(0000710),           one(0170770),           "Ddds"},        /* register to memory */
+{"movepw",     one(0000410),           one(0170770),           "dsDd"},        /* memory to register */
+{"movepw",     one(0000610),           one(0170770),           "Ddds"},        /* register to memory */
+{"moveq",      one(0070000),           one(0170400),           "MsDd"},
+{"movew",      one(0030000),           one(0170000),           "*w$d"},
+{"movew",      one(0030100),           one(0170700),           "*wAd"},        /* movea,       written as move */
+{"movew",      one(0040300),           one(0177700),           "Ss$s"},        /* Move from sr */
+{"movew",      one(0041300),           one(0177700),           "Cs$s"},        /* Move from ccr */
+{"movew",      one(0042300),           one(0177700),           ";wCd"},        /* move to ccr */
+{"movew",      one(0043300),           one(0177700),           ";wSd"},        /* move to sr */
+
+{"movesb",     two(0007000, 0),        two(0177700, 07777),    "~sR1"},         /* moves from memory */
+{"movesb",     two(0007000, 04000),    two(0177700, 07777),    "R1~s"},         /* moves to memory */
+{"movesl",     two(0007200, 0),        two(0177700, 07777),    "~sR1"},         /* moves from memory */
+{"movesl",     two(0007200, 04000),    two(0177700, 07777),    "R1~s"},         /* moves to memory */
+{"movesw",     two(0007100, 0),        two(0177700, 07777),    "~sR1"},         /* moves from memory */
+{"movesw",     two(0007100, 04000),    two(0177700, 07777),    "R1~s"},         /* moves to memory */
+
+{"mulsl",      two(0046000, 004000),   two(0177700, 0107770),  ";lD1"},
+{"mulsl",      two(0046000, 006000),   two(0177700, 0107770),  ";lD3D1"},
+{"mulsw",      one(0140700),           one(0170700),           ";wDd"},
+{"muls",       one(0140700),           one(0170700),           ";wDd"},
+{"mulul",      two(0046000, 000000),   two(0177700, 0107770),  ";lD1"},
+{"mulul",      two(0046000, 002000),   two(0177700, 0107770),  ";lD3D1"},
+{"muluw",      one(0140300),           one(0170700),           ";lDd"},
+{"mulu",       one(0140300),           one(0170700),           ";lDd"},
+{"nbcd",       one(0044000),           one(0177700),           "$s"},
+{"negb",       one(0042000),           one(0177700),           "$s"},
+{"negl",       one(0042200),           one(0177700),           "$s"},
+{"negw",       one(0042100),           one(0177700),           "$s"},
+{"negxb",      one(0040000),           one(0177700),           "$s"},
+{"negxl",      one(0040200),           one(0177700),           "$s"},
+{"negxw",      one(0040100),           one(0177700),           "$s"},
+{"nop",                one(0047161),           one(0177777),           ""},
+{"notb",       one(0043000),           one(0177700),           "$s"},
+{"notl",       one(0043200),           one(0177700),           "$s"},
+{"notw",       one(0043100),           one(0177700),           "$s"},
+
+{"orb",                one(0000000),           one(0177700),           "#b$s"},        /* ori written as or */
+{"orb",                one(0000074),           one(0177777),           "#bCs"},        /* ori to ccr */
+{"orb",                one(0100000),           one(0170700),           ";bDd"},        /* memory to register */
+{"orb",                one(0100400),           one(0170700),           "Dd~s"},        /* register to memory */
+{"orib",       one(0000000),           one(0177700),           "#b$s"},
+{"orib",       one(0000074),           one(0177777),           "#bCs"},        /* ori to ccr */
+{"oril",       one(0000200),           one(0177700),           "#l$s"},
+{"oriw",       one(0000100),           one(0177700),           "#w$s"},
+{"oriw",       one(0000174),           one(0177777),           "#wSs"},        /* ori to sr */
+{"orl",                one(0000200),           one(0177700),           "#l$s"},
+{"orl",                one(0100200),           one(0170700),           ";lDd"},        /* memory to register */
+{"orl",                one(0100600),           one(0170700),           "Dd~s"},        /* register to memory */
+{"orw",                one(0000100),           one(0177700),           "#w$s"},
+{"orw",                one(0000174),           one(0177777),           "#wSs"},        /* ori to sr */
+{"orw",                one(0100100),           one(0170700),           ";wDd"},        /* memory to register */
+{"orw",                one(0100500),           one(0170700),           "Dd~s"},        /* register to memory */
+
+{"pack",       one(0100500),           one(0170770),           "DsDd#w"},      /* pack Ds,     Dd,     #w */
+{"pack",       one(0100510),           one(0170770),           "-s-d#w"},      /* pack -(As),  -(Ad),  #w */
+{"pea",                one(0044100),           one(0177700),           "!s"},
+{"reset",      one(0047160),           one(0177777),           ""},
+
+{"rolb",       one(0160430),           one(0170770),           "QdDs"},        /* rorb #Q,     Ds */
+{"rolb",       one(0160470),           one(0170770),           "DdDs"},        /* rorb Dd,     Ds */
+{"roll",       one(0160630),           one(0170770),           "QdDs"},        /* rorb #Q,     Ds */
+{"roll",       one(0160670),           one(0170770),           "DdDs"},        /* rorb Dd,     Ds */
+{"rolw",       one(0160530),           one(0170770),           "QdDs"},        /* rorb #Q,     Ds */
+{"rolw",       one(0160570),           one(0170770),           "DdDs"},        /* rorb Dd,     Ds */
+{"rolw",       one(0163700),           one(0177700),           "~s"},  /* Rotate memory */
+{"rorb",       one(0160030),           one(0170770),           "QdDs"},        /* rorb #Q,     Ds */
+{"rorb",       one(0160070),           one(0170770),           "DdDs"},        /* rorb Dd,     Ds */
+{"rorl",       one(0160230),           one(0170770),           "QdDs"},        /* rorb #Q,     Ds */
+{"rorl",       one(0160270),           one(0170770),           "DdDs"},        /* rorb Dd,     Ds */
+{"rorw",       one(0160130),           one(0170770),           "QdDs"},        /* rorb #Q,     Ds */
+{"rorw",       one(0160170),           one(0170770),           "DdDs"},        /* rorb Dd,     Ds */
+{"rorw",       one(0163300),           one(0177700),           "~s"},  /* Rotate memory */
+
+{"roxlb",      one(0160420),           one(0170770),           "QdDs"},        /* roxrb #Q,    Ds */
+{"roxlb",      one(0160460),           one(0170770),           "DdDs"},        /* roxrb Dd,    Ds */
+{"roxll",      one(0160620),           one(0170770),           "QdDs"},        /* roxrb #Q,    Ds */
+{"roxll",      one(0160660),           one(0170770),           "DdDs"},        /* roxrb Dd,    Ds */
+{"roxlw",      one(0160520),           one(0170770),           "QdDs"},        /* roxrb #Q,    Ds */
+{"roxlw",      one(0160560),           one(0170770),           "DdDs"},        /* roxrb Dd,    Ds */
+{"roxlw",      one(0162700),           one(0177700),           "~s"},  /* Rotate memory */
+{"roxrb",      one(0160020),           one(0170770),           "QdDs"},        /* roxrb #Q,    Ds */
+{"roxrb",      one(0160060),           one(0170770),           "DdDs"},        /* roxrb Dd,    Ds */
+{"roxrl",      one(0160220),           one(0170770),           "QdDs"},        /* roxrb #Q,    Ds */
+{"roxrl",      one(0160260),           one(0170770),           "DdDs"},        /* roxrb Dd,    Ds */
+{"roxrw",      one(0160120),           one(0170770),           "QdDs"},        /* roxrb #Q,    Ds */
+{"roxrw",      one(0160160),           one(0170770),           "DdDs"},        /* roxrb Dd,    Ds */
+{"roxrw",      one(0162300),           one(0177700),           "~s"},  /* Rotate memory */
+
+{"rtd",                one(0047164),           one(0177777),           "#w"},
+{"rte",                one(0047163),           one(0177777),           ""},
+{"rtm",                one(0003300),           one(0177760),           "Rs"},
+{"rtr",                one(0047167),           one(0177777),           ""},
+{"rts",                one(0047165),           one(0177777),           ""},
+
+{"scc",                one(0052300),           one(0177700),           "$s"},
+{"scs",                one(0052700),           one(0177700),           "$s"},
+{"seq",                one(0053700),           one(0177700),           "$s"},
+{"sf",         one(0050700),           one(0177700),           "$s"},
+{"sge",                one(0056300),           one(0177700),           "$s"},
+{"sgt",                one(0057300),           one(0177700),           "$s"},
+{"shi",                one(0051300),           one(0177700),           "$s"},
+{"sle",                one(0057700),           one(0177700),           "$s"},
+{"sls",                one(0051700),           one(0177700),           "$s"},
+{"slt",                one(0056700),           one(0177700),           "$s"},
+{"smi",                one(0055700),           one(0177700),           "$s"},
+{"sne",                one(0053300),           one(0177700),           "$s"},
+{"spl",                one(0055300),           one(0177700),           "$s"},
+{"st",         one(0050300),           one(0177700),           "$s"},
+{"svc",                one(0054300),           one(0177700),           "$s"},
+{"svs",                one(0054700),           one(0177700),           "$s"},
+
+{"sbcd",       one(0100400),           one(0170770),           "DsDd"},
+{"sbcd",       one(0100410),           one(0170770),           "-s-d"},
+{"stop",       one(0047162),           one(0177777),           "#w"},
+
+{"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,     ?? */
+{"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(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(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"},
+{"subxl",      one(0110610),           one(0170770),           "-s-d"},
+{"subxw",      one(0110500),           one(0170770),           "DsDd"},
+{"subxw",      one(0110510),           one(0170770),           "-s-d"},
+
+{"swap",       one(0044100),           one(0177770),           "Ds"},
+       
+{"tas",                one(0045300),           one(0177700),           "$s"},
+{"trap",       one(0047100),           one(0177760),           "Ts"},
+
+{"trapcc",     one(0052374),           one(0177777),           ""},
+{"trapcs",     one(0052774),           one(0177777),           ""},
+{"trapeq",     one(0053774),           one(0177777),           ""},
+{"trapf",      one(0050774),           one(0177777),           ""},
+{"trapge",     one(0056374),           one(0177777),           ""},
+{"trapgt",     one(0057374),           one(0177777),           ""},
+{"traphi",     one(0051374),           one(0177777),           ""},
+{"traple",     one(0057774),           one(0177777),           ""},
+{"trapls",     one(0051774),           one(0177777),           ""},
+{"traplt",     one(0056774),           one(0177777),           ""},
+{"trapmi",     one(0055774),           one(0177777),           ""},
+{"trapne",     one(0053374),           one(0177777),           ""},
+{"trappl",     one(0055374),           one(0177777),           ""},
+{"trapt",      one(0050374),           one(0177777),           ""},
+{"trapvc",     one(0054374),           one(0177777),           ""},
+{"trapvs",     one(0054774),           one(0177777),           ""},
+
+{"trapcc.w",   one(0052372),           one(0177777),           ""},
+{"trapcs.w",   one(0052772),           one(0177777),           ""},
+{"trapeq.w",   one(0053772),           one(0177777),           ""},
+{"trapf.w",    one(0050772),           one(0177777),           ""},
+{"trapge.w",   one(0056372),           one(0177777),           ""},
+{"trapgt.w",   one(0057372),           one(0177777),           ""},
+{"traphi.w",   one(0051372),           one(0177777),           ""},
+{"traple.w",   one(0057772),           one(0177777),           ""},
+{"trapls.w",   one(0051772),           one(0177777),           ""},
+{"traplt.w",   one(0056772),           one(0177777),           ""},
+{"trapmi.w",   one(0055772),           one(0177777),           ""},
+{"trapne.w",   one(0053372),           one(0177777),           ""},
+{"trappl.w",   one(0055372),           one(0177777),           ""},
+{"trapt.w",    one(0050372),           one(0177777),           ""},
+{"trapvc.w",   one(0054372),           one(0177777),           ""},
+{"trapvs.w",   one(0054772),           one(0177777),           ""},
+
+{"trapcc.l",   one(0052373),           one(0177777),           ""},
+{"trapcs.l",   one(0052773),           one(0177777),           ""},
+{"trapeq.l",   one(0053773),           one(0177777),           ""},
+{"trapf.l",    one(0050773),           one(0177777),           ""},
+{"trapge.l",   one(0056373),           one(0177777),           ""},
+{"trapgt.l",   one(0057373),           one(0177777),           ""},
+{"traphi.l",   one(0051373),           one(0177777),           ""},
+{"traple.l",   one(0057773),           one(0177777),           ""},
+{"trapls.l",   one(0051773),           one(0177777),           ""},
+{"traplt.l",   one(0056773),           one(0177777),           ""},
+{"trapmi.l",   one(0055773),           one(0177777),           ""},
+{"trapne.l",   one(0053373),           one(0177777),           ""},
+{"trappl.l",   one(0055373),           one(0177777),           ""},
+{"trapt.l",    one(0050373),           one(0177777),           ""},
+{"trapvc.l",   one(0054373),           one(0177777),           ""},
+{"trapvs.l",   one(0054773),           one(0177777),           ""},
+
+{"trapv",      one(0047166),           one(0177777),           ""},
+
+{"tstb",       one(0045000),           one(0177700),           ";b"},
+{"tstw",       one(0045100),           one(0177700),           "*w"},
+{"tstl",       one(0045200),           one(0177700),           "*l"},
+
+{"unlk",       one(0047130),           one(0177770),           "As"},
+{"unpk",       one(0100600),           one(0170770),           "DsDd#w"},
+{"unpk",       one(0100610),           one(0170770),           "-s-d#w"},
+       /* JF floating pt stuff moved down here */
+
+{"fabsb",      two(0xF000, 0x5818),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fabsd",      two(0xF000, 0x5418),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fabsl",      two(0xF000, 0x4018),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fabsp",      two(0xF000, 0x4C18),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fabss",      two(0xF000, 0x4418),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fabsw",      two(0xF000, 0x5018),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fabsx",      two(0xF000, 0x0018),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fabsx",      two(0xF000, 0x4818),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fabsx",      two(0xF000, 0x0018),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"facosb",     two(0xF000, 0x581C),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"facosd",     two(0xF000, 0x541C),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"facosl",     two(0xF000, 0x401C),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"facosp",     two(0xF000, 0x4C1C),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"facoss",     two(0xF000, 0x441C),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"facosw",     two(0xF000, 0x501C),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"facosx",     two(0xF000, 0x001C),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"facosx",     two(0xF000, 0x481C),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"facosx",     two(0xF000, 0x001C),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"faddb",      two(0xF000, 0x5822),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"faddd",      two(0xF000, 0x5422),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"faddl",      two(0xF000, 0x4022),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"faddp",      two(0xF000, 0x4C22),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fadds",      two(0xF000, 0x4422),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"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"},
+
+{"fasinb",     two(0xF000, 0x580C),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fasind",     two(0xF000, 0x540C),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fasinl",     two(0xF000, 0x400C),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fasinp",     two(0xF000, 0x4C0C),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fasins",     two(0xF000, 0x440C),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fasinw",     two(0xF000, 0x500C),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fasinx",     two(0xF000, 0x000C),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fasinx",     two(0xF000, 0x480C),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fasinx",     two(0xF000, 0x000C),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fatanb",     two(0xF000, 0x580A),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fatand",     two(0xF000, 0x540A),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fatanl",     two(0xF000, 0x400A),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fatanp",     two(0xF000, 0x4C0A),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fatans",     two(0xF000, 0x440A),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fatanw",     two(0xF000, 0x500A),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fatanx",     two(0xF000, 0x000A),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fatanx",     two(0xF000, 0x480A),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fatanx",     two(0xF000, 0x000A),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fatanhb",    two(0xF000, 0x580D),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fatanhd",    two(0xF000, 0x540D),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fatanhl",    two(0xF000, 0x400D),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fatanhp",    two(0xF000, 0x4C0D),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fatanhs",    two(0xF000, 0x440D),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fatanhw",    two(0xF000, 0x500D),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fatanhx",    two(0xF000, 0x000D),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fatanhx",    two(0xF000, 0x480D),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fatanhx",    two(0xF000, 0x000D),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fbeq",       one(0xF081),            one(0xF1FF),            "IdBc"},
+{"fbf",                one(0xF080),            one(0xF1FF),            "IdBc"},
+{"fbge",       one(0xF093),            one(0xF1FF),            "IdBc"},
+{"fbgl",       one(0xF096),            one(0xF1FF),            "IdBc"},
+{"fbgle",      one(0xF097),            one(0xF1FF),            "IdBc"},
+{"fbgt",       one(0xF092),            one(0xF1FF),            "IdBc"},
+{"fble",       one(0xF095),            one(0xF1FF),            "IdBc"},
+{"fblt",       one(0xF094),            one(0xF1FF),            "IdBc"},
+{"fbne",       one(0xF08E),            one(0xF1FF),            "IdBc"},
+{"fbnge",      one(0xF09C),            one(0xF1FF),            "IdBc"},
+{"fbngl",      one(0xF099),            one(0xF1FF),            "IdBc"},
+{"fbngle",     one(0xF098),            one(0xF1FF),            "IdBc"},
+{"fbngt",      one(0xF09D),            one(0xF1FF),            "IdBc"},
+{"fbnle",      one(0xF09A),            one(0xF1FF),            "IdBc"},
+{"fbnlt",      one(0xF09B),            one(0xF1FF),            "IdBc"},
+{"fboge",      one(0xF083),            one(0xF1FF),            "IdBc"},
+{"fbogl",      one(0xF086),            one(0xF1FF),            "IdBc"},
+{"fbogt",      one(0xF082),            one(0xF1FF),            "IdBc"},
+{"fbole",      one(0xF085),            one(0xF1FF),            "IdBc"},
+{"fbolt",      one(0xF084),            one(0xF1FF),            "IdBc"},
+{"fbor",       one(0xF087),            one(0xF1FF),            "IdBc"},
+{"fbseq",      one(0xF091),            one(0xF1FF),            "IdBc"},
+{"fbsf",       one(0xF090),            one(0xF1FF),            "IdBc"},
+{"fbsne",      one(0xF09E),            one(0xF1FF),            "IdBc"},
+{"fbst",       one(0xF09F),            one(0xF1FF),            "IdBc"},
+{"fbt",                one(0xF08F),            one(0xF1FF),            "IdBc"},
+{"fbueq",      one(0xF089),            one(0xF1FF),            "IdBc"},
+{"fbuge",      one(0xF08B),            one(0xF1FF),            "IdBc"},
+{"fbugt",      one(0xF08A),            one(0xF1FF),            "IdBc"},
+{"fbule",      one(0xF08D),            one(0xF1FF),            "IdBc"},
+{"fbult",      one(0xF08C),            one(0xF1FF),            "IdBc"},
+{"fbun",       one(0xF088),            one(0xF1FF),            "IdBc"},
+
+{"fcmpb",      two(0xF000, 0x5838),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fcmpd",      two(0xF000, 0x5438),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fcmpl",      two(0xF000, 0x4038),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fcmpp",      two(0xF000, 0x4C38),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fcmps",      two(0xF000, 0x4438),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"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"},
+
+{"fcosb",      two(0xF000, 0x581D),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fcosd",      two(0xF000, 0x541D),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fcosl",      two(0xF000, 0x401D),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fcosp",      two(0xF000, 0x4C1D),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fcoss",      two(0xF000, 0x441D),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fcosw",      two(0xF000, 0x501D),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fcosx",      two(0xF000, 0x001D),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fcosx",      two(0xF000, 0x481D),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fcosx",      two(0xF000, 0x001D),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fcoshb",     two(0xF000, 0x5819),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fcoshd",     two(0xF000, 0x5419),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fcoshl",     two(0xF000, 0x4019),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fcoshp",     two(0xF000, 0x4C19),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fcoshs",     two(0xF000, 0x4419),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fcoshw",     two(0xF000, 0x5019),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fcoshx",     two(0xF000, 0x0019),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fcoshx",     two(0xF000, 0x4819),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fcoshx",     two(0xF000, 0x0019),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fdbeq",      two(0xF048, 0x0001),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbf",       two(0xF048, 0x0000),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbge",      two(0xF048, 0x0013),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbgl",      two(0xF048, 0x0016),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbgle",     two(0xF048, 0x0017),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbgt",      two(0xF048, 0x0012),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdble",      two(0xF048, 0x0015),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdblt",      two(0xF048, 0x0014),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbne",      two(0xF048, 0x000E),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbnge",     two(0xF048, 0x001C),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbngl",     two(0xF048, 0x0019),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbngle",    two(0xF048, 0x0018),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbngt",     two(0xF048, 0x001D),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbnle",     two(0xF048, 0x001A),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbnlt",     two(0xF048, 0x001B),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdboge",     two(0xF048, 0x0003),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbogl",     two(0xF048, 0x0006),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbogt",     two(0xF048, 0x0002),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbole",     two(0xF048, 0x0005),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbolt",     two(0xF048, 0x0004),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbor",      two(0xF048, 0x0007),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbseq",     two(0xF048, 0x0011),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbsf",      two(0xF048, 0x0010),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbsne",     two(0xF048, 0x001E),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbst",      two(0xF048, 0x001F),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbt",       two(0xF048, 0x000F),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbueq",     two(0xF048, 0x0009),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbuge",     two(0xF048, 0x000B),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbugt",     two(0xF048, 0x000A),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbule",     two(0xF048, 0x000D),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbult",     two(0xF048, 0x000C),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbun",      two(0xF048, 0x0008),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+
+{"fdivb",      two(0xF000, 0x5820),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fdivd",      two(0xF000, 0x5420),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fdivl",      two(0xF000, 0x4020),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fdivp",      two(0xF000, 0x4C20),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fdivs",      two(0xF000, 0x4420),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"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"},
+
+{"fetoxb",     two(0xF000, 0x5810),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fetoxd",     two(0xF000, 0x5410),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fetoxl",     two(0xF000, 0x4010),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fetoxp",     two(0xF000, 0x4C10),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fetoxs",     two(0xF000, 0x4410),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fetoxw",     two(0xF000, 0x5010),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fetoxx",     two(0xF000, 0x0010),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fetoxx",     two(0xF000, 0x4810),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fetoxx",     two(0xF000, 0x0010),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fetoxm1b",   two(0xF000, 0x5808),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fetoxm1d",   two(0xF000, 0x5408),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fetoxm1l",   two(0xF000, 0x4008),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fetoxm1p",   two(0xF000, 0x4C08),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fetoxm1s",   two(0xF000, 0x4408),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fetoxm1w",   two(0xF000, 0x5008),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fetoxm1x",   two(0xF000, 0x0008),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fetoxm1x",   two(0xF000, 0x4808),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fetoxm1x",   two(0xF000, 0x0008),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fgetexpb",   two(0xF000, 0x581E),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fgetexpd",   two(0xF000, 0x541E),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fgetexpl",   two(0xF000, 0x401E),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fgetexpp",   two(0xF000, 0x4C1E),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fgetexps",   two(0xF000, 0x441E),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fgetexpw",   two(0xF000, 0x501E),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fgetexpx",   two(0xF000, 0x001E),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fgetexpx",   two(0xF000, 0x481E),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fgetexpx",   two(0xF000, 0x001E),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fgetmanb",   two(0xF000, 0x581F),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fgetmand",   two(0xF000, 0x541F),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fgetmanl",   two(0xF000, 0x401F),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fgetmanp",   two(0xF000, 0x4C1F),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fgetmans",   two(0xF000, 0x441F),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fgetmanw",   two(0xF000, 0x501F),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fgetmanx",   two(0xF000, 0x001F),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fgetmanx",   two(0xF000, 0x481F),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fgetmanx",   two(0xF000, 0x001F),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fintb",      two(0xF000, 0x5801),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fintd",      two(0xF000, 0x5401),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fintl",      two(0xF000, 0x4001),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fintp",      two(0xF000, 0x4C01),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fints",      two(0xF000, 0x4401),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fintw",      two(0xF000, 0x5001),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fintx",      two(0xF000, 0x0001),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fintx",      two(0xF000, 0x4801),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fintx",      two(0xF000, 0x0001),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fintrzb",    two(0xF000, 0x5803),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fintrzd",    two(0xF000, 0x5403),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fintrzl",    two(0xF000, 0x4003),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fintrzp",    two(0xF000, 0x4C03),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fintrzs",    two(0xF000, 0x4403),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fintrzw",    two(0xF000, 0x5003),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fintrzx",    two(0xF000, 0x0003),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fintrzx",    two(0xF000, 0x4803),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fintrzx",    two(0xF000, 0x0003),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"flog10b",    two(0xF000, 0x5815),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"flog10d",    two(0xF000, 0x5415),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"flog10l",    two(0xF000, 0x4015),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"flog10p",    two(0xF000, 0x4C15),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"flog10s",    two(0xF000, 0x4415),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"flog10w",    two(0xF000, 0x5015),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"flog10x",    two(0xF000, 0x0015),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"flog10x",    two(0xF000, 0x4815),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"flog10x",    two(0xF000, 0x0015),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"flog2b",     two(0xF000, 0x5816),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"flog2d",     two(0xF000, 0x5416),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"flog2l",     two(0xF000, 0x4016),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"flog2p",     two(0xF000, 0x4C16),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"flog2s",     two(0xF000, 0x4416),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"flog2w",     two(0xF000, 0x5016),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"flog2x",     two(0xF000, 0x0016),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"flog2x",     two(0xF000, 0x4816),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"flog2x",     two(0xF000, 0x0016),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"flognb",     two(0xF000, 0x5814),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"flognd",     two(0xF000, 0x5414),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"flognl",     two(0xF000, 0x4014),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"flognp",     two(0xF000, 0x4C14),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"flogns",     two(0xF000, 0x4414),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"flognw",     two(0xF000, 0x5014),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"flognx",     two(0xF000, 0x0014),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"flognx",     two(0xF000, 0x4814),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"flognx",     two(0xF000, 0x0014),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"flognp1b",   two(0xF000, 0x5806),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"flognp1d",   two(0xF000, 0x5406),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"flognp1l",   two(0xF000, 0x4006),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"flognp1p",   two(0xF000, 0x4C06),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"flognp1s",   two(0xF000, 0x4406),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"flognp1w",   two(0xF000, 0x5006),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"flognp1x",   two(0xF000, 0x0006),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"flognp1x",   two(0xF000, 0x4806),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"flognp1x",   two(0xF000, 0x0006),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fmodb",      two(0xF000, 0x5821),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fmodd",      two(0xF000, 0x5421),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fmodl",      two(0xF000, 0x4021),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fmodp",      two(0xF000, 0x4C21),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fmods",      two(0xF000, 0x4421),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"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"},
+
+{"fmoveb",     two(0xF000, 0x5800),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},              /* fmove from <ea> to fp<n> */
+{"fmoveb",     two(0xF000, 0x7800),    two(0xF1C0, 0xFC7F),    "IiF7@b"},              /* fmove from fp<n> to <ea> */
+{"fmoved",     two(0xF000, 0x5400),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},              /* fmove from <ea> to fp<n> */
+{"fmoved",     two(0xF000, 0x7400),    two(0xF1C0, 0xFC7F),    "IiF7@F"},              /* fmove from fp<n> to <ea> */
+{"fmovel",     two(0xF000, 0x4000),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},              /* fmove from <ea> to fp<n> */
+{"fmovel",     two(0xF000, 0x6000),    two(0xF1C0, 0xFC7F),    "IiF7@l"},              /* fmove from fp<n> to <ea> */
+       /* JF for the assembler */
+{"fmovel",     two(0xF000, 0xA000),    two(0xF1C0, 0xE3FF),    "Iis8@s"},
+{"fmovel",     two(0xF000, 0x8000),    two(0xF1C0, 0xE3FF),    "Ii@ss8"},
+/* JF {"fmovep",       two(0xF000, 0x4C00),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},              /* fmove from <ea> to fp<n> */
+{"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 <ea> to fp<n> */
+{"fmoves",     two(0xF000, 0x6400),    two(0xF1C0, 0xFC7F),    "IiF7@f"},              /* fmove from fp<n> to <ea> */
+{"fmovew",     two(0xF000, 0x5000),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},              /* fmove from <ea> to fp<n> */
+{"fmovew",     two(0xF000, 0x7000),    two(0xF1C0, 0xFC7F),    "IiF7@w"},              /* fmove from fp<n> to <ea> */
+{"fmovex",     two(0xF000, 0x0000),    two(0xF1C0, 0xE07F),    "IiF8F7"},              /* fmove from <ea> to fp<n> */
+{"fmovex",     two(0xF000, 0x4800),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},              /* fmove from <ea> to fp<n> */
+{"fmovex",     two(0xF000, 0x6800),    two(0xF1C0, 0xFC7F),    "IiF7@x"},              /* fmove from fp<n> to <ea> */
+
+               /* 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"},      */
+
+{"fmovecrx",   two(0xF000, 0x5C00),    two(0xF1FF, 0xFC00),    "Ii#CF7"},              /* fmovecr.x #ccc,      FPn */
+{"fmovecr",    two(0xF000, 0x5C00),    two(0xF1FF, 0xFC00),    "Ii#CF7"},
+
+{"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(0xF018, 0xD000),    two(0xF1F8, 0xFF00),    "Id#3+s"},              /* fmovem.x from autoincrement, static and dynamic: */
+{"fmovemx",    two(0xF018, 0xD800),    two(0xF1F8, 0xFF8F),    "IiDk+s"},              /* fmovem.x from autoincrement, static and dynamic: */
+  
+{"fmovemx",    two(0xF000, 0xD000),    two(0xF1C0, 0xFF00),    "Id#3&s"},              /* fmovem.x from control,       static and dynamic: */
+{"fmovemx",    two(0xF000, 0xD800),    two(0xF1C0, 0xFF8F),    "IiDk&s"},              /* fmovem.x from control,       static and dynamic: */
+
+/* fmoveml and fmovel are the same instruction.   This may cause some
+   confusion in the assembler. */
+
+{"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): */
+
+{"fmulb",      two(0xF000, 0x5823),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fmuld",      two(0xF000, 0x5423),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fmull",      two(0xF000, 0x4023),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fmulp",      two(0xF000, 0x4C23),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fmuls",      two(0xF000, 0x4423),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"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"},
+
+{"fnegb",      two(0xF000, 0x581A),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fnegd",      two(0xF000, 0x541A),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fnegl",      two(0xF000, 0x401A),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fnegp",      two(0xF000, 0x4C1A),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fnegs",      two(0xF000, 0x441A),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fnegw",      two(0xF000, 0x501A),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fnegx",      two(0xF000, 0x001A),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fnegx",      two(0xF000, 0x481A),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fnegx",      two(0xF000, 0x001A),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fremb",      two(0xF000, 0x5825),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fremd",      two(0xF000, 0x5425),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"freml",      two(0xF000, 0x4025),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fremp",      two(0xF000, 0x4C25),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"frems",      two(0xF000, 0x4425),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"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"},
+
+{"frestore",   one(0xF140),            one(0xF1C0),            "Id&s"},
+{"frestore",   one(0xF158),            one(0xF1F8),            "Id+s"},
+{"fsave",      one(0xF100),            one(0xF1C0),            "Id&s"},
+{"fsave",      one(0xF120),            one(0xF1F8),            "Id-s"},
+
+{"fsincosb",   two(0xF000, 0x5830),    two(0xF1C0, 0xFC78),    "Ii;bF7FC"},
+{"fsincosd",   two(0xF000, 0x5430),    two(0xF1C0, 0xFC78),    "Ii;FF7FC"},
+{"fsincosl",   two(0xF000, 0x4030),    two(0xF1C0, 0xFC78),    "Ii;lF7FC"},
+{"fsincosp",   two(0xF000, 0x4C30),    two(0xF1C0, 0xFC78),    "Ii;pF7FC"},
+{"fsincoss",   two(0xF000, 0x4430),    two(0xF1C0, 0xFC78),    "Ii;fF7FC"},
+{"fsincosw",   two(0xF000, 0x5030),    two(0xF1C0, 0xFC78),    "Ii;wF7FC"},
+{"fsincosx",   two(0xF000, 0x0030),    two(0xF1C0, 0xE078),    "IiF8F7FC"},
+{"fsincosx",   two(0xF000, 0x4830),    two(0xF1C0, 0xFC78),    "Ii;xF7FC"},
+
+{"fscaleb",    two(0xF000, 0x5826),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fscaled",    two(0xF000, 0x5426),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fscalel",    two(0xF000, 0x4026),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fscalep",    two(0xF000, 0x4C26),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fscales",    two(0xF000, 0x4426),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"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"},
+
+{"fseq",       two(0xF040, 0x0001),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsf",                two(0xF040, 0x0000),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsge",       two(0xF040, 0x0013),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsgl",       two(0xF040, 0x0016),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsgle",      two(0xF040, 0x0017),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsgt",       two(0xF040, 0x0012),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsle",       two(0xF040, 0x0015),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fslt",       two(0xF040, 0x0014),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsne",       two(0xF040, 0x000E),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsnge",      two(0xF040, 0x001C),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsngl",      two(0xF040, 0x0019),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsngle",     two(0xF040, 0x0018),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsngt",      two(0xF040, 0x001D),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsnle",      two(0xF040, 0x001A),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsnlt",      two(0xF040, 0x001B),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsoge",      two(0xF040, 0x0003),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsogl",      two(0xF040, 0x0006),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsogt",      two(0xF040, 0x0002),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsole",      two(0xF040, 0x0005),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsolt",      two(0xF040, 0x0004),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsor",       two(0xF040, 0x0007),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsseq",      two(0xF040, 0x0011),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fssf",       two(0xF040, 0x0010),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fssne",      two(0xF040, 0x001E),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsst",       two(0xF040, 0x001F),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fst",                two(0xF040, 0x000F),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsueq",      two(0xF040, 0x0009),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsuge",      two(0xF040, 0x000B),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsugt",      two(0xF040, 0x000A),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsule",      two(0xF040, 0x000D),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsult",      two(0xF040, 0x000C),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+{"fsun",       two(0xF040, 0x0008),    two(0xF1C0, 0xFFFF),    "Ii@s"},
+
+{"fsgldivb",   two(0xF000, 0x5824),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fsgldivd",   two(0xF000, 0x5424),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fsgldivl",   two(0xF000, 0x4024),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fsgldivp",   two(0xF000, 0x4C24),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fsgldivs",   two(0xF000, 0x4424),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"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"},
+
+{"fsglmulb",   two(0xF000, 0x5827),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fsglmuld",   two(0xF000, 0x5427),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fsglmull",   two(0xF000, 0x4027),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fsglmulp",   two(0xF000, 0x4C27),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fsglmuls",   two(0xF000, 0x4427),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"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"},
+
+{"fsinb",      two(0xF000, 0x580E),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fsind",      two(0xF000, 0x540E),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fsinl",      two(0xF000, 0x400E),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fsinp",      two(0xF000, 0x4C0E),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fsins",      two(0xF000, 0x440E),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fsinw",      two(0xF000, 0x500E),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fsinx",      two(0xF000, 0x000E),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fsinx",      two(0xF000, 0x480E),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fsinx",      two(0xF000, 0x000E),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fsinhb",     two(0xF000, 0x5802),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fsinhd",     two(0xF000, 0x5402),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fsinhl",     two(0xF000, 0x4002),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fsinhp",     two(0xF000, 0x4C02),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fsinhs",     two(0xF000, 0x4402),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fsinhw",     two(0xF000, 0x5002),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fsinhx",     two(0xF000, 0x0002),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fsinhx",     two(0xF000, 0x4802),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fsinhx",     two(0xF000, 0x0002),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fsqrtb",     two(0xF000, 0x5804),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fsqrtd",     two(0xF000, 0x5404),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fsqrtl",     two(0xF000, 0x4004),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fsqrtp",     two(0xF000, 0x4C04),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fsqrts",     two(0xF000, 0x4404),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fsqrtw",     two(0xF000, 0x5004),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fsqrtx",     two(0xF000, 0x0004),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fsqrtx",     two(0xF000, 0x4804),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fsqrtx",     two(0xF000, 0x0004),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fsubb",      two(0xF000, 0x5828),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fsubd",      two(0xF000, 0x5428),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fsubl",      two(0xF000, 0x4028),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fsubp",      two(0xF000, 0x4C28),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fsubs",      two(0xF000, 0x4428),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"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"},
+
+{"ftanb",      two(0xF000, 0x580F),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"ftand",      two(0xF000, 0x540F),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"ftanl",      two(0xF000, 0x400F),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"ftanp",      two(0xF000, 0x4C0F),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"ftans",      two(0xF000, 0x440F),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"ftanw",      two(0xF000, 0x500F),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"ftanx",      two(0xF000, 0x000F),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"ftanx",      two(0xF000, 0x480F),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"ftanx",      two(0xF000, 0x000F),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"ftanhb",     two(0xF000, 0x5809),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"ftanhd",     two(0xF000, 0x5409),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"ftanhl",     two(0xF000, 0x4009),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"ftanhp",     two(0xF000, 0x4C09),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"ftanhs",     two(0xF000, 0x4409),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"ftanhw",     two(0xF000, 0x5009),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"ftanhx",     two(0xF000, 0x0009),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"ftanhx",     two(0xF000, 0x4809),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"ftanhx",     two(0xF000, 0x0009),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"ftentoxb",   two(0xF000, 0x5812),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"ftentoxd",   two(0xF000, 0x5412),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"ftentoxl",   two(0xF000, 0x4012),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"ftentoxp",   two(0xF000, 0x4C12),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"ftentoxs",   two(0xF000, 0x4412),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"ftentoxw",   two(0xF000, 0x5012),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"ftentoxx",   two(0xF000, 0x0012),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"ftentoxx",   two(0xF000, 0x4812),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"ftentoxx",   two(0xF000, 0x0012),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"ftrapeq",    two(0xF07C, 0x0001),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapf",     two(0xF07C, 0x0000),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapge",    two(0xF07C, 0x0013),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapgl",    two(0xF07C, 0x0016),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapgle",   two(0xF07C, 0x0017),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapgt",    two(0xF07C, 0x0012),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftraple",    two(0xF07C, 0x0015),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftraplt",    two(0xF07C, 0x0014),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapne",    two(0xF07C, 0x000E),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapnge",   two(0xF07C, 0x001C),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapngl",   two(0xF07C, 0x0019),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapngle",  two(0xF07C, 0x0018),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapngt",   two(0xF07C, 0x001D),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapnle",   two(0xF07C, 0x001A),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapnlt",   two(0xF07C, 0x001B),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapoge",   two(0xF07C, 0x0003),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapogl",   two(0xF07C, 0x0006),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapogt",   two(0xF07C, 0x0002),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapole",   two(0xF07C, 0x0005),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapolt",   two(0xF07C, 0x0004),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapor",    two(0xF07C, 0x0007),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapseq",   two(0xF07C, 0x0011),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapsf",    two(0xF07C, 0x0010),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapsne",   two(0xF07C, 0x001E),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapst",    two(0xF07C, 0x001F),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapt",     two(0xF07C, 0x000F),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapueq",   two(0xF07C, 0x0009),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapuge",   two(0xF07C, 0x000B),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapugt",   two(0xF07C, 0x000A),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapule",   two(0xF07C, 0x000D),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapult",   two(0xF07C, 0x000C),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapun",    two(0xF07C, 0x0008),    two(0xF1FF, 0xFFFF),    "Ii"},
+        
+{"ftrapeqw",   two(0xF07A, 0x0001),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapfw",    two(0xF07A, 0x0000),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapgew",   two(0xF07A, 0x0013),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapglw",   two(0xF07A, 0x0016),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapglew",  two(0xF07A, 0x0017),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapgtw",   two(0xF07A, 0x0012),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftraplew",   two(0xF07A, 0x0015),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapltw",   two(0xF07A, 0x0014),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapnew",   two(0xF07A, 0x000E),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapngew",  two(0xF07A, 0x001C),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapnglw",  two(0xF07A, 0x0019),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapnglew", two(0xF07A, 0x0018),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapngtw",  two(0xF07A, 0x001D),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapnlew",  two(0xF07A, 0x001A),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapnltw",  two(0xF07A, 0x001B),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapogew",  two(0xF07A, 0x0003),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapoglw",  two(0xF07A, 0x0006),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapogtw",  two(0xF07A, 0x0002),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapolew",  two(0xF07A, 0x0005),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapoltw",  two(0xF07A, 0x0004),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftraporw",   two(0xF07A, 0x0007),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapseqw",  two(0xF07A, 0x0011),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapsfw",   two(0xF07A, 0x0010),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapsnew",  two(0xF07A, 0x001E),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapstw",   two(0xF07A, 0x001F),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftraptw",    two(0xF07A, 0x000F),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapueqw",  two(0xF07A, 0x0009),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapugew",  two(0xF07A, 0x000B),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapugtw",  two(0xF07A, 0x000A),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapulew",  two(0xF07A, 0x000D),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapultw",  two(0xF07A, 0x000C),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapunw",   two(0xF07A, 0x0008),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+
+{"ftrapeql",   two(0xF07B, 0x0001),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapfl",    two(0xF07B, 0x0000),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapgel",   two(0xF07B, 0x0013),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapgll",   two(0xF07B, 0x0016),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapglel",  two(0xF07B, 0x0017),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapgtl",   two(0xF07B, 0x0012),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftraplel",   two(0xF07B, 0x0015),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapltl",   two(0xF07B, 0x0014),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapnel",   two(0xF07B, 0x000E),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapngel",  two(0xF07B, 0x001C),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapngll",  two(0xF07B, 0x0019),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapnglel", two(0xF07B, 0x0018),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapngtl",  two(0xF07B, 0x001D),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapnlel",  two(0xF07B, 0x001A),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapnltl",  two(0xF07B, 0x001B),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapogel",  two(0xF07B, 0x0003),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapogll",  two(0xF07B, 0x0006),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapogtl",  two(0xF07B, 0x0002),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapolel",  two(0xF07B, 0x0005),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapoltl",  two(0xF07B, 0x0004),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftraporl",   two(0xF07B, 0x0007),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapseql",  two(0xF07B, 0x0011),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapsfl",   two(0xF07B, 0x0010),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapsnel",  two(0xF07B, 0x001E),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapstl",   two(0xF07B, 0x001F),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftraptl",    two(0xF07B, 0x000F),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapueql",  two(0xF07B, 0x0009),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapugel",  two(0xF07B, 0x000B),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapugtl",  two(0xF07B, 0x000A),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapulel",  two(0xF07B, 0x000D),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapultl",  two(0xF07B, 0x000C),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapunl",   two(0xF07B, 0x0008),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+
+{"ftstb",      two(0xF000, 0x583A),    two(0xF1C0, 0xFC7F),    "Ii;b"},
+{"ftstd",      two(0xF000, 0x543A),    two(0xF1C0, 0xFC7F),    "Ii;F"},
+{"ftstl",      two(0xF000, 0x403A),    two(0xF1C0, 0xFC7F),    "Ii;l"},
+{"ftstp",      two(0xF000, 0x4C3A),    two(0xF1C0, 0xFC7F),    "Ii;p"},
+{"ftsts",      two(0xF000, 0x443A),    two(0xF1C0, 0xFC7F),    "Ii;f"},
+{"ftstw",      two(0xF000, 0x503A),    two(0xF1C0, 0xFC7F),    "Ii;w"},
+{"ftstx",      two(0xF000, 0x003A),    two(0xF1C0, 0xE07F),    "IiF8"},
+{"ftstx",      two(0xF000, 0x483A),    two(0xF1C0, 0xFC7F),    "Ii;x"},
+
+{"ftwotoxb",   two(0xF000, 0x5811),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"ftwotoxd",   two(0xF000, 0x5411),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"ftwotoxl",   two(0xF000, 0x4011),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"ftwotoxp",   two(0xF000, 0x4C11),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"ftwotoxs",   two(0xF000, 0x4411),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"ftwotoxw",   two(0xF000, 0x5011),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"ftwotoxx",   two(0xF000, 0x0011),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"ftwotoxx",   two(0xF000, 0x4811),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"ftwotoxx",   two(0xF000, 0x0011),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+/* Alternate mnemonics for SUN */
+
+{"jbsr",       one(0060400),           one(0177400),           "Bg"},
+{"jbsr",       one(0047200),           one(0177700),           "!s"},
+{"jra",                one(0060000),           one(0177400),           "Bg"},
+{"jra",                one(0047300),           one(0177700),           "!s"},
+  
+{"jhi",                one(0061000),           one(0177400),           "Bg"},
+{"jls",                one(0061400),           one(0177400),           "Bg"},
+{"jcc",                one(0062000),           one(0177400),           "Bg"},
+{"jcs",                one(0062400),           one(0177400),           "Bg"},
+{"jne",                one(0063000),           one(0177400),           "Bg"},
+{"jeq",                one(0063400),           one(0177400),           "Bg"},
+{"jvc",                one(0064000),           one(0177400),           "Bg"},
+{"jvs",                one(0064400),           one(0177400),           "Bg"},
+{"jpl",                one(0065000),           one(0177400),           "Bg"},
+{"jmi",                one(0065400),           one(0177400),           "Bg"},
+{"jge",                one(0066000),           one(0177400),           "Bg"},
+{"jlt",                one(0066400),           one(0177400),           "Bg"},
+{"jgt",                one(0067000),           one(0177400),           "Bg"},
+{"jle",                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(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 */
+{"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. */
+{"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. */
+{"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 */
+{"movpw",      one(0000610),           one(0170770),           "Ddds"},        /* register to memory */
+{"movq",       one(0070000),           one(0170400),           "MsDd"},
+{"movw",       one(0030000),           one(0170000),           "*w$d"},
+{"movw",       one(0030100),           one(0170700),           "*wAd"},        /* mova,        written as mov */
+{"movw",       one(0040300),           one(0177700),           "Ss$s"},        /* Move from sr */
+{"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"},
+{"movsl",      two(0007200, 0),        two(0177700, 07777),    "~sR1"},
+{"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"},
+};
+
+int numopcodes=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
new file mode 100644 (file)
index 0000000..a22a36a
--- /dev/null
@@ -0,0 +1,773 @@
+/* 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 <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "m68k-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... */
+\f
+/* 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, 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, "<invalid address mode 0%o>", 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]);
+}
+\f
+/* 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.  */
+
+#ifdef mac_aux
+#ifdef __STDC__
+#define        asm16(str)      asm ("short     " str#)
+#else
+#define        asm16(str)      asm ("short     str")
+#endif
+#else
+#ifdef __STDC__
+#define        asm16(str)      asm (".word     " str#)
+#else
+#define        asm16(str)      asm (".word     str")
+#endif
+#endif
+
+convert_from_68881 (from, to)
+     char *from;
+     double *to;
+{
+#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.  */
+  asm16 (020156);
+  asm16 (8);
+  asm16 (021156);
+  asm16 (12);
+  asm16 (0xf210);
+  asm16 (0x4800);
+  asm16 (0xf211);
+  asm16 (0x7400);
+#endif
+}
+
+/* The converse: convert the double *FROM to an extended float
+   and store where TO points.  */
+
+convert_to_68881 (from, to)
+     double *from;
+     char *to;
+{
+#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.  */
+  asm16 (020156);
+  asm16 (8);
+  asm16 (021156);
+  asm16 (12);
+  asm16 (0xf210);
+  asm16 (0x5400);
+  asm16 (0xf211);
+  asm16 (0x6800);
+#endif
+}
diff --git a/gdb/main.c b/gdb/main.c
new file mode 100644 (file)
index 0000000..d6e993e
--- /dev/null
@@ -0,0 +1,1072 @@
+/* Top level 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 <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/param.h>
+#include "defs.h"
+#include "command.h"
+#include "param.h"
+
+#ifdef SET_STACK_LIMIT_HUGE
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+
+/* Version number of GDB, as a string.  */
+
+extern char *version;
+
+/* Chain containing all defined commands.  */
+
+struct cmd_list_element *cmdlist;
+
+/* Chain containing all defined info subcommands.  */
+
+struct cmd_list_element *infolist;
+
+/* stdio stream that command input is being read from.  */
+
+FILE *instream;
+
+/* 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) ();
+
+void free_command_lines ();
+char *read_line ();
+static void initialize_main ();
+void command_loop ();
+static void source_command ();
+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;
+
+return_to_top_level ()
+{
+  quit_flag = 0;
+  immediate_quit = 0;
+  clear_breakpoint_commands ();
+  clear_momentary_breakpoints ();
+  do_cleanups (0);
+  longjmp (to_top_level, 1);
+}
+\f
+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;
+
+#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);
+    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 (argv[i][0] == '-')
+       i++;
+    }
+
+  /* Run the init function of each source file */
+
+  initialize_all_files ();
+  initialize_main ();          /* But that omits this file!  Do it now */
+
+  signal (SIGINT, request_quit);
+  signal (SIGQUIT, SIG_IGN);
+
+  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"))
+           /* 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);
+             /* -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)
+       {
+         if (*p)
+           error ("User-defined commands cannot take command-line arguments: \"%s\"",
+                  p);
+         cmdlines = (struct command_line *) c->function;
+         if (cmdlines == (struct command_line *) 0)
+           /* Null command */
+           return;
+         while (cmdlines)
+           {
+             execute_command (cmdlines->line, 0);
+             cmdlines = cmdlines->next;
+           }
+       }
+      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 (instream == stdin)
+       printf ("%s", prompt);
+      fflush (stdout);
+
+      if (window_hook && instream == stdin)
+       (*window_hook) (instream, prompt);
+
+      quit_flag = 0;
+      old_chain = make_cleanup (do_nothing, 0);
+      execute_command (read_line (instream == stdin), instream == stdin);
+      /* Do any commands attached to breakpoint we stopped at.  */
+      do_breakpoint_commands ();
+      do_cleanups (old_chain);
+    }
+}
+\f
+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;
+}
+
+/* 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 *
+read_line (repeat)
+     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++;
+  signal (SIGTSTP, stop_sig);
+
+  while (1)
+    {
+      c = fgetc (instream);
+      if (c == -1 || c == '\n')
+       break;
+      if (p - line == linesize - 1)
+       {
+         linesize *= 2;
+         nline = (char *) xrealloc (line, linesize);
+         p += nline - line;
+         line = nline;
+       }
+      *p++ = c;
+    }
+
+  signal (SIGTSTP, SIG_DFL);
+  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;
+}
+\f
+/* 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 = read_line (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;
+    }
+}
+\f
+/* Add an element to the list of info subcommands.  */
+
+void
+add_info (name, fun, doc)
+     char *name;
+     void (*fun) ();
+     char *doc;
+{
+  add_cmd (name, 0, 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_cmd (0, infolist, "info ", -1, stdout);
+}
+\f
+/* 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, cmdlist, "", -2, stdout);
+}
+\f
+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 >= '1' && *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);
+
+  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);
+}
+\f
+static void
+copying_info ()
+{
+  immediate_quit++;
+  printf ("                GDB GENERAL PUBLIC LICENSE\n\
+\n\
+ Copyright (C) 1986 Richard M. Stallman\n\
+ Everyone is permitted to copy and distribute verbatim copies\n\
+ of this license, but changing it is not allowed.\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);
+  read_line ();
+
+  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);
+  read_line ();
+
+  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) 1987 Free Software Foundation, Inc.\" (or with the year updated if\n\
+that is 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);
+  read_line ();
+
+  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 third\n\
+    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) 1987 Free Software Foundation, Inc.\" (or with\n\
+    the year updated if appropriate), saying that there\n\
+    is no warranty (or else, saying that you provide\n\
+    a warranty) and that users may redistribute the program under\n\
+    these conditions, and telling the user how to view a copy of\n\
+    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\
+--Type Return to print more--");
+  fflush (stdout);
+  read_line ();
+
+  printf ("\
+  3. You may copy and distribute GDB or any portion of it in\n\
+compiled, executable or object code form under the terms of Paragraphs\n\
+1 and 2 above provided that you do the following:\n\
+\n\
+    a) cause each such copy to be accompanied by the\n\
+    corresponding machine-readable source code, which must\n\
+    be distributed under the terms of Paragraphs 1 and 2 above; or,\n\
+\n\
+    b) cause each such copy to be accompanied by a\n\
+    written offer, with no time limit, to give any third party\n\
+    free (except for a nominal shipping charge) a machine readable\n\
+    copy of the corresponding source code, to be distributed\n\
+    under the terms of Paragraphs 1 and 2 above; or,\n\n");
+
+  printf ("\
+    c) in the case of a recipient of GDB in compiled, executable\n\
+    or object code form (without the corresponding source code) you\n\
+    shall cause copies you distribute to be accompanied by a copy\n\
+    of the written offer of source code which you received along\n\
+    with the copy you received.\n\
+--Type Return to print more--");
+  fflush (stdout);
+  read_line ();
+
+  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\
+  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--;
+}
+\f
+static void
+print_gdb_version ()
+{
+  printf ("GDB %s, Copyright (C) 1987 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--;
+}
+\f
+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;
+}
+\f
+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;
+}
+\f
+static void
+pwd_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  char buf[MAXPATHLEN];
+  if (arg) error ("The \"pwd\" command does not take an argument: %s", arg);
+  printf ("Working directory %s.\n", getwd (buf));
+}
+
+static void
+cd_command (dir, from_tty)
+     char *dir;
+     int from_tty;
+{
+  if (dir == 0)
+    error_no_arg ("new working directory");
+
+  if (chdir (dir) < 0)
+    perror_with_name (dir);
+  if (from_tty)
+    pwd_command ((char *) 0, 1);
+}
+
+\f
+/* Clean up on error during a "source" command.
+   Close the file opened by the command
+   and restore the previous input stream.  */
+
+static void
+source_cleanup (stream)
+     FILE *stream;
+{
+  fclose (instream);
+  instream = stream;
+}
+
+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);
+    }
+}
+
+\f
+static void
+initialize_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_com ("set-prompt", class_support, set_prompt_command,
+          "Change gdb's prompt from the default of \"(gdb)\"");
+  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.");
+}
diff --git a/gdb/ns32k-opcode.h b/gdb/ns32k-opcode.h
new file mode 100644 (file)
index 0000000..2d5ff30
--- /dev/null
@@ -0,0 +1,307 @@
+/* ns32k-opcode.h */
+
+#ifndef ns32k_opcodeT
+#define ns32k_opcodeT int
+#endif /* no ns32k_opcodeT */
+
+struct not_wot                 /* ns32k opcode table: wot to do with this */
+                               /* particular opcode */
+{
+  int obits;           /* number of opcode bits */
+  int ibits;           /* number of instruction bits */
+  ns32k_opcodeT        code;   /* op-code (may be > 8 bits!) */
+  char *args;          /* how to compile said opcode */
+};
+
+struct not                     /* ns32k opcode text */
+{
+  char *            name;      /* opcode name: lowercase string  [key]  */
+  struct not_wot    detail;    /* rest of opcode table          [datum] */
+};
+
+/* F : 32 bit float
+ * L : 64 bit float
+ * B : byte
+ * W : word
+ * D : double-word
+ * Q : quad-word
+ * d : displacement
+ * q : quick
+ * i : immediate (8 bits)
+ * r : register number (3 bits)
+ * p : displacement - pc relative addressing
+*/
+static struct not
+notstrs[] =
+{
+  { "absf",    14,24,  0x35be, "1F2F" },
+  { "absl",    14,24,  0x34be, "1L2L" },
+  { "absb",    14,24,  0x304e, "1B2B" },
+  { "absw",    14,24,  0x314e, "1W2W" },
+  { "absd",    14,24,  0x334e, "1D2D" },
+  { "acbb",     7,16,  0x4c,   "2B1q3p" },
+  { "addf",    14,24,  0x01be, "1F2F" },
+  { "addl",    14,24,  0x00be, "1L2L" },
+  { "addb",     6,16,  0x00,   "1B2B" },
+  { "addw",     6,16,  0x01,   "1W2W" },
+  { "addd",     6,16,  0x03,   "1D2D" },
+  { "addcb",    6,16,  0x10,   "1B2B" },
+  { "addcw",    6,16,  0x11,   "1W2W" },
+  { "addcd",    6,16,  0x13,   "1D2D" },
+  { "addpb",   14,24,  0x3c4e, "1B2B" },
+  { "addpw",   14,24,  0x3d4e, "1W2W" },
+  { "addpd",   14,24,  0x3f4e, "1D2D" },
+  { "addqb",    7,16,  0x0c,   "2B1q" },
+  { "addqw",    7,16,  0x0d,   "2W1q" },
+  { "addqd",    7,16,  0x0f,   "2D1q" },
+  { "addr",     6,16,  0x27,   "1D2D" },
+  { "adjspb",  11,16,  0x057c, "1B" },
+  { "adjspw",  11,16,  0x057d, "1W" },
+  { "adjspd",  11,16,  0x057f, "1D" },
+  { "andb",     6,16,  0x28,   "1B2B" },
+  { "andw",     6,16,  0x29,   "1W2W" },
+  { "andd",     6,16,  0x2b,   "1D2D" },
+  { "ashb",    14,24,  0x044e, "1B2B" },
+  { "ashw",    14,24,  0x054e, "1B2W" },
+  { "ashd",    14,24,  0x074e, "1B2D" },
+  { "beq",      8,8,   0x0a,   "1p" },
+  { "bne",      8,8,   0x1a,   "1p" },
+  { "bcs",      8,8,   0x2a,   "1p" },
+  { "bcc",      8,8,   0x3a,   "1p" },
+  { "bhi",      8,8,   0x4a,   "1p" },
+  { "bls",      8,8,   0x5a,   "1p" },
+  { "bgt",      8,8,   0x6a,   "1p" },
+  { "ble",      8,8,   0x7a,   "1p" },
+  { "bfs",      8,8,   0x8a,   "1p" },
+  { "bfc",      8,8,   0x9a,   "1p" },
+  { "blo",      8,8,   0xaa,   "1p" },
+  { "bhs",      8,8,   0xba,   "1p" },
+  { "blt",      8,8,   0xca,   "1p" },
+  { "bge",      8,8,   0xda,   "1p" },
+  { "bicb",     6,16,  0x08,   "1B2B" },
+  { "bicw",     6,16,  0x09,   "1W2W" },
+  { "bicd",     6,16,  0x0b,   "1D2D" },
+  { "bicpsrb", 11,16,  0x17c,  "1B" },
+  { "bicpsrw", 11,16,  0x17d,  "1W" },
+  { "bispsrb", 11,16,  0x37c,  "1B" },
+  { "bispsrw", 11,16,  0x37d,  "1W" },
+  { "bpt",      8,8,   0xf2,   "" },
+  { "br",       8,8,   0xea,   "1p" },
+  { "bsr",      8,8,   0x02,   "1p" },
+  { "caseb",   11,16,  0x77c,  "1B" },
+  { "casew",   11,16,  0x77d,  "1W" },
+  { "cased",   11,16,  0x77f,  "1D" },
+  { "cbitb",   14,24,  0x084e, "1B2D" },
+  { "cbitw",   14,24,  0x094e, "1W2D" },
+  { "cbitd",   14,24,  0x0b4e, "1D2D" },
+  { "cbitib",  14,24,  0x0c4e, "1B2D" },
+  { "cbitiw",  14,24,  0x0d4e, "1W2D" },
+  { "cbitid",  14,24,  0x0f4e, "1D2D" },
+  { "checkb",  11,24,  0x0ee,  "2A3B1r" },
+  { "checkw",  11,24,  0x1ee,  "2A3B1r" },
+  { "checkd",  11,24,  0x3ee,  "2A3D1r" },
+  { "cmpf",    14,24,  0x09be, "1F2F" },
+  { "cmpl",    14,24,  0x08be, "1L2L" },
+  { "cmpb",     6,16,  0x04,   "1B2B" },
+  { "cmpw",     6,16,  0x05,   "1W2W" },
+  { "cmpd",     6,16,  0x07,   "1D2D" },
+  { "cmpmb",   14,24,  0x04ce, "1D2D3d" },
+  { "cmpmw",   14,24,  0x05ce, "1D2D3d" },
+  { "cmpmd",   14,24,  0x07ce, "1D2D3d" },
+  { "cmpqb",    7,16,  0x1c,   "2B1q" },
+  { "cmpqw",    7,16,  0x1d,   "2W1q" },
+  { "cmpqd",    7,16,  0x1f,   "2D1q" },
+  { "cmpsb",   16,16,  0x040e, "1i" },
+  { "cmpsw",   16,16,  0x050e, "1i" },
+  { "cmpsd",   16,16,  0x070e, "1i" },
+  { "cmpst",   16,16,  0x840e, "1i" },
+  { "comb",    14,24,  0x344e, "1B2B" },
+  { "comw",    14,24,  0x354e, "1W2W" },
+  { "comd",    14,24,  0x374e, "1D2D" },
+  { "cvtp",    11,24,  0x036e, "2D3D1r" },
+  { "cxp",      8,8,   0x22,   "1p" },
+  { "cxpd",    11,16,  0x07f,  "1D" },
+  { "deib",    14,24,  0x2cce, "1B2W" },
+  { "deiw",    14,24,  0x2cce, "1W2D" },
+  { "deid",    14,24,  0x2cce, "1D2Q" },
+  { "dia",      8,8,   0xc2,   "" },
+  { "divf",    14,24,  0x21be, "1F2F" },
+  { "divl",    14,24,  0x20be, "1L2L" },
+  { "divb",    14,24,  0x3cce, "1B2B" },
+  { "divw",    14,24,  0x3dce, "1W2W" },
+  { "divd",    14,24,  0x3fce, "1D2D" },
+  { "enter",    8,8,   0x82,   "1i2d" },
+  { "exit",     8,8,   0x92,   "1i" },
+  { "extb",    11,24,  0x02e,  "2D3B1r4d" },
+  { "extw",    11,24,  0x12e,  "2D3W1r4d" },
+  { "extd",    11,24,  0x32e,  "2D3D1r4d" },
+  { "extsb",   14,24,  0x0cce, "1D2B3i" },
+  { "extsw",   14,24,  0x0dce, "1D2W3i" },
+  { "extsd",   14,24,  0x0fce, "1D2D3i" },
+  { "ffsb",    14,24,  0x046e, "1B2B" },
+  { "ffsw",    14,24,  0x056e, "1W2B" },
+  { "ffsd",    14,24,  0x076e, "1D2B" },
+  { "flag",     8,8,   0xd2,   "" },
+  { "floorfb", 14,24,  0x3c3e, "1F2B" },
+  { "floorfw", 14,24,  0x3d3e, "1F2W" },
+  { "floorfd", 14,24,  0x3f3e, "1F2D" },
+  { "floorlb", 14,24,  0x383e, "1L2B" },
+  { "floorlw", 14,24,  0x393e, "1L2W" },
+  { "floorld", 14,24,  0x3b3e, "1L2D" },
+  { "ibitb",   14,24,  0x384e, "1B2D" },
+  { "ibitw",   14,24,  0x394e, "1W2D" },
+  { "ibitd",   14,24,  0x3b4e, "1D2D" },
+  { "indexb",  11,24,  0x42e,  "2B3B1r" },
+  { "indexw",  11,24,  0x52e,  "2W3W1r" },
+  { "indexd",  11,24,  0x72e,  "2D3D1r" },
+  { "insb",    11,24,  0x0ae,  "2B3B1r4d" },
+  { "insw",    11,24,  0x1ae,  "2W3W1r4d" },
+  { "insd",    11,24,  0x3ae,  "2D3D1r4d" },
+  { "inssb",   14,24,  0x08ce, "1B2D3i" },
+  { "inssw",   14,24,  0x09ce, "1W2D3i" },
+  { "inssd",   14,24,  0x0bce, "1D2D3i" },
+  { "jsr",     11,16,  0x67f,  "1A" },
+  { "jump",    11,16,  0x27f,  "1A" },
+  { "lfsr",    19,24,  0x00f3e,"1D" },
+  { "lmr",     15,24,  0x0b1e, "2D1q" },
+  { "lprb",     7,16,  0x6c,   "2B1q" },
+  { "lprw",     7,16,  0x6d,   "2W1q" },
+  { "lprd",     7,16,  0x6f,   "2D1q" },
+  { "lshb",    14,24,  0x144e, "1B2B" },
+  { "lshw",    14,24,  0x154e, "1B2W" },
+  { "lshd",    14,24,  0x174e, "1B2D" },
+  { "meib",    14,24,  0x24ce, "1B2W" },
+  { "meiw",    14,24,  0x25ce, "1W2D" },
+  { "meid",    14,24,  0x27ce, "1D2Q" },
+  { "modb",    14,24,  0x38ce, "1B2B" },
+  { "modw",    14,24,  0x39ce, "1W2W" },
+  { "modd",    14,24,  0x3bce, "1D2D" },
+  { "movf",    14,24,  0x05be, "1F2F" },
+  { "movl",    14,24,  0x04be, "1L2L" },
+  { "movb",     6,16,  0x14,   "1B2B" },
+  { "movw",     6,16,  0x15,   "1W2W" },
+  { "movd",     6,16,  0x17,   "1D2D" },
+  { "movbf",   14,24,  0x043e, "1B2F" },
+  { "movwf",   14,24,  0x053e, "1W2F" },
+  { "movdf",   14,24,  0x073e, "1D2F" },
+  { "movbl",   14,24,  0x003e, "1B2L" },
+  { "movwl",   14,24,  0x013e, "1W2L" },
+  { "movdl",   14,24,  0x033e, "1D2L" },
+  { "movfl",   14,24,  0x1b3e, "1F2L" },
+  { "movlf",   14,24,  0x163e, "1L2F" },
+  { "movmb",   14,24,  0x00ce, "1D2D3d" },
+  { "movmw",   14,24,  0x00de, "1D2D3d" },
+  { "movmd",   14,24,  0x00fe, "1D2D3d" },
+  { "movqb",    7,16,  0x5c,   "2B1q" },
+  { "movqw",    7,16,  0x5d,   "2B1q" },
+  { "movqd",    7,16,  0x5f,   "2B1q" },
+  { "movsb",   16,16,  0x000e, "1i" },
+  { "movsw",   16,16,  0x010e, "1i" },
+  { "movsd",   16,16,  0x030e, "1i" },
+  { "movst",   16,16,  0x800e, "1i" },
+  { "movsub",  14,24,  0x0cae, "1A1A" },
+  { "movsuw",  14,24,  0x0dae, "1A1A" },
+  { "movsud",  14,24,  0x0fae, "1A1A" },
+  { "movusb",  14,24,  0x1cae, "1A1A" },
+  { "movusw",  14,24,  0x1dae, "1A1A" },
+  { "movusd",  14,24,  0x1fae, "1A1A" },
+  { "movxbd",  14,24,  0x1cce, "1B2D" },
+  { "movxwd",  14,24,  0x1dce, "1W2D" },
+  { "movxbw",  14,24,  0x10ce, "1B2W" },
+  { "movzbd",  14,24,  0x18ce, "1B2D" },
+  { "movzwd",  14,24,  0x19ce, "1W2D" },
+  { "movzbw",  14,24,  0x14ce, "1B2W" },
+  { "mulf",    14,24,  0x31be, "1F2F" },
+  { "mull",    14,24,  0x30be, "1L2L" },
+  { "mulb",    14,24,  0x20ce, "1B2B" },
+  { "mulw",    14,24,  0x21ce, "1W2W" },
+  { "muld",    14,24,  0x23ce, "1D2D" },
+  { "negf",    14,24,  0x15be, "1F2F" },
+  { "negl",    14,24,  0x14be, "1L2L" },
+  { "negb",    14,24,  0x204e, "1B2B" },
+  { "negw",    14,24,  0x214e, "1W2W" },
+  { "negd",    14,24,  0x234e, "1D2D" },
+  { "nop",      8,8,   0xa2,   "" },
+  { "notb",    14,24,  0x244e, "1B2B" },
+  { "notw",    14,24,  0x254e, "1W2W" },
+  { "notd",    14,24,  0x274e, "1D2D" },
+  { "orb",      6,16,  0x18,   "1B1B" },
+  { "orw",      6,16,  0x19,   "1W1W" },
+  { "ord",      6,16,  0x1b,   "1D1D" },
+  { "quob",    14,24,  0x30ce, "1B2B" },
+  { "quow",    14,24,  0x31ce, "1W2W" },
+  { "quod",    14,24,  0x33ce, "1D2D" },
+  { "rdval",   19,24,  0x0031e,"1A" },
+  { "remb",    14,24,  0x34ce, "1B2B" },
+  { "remw",    14,24,  0x35ce, "1W2W" },
+  { "remd",    14,24,  0x37ce, "1D2D" },
+  { "restore",  8,8,   0x72,   "1i" },
+  { "ret",      8,8,   0x12,   "1d" },
+  { "reti",     8,8,   0x52,   "" },
+  { "rett",     8,8,   0x42,   "" },
+  { "rotb",    14,24,  0x004e, "1B2B" },
+  { "rotw",    14,24,  0x014e, "1B2W" },
+  { "rotd",    14,24,  0x034e, "1B2D" },
+  { "roundfb", 14,24,  0x243e, "1F2B" },
+  { "roundfw", 14,24,  0x253e, "1F2W" },
+  { "roundfd", 14,24,  0x273e, "1F2D" },
+  { "roundlb", 14,24,  0x203e, "1L2B" },
+  { "roundlw", 14,24,  0x213e, "1L2W" },
+  { "roundld", 14,24,  0x233e, "1L2D" },
+  { "rxp",      8,8,   0x32,   "1d" },
+  { "sCONDb",   7,16,  0x3c,   "2B1q" },
+  { "sCONDw",   7,16,  0x3d,   "2D1q" },
+  { "sCONDd",   7,16,  0x3f,   "2D1q" },
+  { "save",     8,8,   0x62,   "1i" },
+  { "sbitb",   14,24,  0x184e, "1B2A" },
+  { "sbitw",   14,24,  0x194e, "1W2A" },
+  { "sbitd",   14,24,  0x1b4e, "1D2A" },
+  { "sbitib",  14,24,  0x1c4e, "1B2A" },
+  { "sbitiw",  14,24,  0x1d4e, "1W2A" },
+  { "sbitid",  14,24,  0x1f4e, "1D2A" },
+  { "setcfg",  15,24,  0x0b0e, "5D1q" },
+  { "sfsr",    14,24,  0x673e, "5D1D" },
+  { "skpsb",   16,16,  0x0c0e, "1i" },
+  { "skpsw",   16,16,  0x0d0e, "1i" },
+  { "skpsd",   16,16,  0x0f0e, "1i" },
+  { "skpst",   16,16,  0x8c0e, "1i" },
+  { "smr",     15,24,  0x0f1e, "2D1q" },
+  { "sprb",     7,16,  0x2c,   "2B1q" },
+  { "sprw",     7,16,  0x2d,   "2W1q" },
+  { "sprd",     7,16,  0x2f,   "2D1q" },
+  { "subf",    14,24,  0x11be, "1F2F" },
+  { "subl",    14,24,  0x10be, "1L2L" },
+  { "subb",     6,16,  0x20,   "1B2B" },
+  { "subw",     6,16,  0x21,   "1W2W" },
+  { "subd",     6,16,  0x23,   "1D2D" },
+  { "subcb",    6,16,  0x30,   "1B2B" },
+  { "subcw",    6,16,  0x31,   "1W2W" },
+  { "subcd",    6,16,  0x33,   "1D2D" },
+  { "subpb",   14,24,  0x2c4e, "1B2B" },
+  { "subpw",   14,24,  0x2d4e, "1W2W" },
+  { "subpd",   14,24,  0x2f4e, "1D2D" },
+#ifndef NS32K_SVC_IMMED_OPERANDS
+  { "svc",      8,8,   0xe2,   "2i1i" }, /* not really, but unix uses it */
+#else
+  { "svc",      8,8,   0xe2,   "" }, /* not really, but unix uses it */
+#endif
+  { "tbitb",    6,16,  0x34,   "1B2A" },
+  { "tbitw",    6,16,  0x35,   "1W2A" },
+  { "tbitd",    6,16,  0x37,   "1D2A" },
+  { "truncfb", 14,24,  0x2c3e, "1F2B" },
+  { "truncfw", 14,24,  0x2d3e, "1F2W" },
+  { "truncfd", 14,24,  0x2f3e, "1F2D" },
+  { "trunclb", 14,24,  0x283e, "1L2B" },
+  { "trunclw", 14,24,  0x293e, "1L2W" },
+  { "truncld", 14,24,  0x2b3e, "1L2D" },
+  { "wait",     8,8,   0xb2,   "" },
+  { "wrval",   19,24,  0x0071e,"1A" },
+  { "xorb",     6,16,  0x38,   "1B2B" },
+  { "xorw",     6,16,  0x39,   "1W2W" },
+  { "xord",     6,16,  0x3b,   "1D2D" },
+};                             /* notstrs */
+
+/* end: ns32k.opcode.h */
+
+#define MAX_ARGS 4
+#define ARG_LEN 50
diff --git a/gdb/ns32k-pinsn.c b/gdb/ns32k-pinsn.c
new file mode 100644 (file)
index 0000000..7afee48
--- /dev/null
@@ -0,0 +1,437 @@
+/* Print 32000 instructions 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 <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "ns32k-opcode.h"
+
+/* 32000 instructions are never longer than this.  */
+#define MAXLEN 62
+
+/* Number of elements in the opcode table.  */
+#define NOPCODES (sizeof notstrs / sizeof notstrs[0])
+
+extern char *reg_names[];
+
+#define NEXT_IS_ADDR   '|'
+
+/*
+ * extract "count" bits starting "offset" bits
+ * into buffer
+ */
+
+int
+bit_extract (buffer, offset, count)
+     char *buffer;
+     int offset;
+     int count;
+{
+  int result;
+  int mask;
+  int bit;
+
+  buffer += offset >> 3;
+  offset &= 7;
+  bit = 1;
+  result = 0;
+  while (count--) 
+    {
+      if ((*buffer & (1 << offset)))
+       result |= bit;
+      if (++offset == 8)
+       {
+         offset = 0;
+         buffer++;
+       }
+      bit <<= 1;
+    }
+  return result;
+}
+
+double
+dbit_extract (buffer, offset, count)
+{
+  union {
+    struct {int low, high; } ival;
+    double dval;
+  } foo;
+
+  foo.ival.low = bit_extract (buffer, offset, 32);
+  foo.ival.high = bit_extract (buffer, offset+32, 32);
+  return foo.dval;
+}
+
+sign_extend (value, bits)
+{
+  value = value & ((1 << bits) - 1);
+  return (value & (1 << (bits-1))
+         ? value | (~((1 << bits) - 1))
+         : value);
+}
+
+flip_bytes (ptr, count)
+     char *ptr;
+     int count;
+{
+  char tmp;
+
+  while (count > 0)
+    {
+      tmp = *ptr;
+      ptr[0] = ptr[count-1];
+      ptr[count-1] = tmp;
+      ptr++;
+      count -= 2;
+    }
+}
+
+\f
+/* Print the 32000 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;
+  unsigned short first_word;
+  int gen, disp;
+  int ioffset;         /* bits into instruction */
+  int aoffset;         /* bits into arguments */
+  char arg_bufs[MAX_ARGS+1][ARG_LEN];
+  int argnum;
+  int maxarg;
+
+  read_memory (memaddr, buffer, MAXLEN);
+
+  first_word = *(unsigned short *) buffer;
+  for (i = 0; i < NOPCODES; i++)
+    if ((first_word & ((1 << notstrs[i].detail.obits) - 1))
+       == notstrs[i].detail.code)
+      break;
+
+  /* Handle undefined instructions.  */
+  if (i == NOPCODES)
+    {
+      fprintf (stream, "0%o", buffer[0]);
+      return 1;
+    }
+
+  fprintf (stream, "%s", notstrs[i].name);
+
+  ioffset = notstrs[i].detail.ibits;
+  aoffset = notstrs[i].detail.ibits;
+  d = notstrs[i].detail.args;
+
+  if (*d)
+    {
+      fputc ('\t', stream);
+
+      maxarg = 0;
+      while (*d)
+       {
+         argnum = *d - '1';
+         d++;
+         if (argnum > maxarg && argnum < MAX_ARGS)
+           maxarg = argnum;
+         ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
+                                   memaddr, arg_bufs[argnum]);
+         d++;
+       }
+      for (argnum = 0; argnum <= maxarg; argnum++)
+       {
+         CORE_ADDR addr;
+         char *ch, *index ();
+         for (ch = arg_bufs[argnum]; *ch;)
+           {
+             if (*ch == NEXT_IS_ADDR)
+               {
+                 ++ch;
+                 addr = atoi (ch);
+                 print_address (addr, stream);
+                 while (*ch && *ch != NEXT_IS_ADDR)
+                   ++ch;
+                 if (*ch)
+                   ++ch;
+               }
+             else
+               putc (*ch++, stream);
+           }
+         if (argnum < maxarg)
+           fprintf (stream, ", ");
+       }
+    }
+  return aoffset / 8;
+}
+
+print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result)
+     char d;
+     int ioffset, *aoffsetp;
+     char *buffer;
+     CORE_ADDR addr;
+     char *result;
+{
+  int addr_mode;
+  float Fvalue;
+  double Lvalue;
+  int Ivalue;
+  int disp1, disp2;
+  int index;
+
+  switch (d)
+    {
+    case 'F':
+    case 'L':
+    case 'B':
+    case 'W':
+    case 'D':
+    case 'A':
+      addr_mode = bit_extract (buffer, ioffset-5, 5);
+      ioffset -= 5;
+      switch (addr_mode)
+       {
+       case 0x0: case 0x1: case 0x2: case 0x3:
+       case 0x4: case 0x5: case 0x6: case 0x7:
+         sprintf (result, "r%d", addr_mode);
+         break;
+       case 0x8: case 0x9: case 0xa: case 0xb:
+       case 0xc: case 0xd: case 0xe: case 0xf:
+         disp1 = get_displacement (buffer, aoffsetp);
+         sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
+         break;
+       case 0x10:
+       case 0x11:
+       case 0x12:
+         disp1 = get_displacement (buffer, aoffsetp);
+         disp2 = get_displacement (buffer, aoffsetp);
+         sprintf (result, "%d(%d(%s))", disp2, disp1,
+                  addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb");
+         break;
+       case 0x13:
+         sprintf (result, "reserved");
+         break;
+       case 0x14:
+         switch (d)
+           {
+           case 'B':
+             Ivalue = bit_extract (buffer, *aoffsetp, 8);
+             Ivalue = sign_extend (Ivalue, 8);
+             *aoffsetp += 8;
+             sprintf (result, "$%d", Ivalue);
+             break;
+           case 'W':
+             Ivalue = bit_extract (buffer, *aoffsetp, 16);
+             flip_bytes (&Ivalue, 2);
+             *aoffsetp += 16;
+             Ivalue = sign_extend (Ivalue, 16);
+             sprintf (result, "$%d", Ivalue);
+             break;
+           case 'D':
+             Ivalue = bit_extract (buffer, *aoffsetp, 32);
+             flip_bytes (&Ivalue, 4);
+             *aoffsetp += 32;
+             sprintf (result, "$%d", Ivalue);
+             break;
+           case 'A':
+             Ivalue = bit_extract (buffer, *aoffsetp, 32);
+             flip_bytes (&Ivalue, 4);
+             *aoffsetp += 32;
+             sprintf (result, "$|%d|", Ivalue);
+             break;
+           case 'F':
+             Fvalue = (float) bit_extract (buffer, *aoffsetp, 32);
+             flip_bytes (&Fvalue, 4);
+             *aoffsetp += 32;
+             sprintf (result, "$%g", Fvalue);
+             break;
+           case 'L':
+             Lvalue = dbit_extract (buffer, *aoffsetp, 64);
+             flip_bytes (&Lvalue, 8);
+             *aoffsetp += 64;
+             sprintf (result, "$%g", Lvalue);
+             break;
+           }
+         break;
+       case 0x15:
+         disp1 = get_displacement (buffer, aoffsetp);
+         sprintf (result, "@|%d|", disp1);
+         break;
+       case 0x16:
+         disp1 = get_displacement (buffer, aoffsetp);
+         disp2 = get_displacement (buffer, aoffsetp);
+         sprintf (result, "EXT(%d) + %d", disp1, disp2);
+         break;
+       case 0x17:
+         sprintf (result, "tos");
+         break;
+       case 0x18:
+         disp1 = get_displacement (buffer, aoffsetp);
+         sprintf (result, "%d(fp)", disp1);
+         break;
+       case 0x19:
+         disp1 = get_displacement (buffer, aoffsetp);
+         sprintf (result, "%d(sp)", disp1);
+         break;
+       case 0x1a:
+         disp1 = get_displacement (buffer, aoffsetp);
+         sprintf (result, "%d(sb)", disp1);
+         break;
+       case 0x1b:
+         disp1 = get_displacement (buffer, aoffsetp);
+         sprintf (result, "|%d|", addr + disp1);
+         break;
+       case 0x1c:
+       case 0x1d:
+       case 0x1e:
+       case 0x1f:
+         index = bit_extract (buffer, *aoffsetp, 8);
+         *aoffsetp += 8;
+         print_insn_arg (d, *aoffsetp, aoffsetp, buffer, addr,
+                         result);
+         {
+           static char *ind[] = {"b", "w", "d", "q"};
+           char *off;
+
+           off = result + strlen (result);
+           sprintf (off, "[r%d:%s]", index & 7,
+                    ind[addr_mode & 3]);
+         }
+         break;
+       }
+      break;
+    case 'q':
+      Ivalue = bit_extract (buffer, ioffset-4, 4);
+      Ivalue = sign_extend (Ivalue, 4);
+      sprintf (result, "%d", Ivalue);
+      ioffset -= 4;
+      break;
+    case 'r':
+      Ivalue = bit_extract (buffer, ioffset-3, 3);
+      sprintf (result, "r%d", Ivalue&7);
+      ioffset -= 3;
+      break;
+    case 'd':
+      sprintf (result, "%d", get_displacement (buffer, aoffsetp));
+      break;
+    case 'p':
+      sprintf (result, "%c%d%c", NEXT_IS_ADDR,
+              addr + get_displacement (buffer, aoffsetp),
+              NEXT_IS_ADDR);
+      break;
+    case 'i':
+      Ivalue = bit_extract (buffer, *aoffsetp, 8);
+      *aoffsetp += 8;
+      sprintf (result, "0x%x", Ivalue);
+      break;
+    }
+  return ioffset;
+}
+
+get_displacement (buffer, aoffsetp)
+     char *buffer;
+     int *aoffsetp;
+{
+  int Ivalue;
+
+  Ivalue = bit_extract (buffer, *aoffsetp, 8);
+  switch (Ivalue & 0xc0)
+    {
+    case 0x00:
+    case 0x40:
+      Ivalue = sign_extend (Ivalue, 7);
+      *aoffsetp += 8;
+      break;
+    case 0x80:
+      Ivalue = bit_extract (buffer, *aoffsetp, 16);
+      flip_bytes (&Ivalue, 2);
+      Ivalue = sign_extend (Ivalue, 14);
+      *aoffsetp += 16;
+      break;
+    case 0xc0:
+      Ivalue = bit_extract (buffer, *aoffsetp, 32);
+      flip_bytes (&Ivalue, 4);
+      Ivalue = sign_extend (Ivalue, 30);
+      *aoffsetp += 32;
+      break;
+    }
+  return Ivalue;
+}
+\f
+/* Return the number of locals in the current frame given a pc
+   pointing to the enter instruction.  This is used in the macro
+   FRAME_FIND_SAVED_REGS.  */
+
+ns32k_localcount (enter_pc)
+     CORE_ADDR enter_pc;
+{
+  unsigned char localtype;
+  int localcount;
+
+  localtype = read_memory_integer (enter_pc+2, 1);
+  if ((localtype & 0x80) == 0)
+    localcount = localtype;
+  else if ((localtype & 0xc0) == 0x80)
+    localcount = (((localtype & 0x3f) << 8)
+                 | (read_memory_integer (enter_pc+3, 1) & 0xff));
+  else
+    localcount = (((localtype & 0x3f) << 24)
+                 | ((read_memory_integer (enter_pc+3, 1) & 0xff) << 16)
+                 | ((read_memory_integer (enter_pc+4, 1) & 0xff) << 8 )
+                 | (read_memory_integer (enter_pc+5, 1) & 0xff));
+  return localcount;
+}
+
+/*
+ * Get the address of the enter opcode for the function
+ * containing PC, if there is an enter for the function,
+ * and if the pc is between the enter and exit.
+ * Returns positive address if pc is between enter/exit,
+ * 1 if pc before enter or after exit, 0 otherwise.
+ */
+
+CORE_ADDR
+n32k_get_enter_addr (pc)
+     CORE_ADDR pc;
+{
+  CORE_ADDR enter_addr;
+  unsigned char op;
+
+  if (ABOUT_TO_RETURN (pc))
+    return 1;          /* after exit */
+
+  enter_addr = get_pc_function_start (pc);
+
+  if (pc == enter_addr) 
+    return 1;          /* before enter */
+
+  op = read_memory_integer (enter_addr, 1);
+
+  if (op != 0x82)
+    return 0;          /* function has no enter/exit */
+
+  return enter_addr;   /* pc is between enter and exit */
+}
diff --git a/gdb/obstack.c b/gdb/obstack.c
new file mode 120000 (symlink)
index 0000000..887f348
--- /dev/null
@@ -0,0 +1 @@
+../gcc/gcc-1.22/obstack.c
\ No newline at end of file
diff --git a/gdb/obstack.h b/gdb/obstack.h
new file mode 120000 (symlink)
index 0000000..db1184b
--- /dev/null
@@ -0,0 +1 @@
+../gcc/gcc-1.19/obstack.h
\ No newline at end of file
diff --git a/gdb/param.h b/gdb/param.h
new file mode 100644 (file)
index 0000000..56f2c8a
--- /dev/null
@@ -0,0 +1 @@
+#include "m-mac-aux.h"
diff --git a/gdb/pinsn.c b/gdb/pinsn.c
new file mode 100644 (file)
index 0000000..0b6414e
--- /dev/null
@@ -0,0 +1 @@
+#include "m68k-pinsn.c"
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
new file mode 100644 (file)
index 0000000..d84dd9d
--- /dev/null
@@ -0,0 +1,979 @@
+/* Print values for GNU debugger 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 <stdio.h>
+#include "defs.h"
+#include "initialize.h"
+#include "param.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;
+
+void do_displays ();
+void print_address ();
+
+START_FILE
+\f
+/* 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++;
+      else if (*p >= 'a' && *p <= 'z')
+       val.format = *p++;
+      else
+       break;
+    }
+
+  while (*p == ' ' || *p == '\t') p++;
+  *string_ptr = p;
+
+  return val;
+}
+\f
+/* 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.  */
+
+static void
+print_formatted (val, format)
+     register value val;
+     register char format;
+{
+  register CORE_ADDR val_long;
+  int len = TYPE_LENGTH (VALUE_TYPE (val));
+
+  if (VALUE_LVAL (val) == lval_memory)
+    next_address = VALUE_ADDRESS (val) + len;
+
+  if (format && format != 's')
+    {
+      val_long = value_as_long (val);
+
+      /* 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;
+       }
+    }
+
+  switch (format)
+    {
+    case 's':
+      next_address = VALUE_ADDRESS (val)
+       + value_print (value_addr (val), stdout);
+      break;
+
+    case 'i':
+      next_address = VALUE_ADDRESS (val)
+       + print_insn (VALUE_ADDRESS (val), stdout);
+      break;
+
+    case 'x':
+      printf ("0x%x", val_long);
+      break;
+
+    case 'd':
+      printf ("%d", val_long);
+      break;
+
+    case 'u':
+      printf ("%u", val_long);
+      break;
+
+    case 'o':
+      if (val_long)
+       printf ("0%o", val_long);
+      else
+       printf ("0");
+      break;
+
+    case 'a':
+      print_address (val_long, stdout);
+      break;
+
+    case 'c':
+      value_print (value_cast (builtin_type_char, val), stdout);
+      break;
+
+    case 'f':
+      if (TYPE_LENGTH (VALUE_TYPE (val)) == sizeof (float))
+       VALUE_TYPE (val) = builtin_type_float;
+      if (TYPE_LENGTH (VALUE_TYPE (val)) == sizeof (double))
+       VALUE_TYPE (val) = builtin_type_double;
+#ifdef IEEE_FLOAT
+      if (is_nan (value_as_double (val)))
+       {
+         printf ("Nan");
+         break;
+       }
+#endif
+      printf ("%g", value_as_double (val));
+      break;
+
+    case 0:
+      value_print (val, stdout);
+      break;
+
+    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, addr));
+}
+
+/* Print address ADDR symbolically on STREAM.
+   First print it as a number.  Then perhaps print
+   <SYMBOL + OFFSET> after the number.  */
+
+void
+print_address (addr, stream)
+     CORE_ADDR addr;
+     FILE *stream;
+{
+  register int i;
+
+  fprintf (stream, "0x%x", addr);
+
+  i = find_pc_misc_function (addr);
+  if (i >= 0)
+    if (misc_function_vector[i].address != addr)
+      fprintf (stream, " <%s+%d>",
+              misc_function_vector[i].name,
+              addr - misc_function_vector[i].address);
+    else
+      fprintf (stream, " <%s>", misc_function_vector[i].name);
+
+}
+\f
+/* 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')
+    val_type = builtin_type_double;
+
+  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);
+      for (i = maxelts;
+          i > 0 && count > 0;
+          i--, count--)
+       {
+         fputc ('\t', stdout);
+         /* Note that this 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);
+       }
+      fputc ('\n', stdout);
+      fflush (stdout);
+    }
+}
+\f
+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);
+  printf ("$%d = ", histindex);
+
+  print_formatted (val, format);
+  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);
+
+  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;
+
+  if (exp == 0)
+    error ("Argument required.");
+
+  sym = lookup_symbol (exp, get_selected_block (), VAR_NAMESPACE);
+  if (sym == 0)
+    {
+      register int i;
+
+      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_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");
+}
+\f
+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 = value_as_long (evaluate_expression (expr));
+      do_cleanups (old_chain);
+    }
+
+  do_examine (fmt, next_address);
+
+  /* Make last address examined available to the user as $_.  */
+  set_internalvar (lookup_internalvar ("_"),
+                  value_from_long (builtin_type_int, last_examine_address));
+
+  /* Make contents of last address examined available to the user as $__.  */
+  set_internalvar (lookup_internalvar ("__"), last_examine_value);
+}
+\f
+/* 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);
+         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");
+}
+\f
+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;
+  /* Block in which expression is to be evaluated.  */
+  struct block *block;
+};
+
+/* 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)
+     char *exp;
+{
+  struct format_data fmt;
+  register struct expression *expr;
+  register struct display *new;
+
+  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;
+    }
+
+  expr = parse_c_expression (exp);
+
+  new = (struct display *) xmalloc (sizeof (struct display));
+
+  new->exp = expr;
+  new->next = display_chain;
+  new->number = ++display_number;
+  new->format = fmt;
+  display_chain = 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 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);
+
+      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;
+             }
+         }
+
+      p = p1;
+      while (*p == ' ' || *p == '\t') p++;
+    }
+  dont_repeat ();
+}
+
+/* Display all of the values on the auto-display chain.  */
+
+void
+do_displays ()
+{
+  register struct display *d;
+
+  for (d = display_chain; d; d = d->next)
+    {
+      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,
+                     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);
+         printf ("\n");
+       }
+      fflush (stdout);
+    }
+}
+
+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");
+  for (d = display_chain; d; d = d->next)
+    {
+      printf ("%d: ", d->number);
+      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);
+      printf ("\n");
+      fflush (stdout);
+    }
+}
+\f
+/* 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);
+}
+
+/* Print the arguments of a stack frame, given the function FUNC
+   running in that frame (as a symbol), the address of the arglist,
+   and the number of args according to the stack frame (or -1 if unknown).  */
+
+static void print_frame_nameless_args ();
+
+print_frame_args (func, addr, num, stream)
+     struct symbol *func;
+     register CORE_ADDR addr;
+     int num;
+     FILE *stream;
+{
+  struct block *b;
+  int nsyms = 0;
+  int first = 1;
+  register int i;
+  register int last_offset = FRAME_ARGS_SKIP;
+  register struct symbol *sym, *nextsym;
+  register value val;
+
+  if (func)
+    {
+      b = SYMBOL_BLOCK_VALUE (func);
+      nsyms = BLOCK_NSYMS (b);
+    }
+
+  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
+             && SYMBOL_VALUE (sym) >= last_offset
+             && (nextsym == 0
+                 || SYMBOL_VALUE (sym) < SYMBOL_VALUE (nextsym)))
+           nextsym = sym;
+       }
+      if (nextsym == 0)
+       break;
+      sym = nextsym;
+      /* Print any nameless args between the last arg printed
+        and the next arg.  */
+      if (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.  */
+      val = value_at (SYMBOL_TYPE (sym), addr + SYMBOL_VALUE (sym));
+      if (! first)
+       fprintf (stream, ", ");
+      fprintf (stream, "%s=", SYMBOL_NAME (sym));
+      value_print (val, stream);
+      first = 0;
+      last_offset = SYMBOL_VALUE (sym) + 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);
+    }
+  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);
+    }
+}
+\f
+static
+initialize ()
+{
+  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_com ("undisplay", class_vars, undisplay_command,
+          "Cancel some expressions to be displayed whenever 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.");
+  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_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_com ("set", class_vars, set_command,
+          "Perform an assignment VAR = EXP.  You must type the \"=\".\n\
+VAR may be a debugger \"convenience\" variables (names starting with $),\n\
+a register (a few standard names starting with $), or an actual variable\n\
+in the program being debugger.  EXP is any expression.");
+
+  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);
+}
+
+END_FILE
diff --git a/gdb/song b/gdb/song
new file mode 100644 (file)
index 0000000..ad65ee9
--- /dev/null
+++ b/gdb/song
@@ -0,0 +1,44 @@
+Date: Tue, 6 Oct 87 08:52:07 PDT
+To: bug-gnu-emacs@prep.ai.mit.edu
+From: Lynn Slater <silvlis!wobegon!lrs@sun.com>
+Sender: silvlis!wobegon!lrs@sun.com
+Organization: Silvar-Lisco, 1080 Marsh Road, Menlo Park, CA 94025-1053
+Phone.......: (415) 853-6336 (Office); (415) 796-4149 (Home)
+Subject: GDB sing-along
+
+
+Somebody asked us what was GDB.  With apologies to Oscar Hemmerstein
+II, Richard Rodgers, and Julie Andrews, we offered the following reply:
+
+Let's start at the very beginning, a very good place to start,
+  When you're learning to sing, its Do, Re, Mi;
+  When you're learning to code, its G,  D,   B.
+                       (background) G,  D,   B.
+  The first three letters just happen to be, G, D, B.
+                       (background) G,  D,   B.
+
+(Chorus)
+   G!,    GNU!, it's Stallman's hope,
+   
+   B,     a break I set myself.
+   
+   D,     debug that rotten code,
+   
+   Run,   a far, far way to go.
+   
+   Print, to see what you have done,
+   
+   Set,   a patch that follows print.
+
+   Quit,  and recompile your code  - - -
+   
+That will bring it back to G,
+                            D,
+                             B,
+                               <link>
+(Resume from the Chorus)
+
+
+:-)  Joel Bion, Mark Baushke, and Lynn Slater :-)
+
diff --git a/gdb/source.c b/gdb/source.c
new file mode 100644 (file)
index 0000000..27ffd8f
--- /dev/null
@@ -0,0 +1,667 @@
+/* List lines of source files 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 <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include "defs.h"
+#include "initialize.h"
+#include "symtab.h"
+
+/* 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 for "info line" to work on if no line specified.  */
+
+static int line_info_default_line;
+
+/* First line number listed by last listing command.  */
+
+static int first_line_listed;
+
+START_FILE
+\f
+/* Set the source file default for the "list" command,
+   specifying a symtab.  */
+
+void
+select_source_symtab (s)
+     register struct symtab *s;
+{
+  if (s)
+    {
+      struct symtab_and_line sal;
+
+      /* Make the default place to list be the function `main'
+        if one exists.  */
+      if (lookup_symbol ("main", 0, VAR_NAMESPACE))
+       {
+         sal = decode_line_spec ("main", 1);
+         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.  */
+      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;
+    }
+}
+\f
+static void
+directories_info ()
+{
+  printf ("Source directories searched: %s\n", source_path);
+}
+
+static void
+init_source_path ()
+{
+  register struct symtab *s;
+  char wd[MAXPATHLEN];
+  if (getwd (wd) == NULL)
+    perror_with_name ("getwd");
+
+  source_path = savestring (wd, strlen (wd));
+
+  /* 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;
+
+  char wd[MAXPATHLEN];
+  if (getwd (wd) == NULL)
+    perror_with_name ("getwd");
+
+  if (dirname == 0)
+    {
+      if (query ("Reinitialize source path to %s? ", wd))
+       {
+         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 = wd;
+             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 (wd, "/", 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 ();
+    }
+}
+\f
+/* 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
+      {
+       char dirname[MAXPATHLEN];
+       if (getwd (dirname) == NULL)
+         perror_with_name ("getwd");
+       *filename_opened = concat (dirname, "/", filename);
+      }
+
+  return fd;
+}
+\f
+/* 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 && 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')
+       {
+         if (nlines == lines_allocated)
+           line_charpos = (int *) xrealloc (line_charpos,
+                                            sizeof (int) * (lines_allocated *= 2));
+         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;
+}
+\f
+/* 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, fullname);
+  if (desc < 0)
+    {
+      *fullname = NULL;
+      return 0;
+    }  
+  if (s->line_charpos == 0) linenums_changed = 1;
+  if (linenums_changed) find_source_lines (s, desc);
+  close (desc);
+  return linenums_changed;
+}
+\f
+/* 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)
+     struct symtab *s;
+     int line, stopline;
+{
+  register int c;
+  register int desc;
+  register FILE *stream;
+  int nlines = stopline - line;
+
+  desc = openp (source_path, 0, s->filename, O_RDONLY, 0, (char **) 0);
+  if (desc < 0)
+    perror_with_name (s->filename);
+
+  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;
+      line_info_default_line = 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);
+}
+\f
+static void
+list_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  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)
+    error ("Listing source lines requires symbols.");
+
+  /* "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);
+      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);
+      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
+    sal = decode_line_1 (&arg1, 0, 0, 0);
+
+  /* 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)
+       sal_end = decode_line_1 (&arg1, 0, 0, 0);
+      else
+       sal_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line);
+    }
+
+  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);
+  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);
+  else
+    print_source_lines (sal.symtab, sal.line,
+                       dummy_end ? sal.line + 10 : sal_end.line + 1);
+}
+\f
+/* Print info on range of pc's in a specified line.  */
+
+static void
+line_info (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  struct symtab_and_line sal;
+  int start_pc, end_pc;
+
+  if (arg == 0)
+    {
+      sal.symtab = current_source_symtab;
+      sal.line = line_info_default_line;
+    }
+  else
+    {
+      sal = decode_line_spec (arg);
+
+      /* If this command is repeated with RET,
+        turn it into the no-arg variant.  */
+
+      if (from_tty)
+       *arg = 0;
+    }
+
+  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.  */
+      line_info_default_line = sal.line + 1;
+    }
+  else
+    printf ("Line number %d is out of range for \"%s\".\n",
+           sal.line, sal.symtab->filename);
+}
+\f
+static
+initialize ()
+{
+  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 ("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.");
+}
+
+END_FILE
diff --git a/gdb/stack.c b/gdb/stack.c
new file mode 100644 (file)
index 0000000..2698729
--- /dev/null
@@ -0,0 +1,612 @@
+/* Print and select stack frames 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 <stdio.h>
+
+#include "defs.h"
+#include "initialize.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+
+START_FILE
+
+/* 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;
+
+static void select_calling_frame ();
+
+void print_frame_info ();
+\f
+/* 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.  */
+
+static void
+print_stack_frame (frame, level, source)
+     FRAME frame;
+     int level;
+     int source;
+{
+  struct frame_info fi;
+
+  fi = get_frame_info (frame);
+
+  print_frame_info (&fi, level, source, 1);
+}
+
+void
+print_frame_info (fi, level, source, args)
+     struct frame_info *fi;
+     register int level;
+     int source;
+     int args;
+{
+  register FRAME frame = fi->frame;
+  struct symtab_and_line sal;
+  struct symbol *func;
+  register char *funname = 0;
+  int numargs;
+
+  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;
+    }
+
+  if (source >= 0 || !sal.symtab)
+    {
+      /* This avoids a bug in cc on the sun.  */
+      struct frame_info tem;
+      tem = *fi;
+
+      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, tem);
+         print_frame_args (func, FRAME_ARGS_ADDRESS (tem), numargs, stdout);
+       }
+      printf (")");
+      if (sal.symtab)
+       printf (" (%s line %d)", sal.symtab->filename, sal.line);
+      printf ("\n");
+    }
+
+  if (source != 0 && sal.symtab)
+    {
+      if (source < 0 && fi->pc != sal.pc)
+       printf ("0x%x\t", fi->pc);
+      print_source_lines (sal.symtab, sal.line, sal.line + 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.  */
+
+print_selected_frame ()
+{
+  print_stack_frame (selected_frame, selected_frame_level, 0);
+}
+
+/* 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 = addr_exp ? parse_and_eval_address (addr_exp) : selected_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;
+
+  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, fi.pc);
+  else
+    printf ("Stack frame at 0x%x:\n pc = 0x%x",
+           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", 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, FRAME_ARGS_ADDRESS (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");
+}
+
+/* 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;
+
+  if (count_exp)
+    count = parse_and_eval_address (count_exp);
+  else
+    count = -1;
+
+  for (i = 0, frame = get_current_frame (), fi = get_frame_info (frame);
+       frame && count--;
+       i++, fi = get_prev_frame_info (fi.frame), frame = fi.frame)
+    {
+      QUIT;
+      print_frame_info (&fi, i, 0, 1);
+    }
+}
+\f
+/* 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)
+       {
+         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 = 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 ()
+{
+  print_frame_local_vars (selected_frame, stdout);
+}
+
+static int
+print_frame_arg_vars (frame, stream)
+     register FRAME frame;
+     register FILE *stream;
+{
+  struct symbol *func = get_frame_function (frame);
+  register struct block *b;
+  int nsyms;
+  register int i;
+  register struct symbol *sym;
+
+  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)
+       {
+         fprintf (stream, "%s = ", SYMBOL_NAME (sym));
+         print_variable_value (sym, frame, stream);
+         fprintf (stream, "\n");
+         fflush (stream);
+       }
+    }
+
+  return 1;
+}
+
+static void
+args_info ()
+{
+  print_frame_arg_vars (selected_frame, stdout);
+}
+\f
+/* 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 (framep, levelp)
+     FRAME *framep;
+     int *levelp;
+{
+  *framep = 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;
+  struct frame_info fi;
+  register FRAME frame1, frame2;
+
+  /* Going up is simple: just do get_prev_frame enough times
+     or until initial frame is reached.  */
+  while (*level_offset_ptr > 0)
+    {
+      prev = get_prev_frame (frame);
+      if (prev == 0)
+       break;
+      (*level_offset_ptr)--;
+      frame = prev;
+    }
+  /* Going down could be done by iterating get_frame_info to
+     find the next frame, but that would be quadratic
+     since get_frame_info must scan all the way from the current frame.
+     The following algotithm 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, select the frame at level LEVEL and print it.
+   With arg larger than 100000, use it as address of frame to select.
+   If from command file or user-defined command, don't print anything
+   if we have an argument.  */
+
+static void
+frame_command (level_exp, from_tty)
+     char *level_exp;
+     int from_tty;
+{
+  register int i;
+  register FRAME frame;
+  unsigned int level, level1;
+
+  if (level_exp)
+    {
+      level1 = level = parse_and_eval_address (level_exp);
+      if (level > 100000)
+       {
+         select_frame (level, -1);
+         frame_info (0);
+         return;
+       }
+
+      frame = find_relative_frame (get_current_frame (), &level1);
+      if (level1 != 0)
+       error ("Stack level %d is out of range.", level);
+      select_frame (frame, level);
+      if (! from_tty)
+       return;
+    }
+
+  print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+/* Select the frame up one or COUNT stack levels
+   from the previously selected frame, and print it briefly.  */
+
+static void
+up_command (count_exp)
+     char *count_exp;
+{
+  register FRAME frame;
+  int count = 1, count1;
+  if (count_exp)
+    count = parse_and_eval_address (count_exp);
+  count1 = count;
+  
+  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);
+}
+\f
+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);
+}
+\f
+static
+initialize ()
+{
+  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.");
+  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.");
+}
+
+END_FILE
diff --git a/gdb/standalone.c b/gdb/standalone.c
new file mode 100644 (file)
index 0000000..94adf64
--- /dev/null
@@ -0,0 +1,605 @@
+/* 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!
+*/
+
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if defined (SIGTSTP) && defined (SIGIO)
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif /* SIGTSTP and SIGIO defined (must be 4.2) */
+
+#include "defs.h"
+#include "initialize.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+
+START_FILE
+\f
+/* Random system calls, mostly no-ops to prevent link problems  */
+
+ioctl (desc, code, arg)
+{}
+
+int (* signal ()) ()
+{}
+
+kill ()
+{}
+
+getpid ()
+{
+  return 0;
+}
+
+sigsetmask ()
+{}
+
+chdir ()
+{}
+
+char *
+getwd (buf)
+     char *buf;
+{
+  buf[0] = '/';
+  buf[1] = 0;
+  return buf;
+}
+
+/* Used to check for existence of .gdbinit.  Say no.  */
+
+access ()
+{
+  return -1;
+}
+
+exit ()
+{
+  error ("Fatal error; restarting.");
+}
+\f
+/* Reading "files".  The contents of some files are written into kdb's
+   data area before it is run.  These files are used to contain the
+   symbol table for kdb to load, and the source files (in case the
+   kdb user wants to print them).  The symbols are stored in a file
+   named "kdb-symbols" in a.out format (except that all the text and
+   data have been stripped to save room).
+
+   The files are stored in the following format:
+   int     number of bytes of data for this file, including these four.
+   char[]  name of the file, ending with a null.
+   padding to multiple of 4 boundary.
+   char[]  file contents.  The length can be deduced from what was
+           specified before.  There is no terminating null here.
+
+   If the int at the front is zero, it means there are no more files.
+
+   Opening a file in kdb returns a nonzero value to indicate success,
+   but the value does not matter.  Only one file can be open, and only
+   for reading.  All the primitives for input from the file know
+   which file is open and ignore what is specified for the descriptor
+   or for the stdio stream.
+
+   Input with fgetc can be done either on the file that is open
+   or on stdin (which reads from the terminal through tty_input ()  */
+
+/* Address of data for the files stored in format described above.  */
+char *files_start;
+
+/* The file stream currently open:  */
+
+char *sourcebeg;               /* beginning of contents */
+int sourcesize;                        /* size of contents */
+char *sourceptr;               /* current read pointer */
+int sourceleft;                        /* number of bytes to eof */
+
+/* "descriptor" for the file now open.
+   Incremented at each close.
+   If specified descriptor does not match this,
+   it means the program is trying to use a closed descriptor.
+   We report an error for that.  */
+
+int sourcedesc;
+
+open (filename, modes)
+     char *filename;
+     int modes;
+{
+  register char *next;
+  extern int errno;
+
+  if (modes)
+    {
+      errno = EROFS;
+      return -1;
+    }
+
+  if (sourceptr)
+    {
+      errno = EMFILE;
+      return -1;
+    }
+
+  for (next - files_start; * (int *) next;
+       next += * (int *) next)
+    {
+      if (!strcmp (next + 4, filename))
+       {
+         sourcebeg = next + 4 + strlen (next + 4) + 1;
+         sourcebeg = (char *) (((int) sourcebeg + 3) & (-4));
+         sourceptr = sourcebeg;
+         sourcesize = next + * (int *) next - sourceptr;
+         sourceleft = sourcesize;
+         return sourcedesc;
+       }
+    }
+  return 0;
+}
+
+close (desc)
+     int desc;
+{
+  sourceptr = 0;
+  sourcedesc++;
+  /* Don't let sourcedesc get big enough to be confused with stdin.  */
+  if (sourcedesc == 100)
+    sourcedesc = 5;
+}
+
+FILE *
+fopen (filename, modes)
+     char *filename;
+     char *modes;
+{
+  return (FILE *) open (filename, *modes == 'w');
+}
+
+FILE *
+fdopen (desc)
+     int desc;
+{
+  return (FILE *) desc;
+}
+
+fclose (desc)
+     int desc;
+{
+  close (desc);
+}
+
+fstat (desc, statbuf)
+     struct stat *statbuf;
+{
+  extern int errno;
+
+  if (desc != sourcedesc)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  statbuf->st_size = sourcesize;
+}
+
+myread (desc, destptr, size, filename)
+     int desc;
+     char *destptr;
+     int size;
+     char *filename;
+{
+  int len = min (sourceleft, size);
+  extern int errno;
+
+  if (desc != sourcedesc)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  bcopy (sourceptr, destptr, len);
+  sourceleft -= len;
+  return len;
+}
+
+int
+fread (bufp, numelts, eltsize, stream)
+{
+  register int elts = min (numelts, sourceleft / eltsize);
+  register int len = elts * eltsize;
+  extern int errno;
+
+  if (stream != sourcedesc)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  bcopy (sourceptr, bufp, len);
+  sourceleft -= len;
+  return elts;
+}
+
+int
+fgetc (desc)
+     int desc;
+{
+  extern int errno;
+
+  if (desc == (int) stdin)
+    return tty_input ();
+
+  if (desc != sourcedesc)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  if (sourceleft-- <= 0)
+    return EOF;
+  return *sourceptr++;
+}
+
+lseek (desc, pos)
+     int desc;
+     int pos;
+{
+  extern int errno;
+
+  if (desc != sourcedesc)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  if (pos < 0 || pos > sourcesize)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  sourceptr = sourcebeg + pos;
+  sourceleft = sourcesize - pos;
+}
+\f
+/* Output in kdb can go only to the terminal, so the stream
+   specified may be ignored.  */
+
+printf (a1, a2, a3, a4, a5, a6, a7, a8, a9)
+{
+  char buffer[1024];
+  sprintf (buffer, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+  display_string (buffer);
+}
+
+fprintf (ign, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+{
+  char buffer[1024];
+  sprintf (buffer, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+  display_string (buffer);
+}
+
+fwrite (buf, numelts, size, stream)
+     register char *buf;
+     int numelts, size;
+{
+  register int i = numelts * size;
+  while (i-- > 0)
+    fputc (*buf++, stream);
+}
+
+fputc (c, ign)
+{
+  char buf[2];
+  buf[0] = c;
+  buf[1] = 0;
+  display_string (buf);
+}
+
+/* sprintf refers to this, but loading this from the
+   library would cause fflush to be loaded from it too.
+   In fact there should be no need to call this (I hope).  */
+
+_flsbuf ()
+{
+  error ("_flsbuf was actually called.");
+}
+
+fflush (ign)
+{
+}
+\f
+/* Entries into core and inflow, needed only to make things link ok.  */
+
+exec_file_command ()
+{}
+
+core_file_command ()
+{}
+
+char *
+get_exec_file ()
+{
+  /* Makes one printout look reasonable; value does not matter otherwise.  */
+  return "run";
+}
+
+have_core_file_p ()
+{
+  return 0;
+}
+
+kill_command ()
+{
+  inferior_pid = 0;
+}
+
+terminal_inferior ()
+{}
+
+terminal_ours ()
+{}
+
+terminal_init_inferior ()
+{}
+
+write_inferior_register ()
+{}
+
+read_inferior_register ()
+{}
+
+read_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  bcopy (memaddr, myaddr, len);
+}
+
+/* Always return 0 indicating success.  */
+
+write_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  bcopy (myaddr, memaddr, len);
+  return 0;
+}
+
+static REGISTER_TYPE saved_regs[NUM_REGS];
+
+REGISTER_TYPE
+read_register (regno)
+     int regno;
+{
+  if (regno < 0 || regno >= NUM_REGS)
+    error ("Register number %d out of range.", regno);
+  return saved_regs[regno];
+}
+
+void
+write_register (regno, value)
+     int regno;
+     REGISTER_TYPE value;
+{
+  if (regno < 0 || regno >= NUM_REGS)
+    error ("Register number %d out of range.", regno);
+  saved_regs[regno] = value;
+}
+\f
+/* System calls needed in relation to running the "inferior".  */
+
+vfork ()
+{
+  /* Just appear to "succeed".  Say the inferior's pid is 1.  */
+  return 1;
+}
+
+/* These are called by code that normally runs in the inferior
+   that has just been forked.  That code never runs, when standalone,
+   and these definitions are so it will link without errors.  */
+
+ptrace ()
+{}
+
+setpgrp ()
+{}
+
+execle ()
+{}
+
+_exit ()
+{}
+\f
+/* Malloc calls these.  */
+
+malloc_warning (str)
+     char *str;
+{
+  printf ("\n%s.\n\n", str);
+}
+
+char *next_free;
+char *memory_limit;
+
+char *
+sbrk (amount)
+     int amount;
+{
+  if (next_free + amount > memory_limit)
+    return (char *) -1;
+  next_free += amount;
+  return next_free - amount;
+}
+
+/* Various ways malloc might ask where end of memory is.  */
+
+char *
+ulimit ()
+{
+  return memory_limit;
+}
+
+int
+vlimit ()
+{
+  return memory_limit - next_free;
+}
+
+getrlimit (addr)
+     struct rlimit *addr;
+{
+  addr->rlim_cur = memory_limit - next_free;
+}
+\f
+/* Context switching to and from program being debugged.  */
+
+/* GDB calls here to run the user program.
+   The frame pointer for this function is saved in
+   gdb_stack by save_frame_pointer; then we restore
+   all of the user program's registers, including PC and PS.  */
+
+static int fault_code;
+static REGISTER_TYPE gdb_stack;
+
+resume ()
+{
+  REGISTER_TYPE restore[NUM_REGS];
+
+  PUSH_FRAME_PTR;
+  save_frame_pointer ();
+
+  bcopy (saved_regs, restore, sizeof restore);
+  POP_REGISTERS;
+  /* Control does not drop through here!  */
+}
+
+save_frame_pointer (val)
+     CORE_ADDR val;
+{
+  gdb_stack = val;
+}
+
+/* Fault handlers call here, running in the user program stack.
+   They must first push a fault code,
+   old PC, old PS, and any other info about the fault.
+   The exact format is machine-dependent and is known only
+   in the definition of PUSH_REGISTERS.  */
+
+fault ()
+{
+  /* Transfer all registers and fault code to the stack
+     in canonical order: registers in order of GDB register number,
+     followed by fault code.  */
+  PUSH_REGISTERS;
+
+  /* Transfer them to saved_regs and fault_code.  */
+  save_registers ();
+
+  restore_gdb ();
+  /* Control does not reach here */
+}
+
+restore_gdb ()
+{
+  CORE_ADDR new_fp = gdb_stack;
+  /* Switch to GDB's stack  */
+  POP_FRAME_PTR;
+  /* Return from the function `resume'.  */
+}
+
+/* Assuming register contents and fault code have been pushed on the stack as
+   arguments to this function, copy them into the standard place
+   for the program's registers while GDB is running.  */
+
+save_registers (firstreg)
+     int firstreg;
+{
+  bcopy (&firstreg, saved_regs, sizeof saved_regs);
+  fault_code = (&firstreg)[NUM_REGS];
+}
+
+/* Store into the structure such as `wait' would return
+   the information on why the program faulted,
+   converted into a machine-independent signal number.  */
+
+static int fault_table[] = FAULT_TABLE;
+
+int
+wait (w)
+     WAITTYPE *w;
+{
+  WSETSTOP (*w, fault_table[fault_code / FAULT_CODE_UNITS]);
+  return inferior_pid;
+}
+\f
+/* Allocate a big space in which files for kdb to read will be stored.
+   Whatever is left is where malloc can allocate storage.
+
+   Initialize it, so that there will be space in the executable file
+   for it.  Then the files can be put into kdb by writing them into
+   kdb's executable file.  */
+
+/* The default size is as much space as we expect to be available
+   for kdb to use!  */
+
+#ifndef HEAP_SIZE
+#define HEAP_SIZE 400000
+#endif
+
+char heap[HEAP_SIZE] = {0};
+
+#ifndef STACK_SIZE
+#define STACK_SIZE 100000
+#endif
+
+int kdb_stack_beg[STACK_SIZE / sizeof (int)];
+int kdb_stack_end;
+
+static
+initialize ()
+{
+  register char *next;
+
+  /* Find start of data on files.  */
+
+  files_start = heap;
+
+  /* Find the end of the data on files.  */
+
+  for (next - files_start; * (int *) next;
+       next += * (int *) next)
+    {}
+
+  /* That is where free storage starts for sbrk to give out.  */
+  next_free = next;
+
+  memory_limit = heap + sizeof heap;
+}
+
+END_FILE
diff --git a/gdb/stuff.c b/gdb/stuff.c
new file mode 100644 (file)
index 0000000..0f0a503
--- /dev/null
@@ -0,0 +1,168 @@
+/* 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!
+*/
+
+/* Written 13-Mar-86 by David Bridgham. */
+
+#include <stdio.h>
+#include <a.out.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+
+extern char *sys_errlist[];
+extern int errno;
+
+main (argc, argv)
+     int argc;
+     char *argv[];
+{
+  register char *cp;
+  char *outfile;
+  register int i;
+  int offset;
+  int out_fd, in_fd;
+  struct stat stat_buf;
+  int size, pad;
+  char buf[1024];
+  static char zeros[4] = {0};
+
+  if (argc < 4)
+    err("Not enough arguments\nUsage: %s -o kdb file1 file2 ...\n",
+       argv[0]);
+
+  outfile = 0;
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (argv[i], "-o") == 0)
+       outfile = argv[++i];
+    }
+  if (outfile == 0)
+    err("Output file not specified\n");
+
+  offset = get_offset (outfile, "_heap");
+
+  out_fd = open (outfile, O_WRONLY);
+  if (out_fd < 0)
+    err ("Error opening %s for write: %s\n", outfile, sys_errlist[errno]);
+  if (lseek (out_fd, offset, 0) < 0)
+    err ("Error seeking to heap in %s: %s\n", outfile, sys_errlist[errno]);
+
+  /* For each file listed on the command line, write it into the
+   * 'heap' of the output file.  Make sure to skip the arguments
+   * that name the output file. */
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (argv[i], "-o") == 0)
+       continue;
+      if ((in_fd = open (argv[i], O_RDONLY)) < 0)
+       err ("Error opening %s for read: %s\n", argv[i], sys_errlist[errno]);
+      if (fstat (in_fd, &stat_buf) < 0)
+       err ("Error stat'ing %s: %s\n", argv[i], sys_errlist[errno]);
+      size = strlen (argv[i]);
+      pad = 4 - (size & 3);
+      size += pad + stat_buf.st_size + sizeof (int);
+      write (out_fd, &size, sizeof (int));
+      write (out_fd, argv[i], strlen (argv[i]));
+      write (out_fd, zeros, pad);
+      while ((size = read (in_fd, buf, sizeof (buf))) > 0)
+       write (out_fd, buf, size);
+      close (in_fd);
+    }
+  size = 0;
+  write (out_fd, &size, sizeof (int));
+  close (out_fd);
+  return (0);
+}
+
+/* Read symbol table from file and returns the offset into the file
+ * where symbol sym_name is located.  If error, print message and
+ * exit. */
+get_offset (file, sym_name)
+     char *file;
+     char *sym_name;
+{
+  int f;
+  struct exec file_hdr;
+  struct nlist *symbol_table;
+  int size;
+  char *strings;
+
+  f = open (file, O_RDONLY);
+  if (f < 0)
+    err ("Error opening %s: %s\n", file, sys_errlist[errno]);
+  if (read (f, &file_hdr, sizeof (file_hdr)) < 0)
+    err ("Error reading exec structure: %s\n", sys_errlist[errno]);
+  if (N_BADMAG (file_hdr))
+    err ("File %s not an a.out file\n", file);
+
+  /* read in symbol table */
+  if ((symbol_table = (struct nlist *)malloc (file_hdr.a_syms)) == 0)
+    err ("Couldn't allocate space for symbol table\n");
+  if (lseek (f, N_SYMOFF (file_hdr), 0) == -1)
+    err ("lseek error: %s\n", sys_errlist[errno]);
+  if (read (f, symbol_table, file_hdr.a_syms) == -1)
+    err ("Error reading symbol table from %s: %s\n", file, sys_errlist[errno]);
+
+  /* read in string table */
+  if (read (f, &size, 4) == -1)
+    err ("reading string table size: %s\n", sys_errlist[errno]);
+  if ((strings = (char *)malloc (size)) == 0)
+    err ("Couldn't allocate memory for string table\n");
+  if (read (f, strings, size - 4) == -1)
+    err ("reading string table: %s\n", sys_errlist[errno]);
+
+  /* Find the core address at which the first byte of kdb text segment
+     should be loaded into core when kdb is run.  */
+  origin = find_symbol ("_etext", symbol_table, file_hdr.a_syms, strings)
+    - file_hdr.a_text;
+  /* Find the core address at which the heap will appear.  */
+  coreaddr = find_symbol (sym_name, symbol_table, file_hdr.a_syms, strings);
+  /* Return address in file of the heap data space.  */
+  return (N_TXTOFF (file_hdr) + core_addr - origin);
+}
+
+find_symbol (sym_name, symbol_table, length, strings)
+     char *sym_name;
+     struct nlist *symbol_table;
+     int length;
+     char *strings;
+{
+  register struct nlist *sym;
+
+  /* Find symbol in question */
+  for (sym = symbol_table;
+       sym != (struct nlist *)((char *)symbol_table + length);
+       sym++)
+      {
+       if ((sym->n_type & N_TYPE) != N_DATA) continue;
+       if (sym->n_un.n_strx == 0) continue;
+       if (strcmp (sym_name, strings + sym->n_un.n_strx - 4) == 0)
+         return sym->n_value;
+      }
+    err ("Data symbol %s not found in %s\n", sym_name, file);
+}
+
+err (msg, a1, a2, a3)
+     char *msg;
+     int a1, a2, a3;
+{
+  fprintf (stderr, msg, a1, a2, a3);
+  exit (-1);
+}
diff --git a/gdb/symmisc.c b/gdb/symmisc.c
new file mode 100644 (file)
index 0000000..d17cbdd
--- /dev/null
@@ -0,0 +1,535 @@
+/* Do various things to symbol tables (other than lookup)), 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 "defs.h"
+#include "initialize.h"
+#include "symtab.h"
+
+#include <stdio.h>
+#include <obstack.h>
+
+static void free_symtab ();
+
+START_FILE
+\f
+/* Free all the symtabs that are currently installed,
+   and all storage associated with them.
+   Leaves us in a consistent state with no symtabs installed.  */
+
+void
+free_all_symtabs ()
+{
+  register struct symtab *s, *snext;
+
+  /* All values will be invalid because their types will be!  */
+
+  clear_value_history ();
+  clear_displays ();
+  clear_internalvars ();
+  clear_breakpoints ();
+  set_default_breakpoint (0, 0, 0, 0);
+
+  current_source_symtab = 0;
+
+  for (s = symtab_list; s; s = snext)
+    {
+      snext = s->next;
+      free_symtab (s);
+    }
+  symtab_list = 0;
+  obstack_free (symbol_obstack, 0);
+  obstack_init (symbol_obstack);
+
+  if (misc_function_vector)
+    free (misc_function_vector);
+  misc_function_count = 0;
+  misc_function_vector = 0;
+}
+
+/* Free a struct block <- B and all the symbols defined in that block.  */
+
+static void
+free_symtab_block (b)
+     struct block *b;
+{
+  register int i, n;
+  n = BLOCK_NSYMS (b);
+  for (i = 0; i < n; i++)
+    {
+      free (SYMBOL_NAME (BLOCK_SYM (b, i)));
+      free (BLOCK_SYM (b, i));
+    }
+  free (b);
+}
+
+/* Free all the storage associated with the struct symtab <- S.
+   Note that some symtabs have contents malloc'ed structure by structure,
+   while some have contents that all live inside one big block of memory,
+   and some share the contents of another symbol table and so you should
+   not free the contents on their behalf (except sometimes the linetable,
+   which maybe per symtab even when the rest is not).
+   It is s->free_code that says which alternative to use.  */
+
+static void
+free_symtab (s)
+     register struct symtab *s;
+{
+  register int i, n;
+  register struct blockvector *bv;
+  register struct type *type;
+  register struct typevector *tv;
+
+  switch (s->free_code)
+    {
+    case free_nothing:
+      /* All the contents are part of a big block of memory
+        and some other symtab is in charge of freeing that block.
+        Therefore, do nothing.  */
+      break;
+
+    case free_explicit:
+      /* All the contents are part of a big block of memory
+        and that is our `free_ptr' and will be freed below.  */
+      break;
+
+    case free_contents:
+      /* Here all the contents were malloc'ed structure by structure
+        and must be freed that way.  */
+      /* First free the blocks (and their symbols.  */
+      bv = BLOCKVECTOR (s);
+      n = BLOCKVECTOR_NBLOCKS (bv);
+      for (i = 0; i < n; i++)
+       free_symtab_block (BLOCKVECTOR_BLOCK (bv, i));
+      /* Free the blockvector itself.  */
+      free (bv);
+      /* Free the type vector.  */
+      tv = TYPEVECTOR (s);
+      if (tv)          /* FIXME, should this happen?  It does... */
+       free (tv);
+      /* Also free the linetable.  */
+      
+    case free_linetable:
+      /* Everything will be freed either by our `free_ptr'
+        or by some other symbatb, except for our linetable.
+        Free that now.  */
+      free (LINETABLE (s));
+      break;
+    }
+
+  /* If there is a single block of memory to free, free it.  */
+  if (s->free_ptr)
+    free (s->free_ptr);
+
+  if (s->line_charpos)
+    free (s->line_charpos);
+  free (s->filename);
+  free (s);
+}
+\f
+/* Convert a raw symbol-segment to a struct symtab,
+   and relocate its internal pointers so that it is valid.  */
+
+/* This is how to relocate one pointer, given a name for it.
+   Works independent of the type of object pointed to.  */
+#define RELOCATE(slot) (slot ? (* (char **) &slot += relocation) : 0)
+
+/* This is the inverse of RELOCATE.  We use it when storing
+   a core address into a slot that has yet to be relocated.  */
+#define UNRELOCATE(slot) (slot ? (* (char **) &slot -= relocation) : 0)
+
+/* During the process of relocation, this holds the amount to relocate by
+   (the address of the file's symtab data, in core in the debugger).  */
+static int relocation;
+
+#define CORE_RELOCATE(slot) \
+  ((slot) += (((slot) < data_start) ? text_relocation          \
+             : ((slot) < bss_start) ? data_relocation : bss_relocation))
+
+#define TEXT_RELOCATE(slot)  ((slot) += text_relocation)
+
+/* Relocation amounts for addresses in the program's core image.  */
+static int text_relocation, data_relocation, bss_relocation;
+
+/* Boundaries that divide program core addresses into text, data and bss;
+   used to determine which relocation amount to use.  */
+static int data_start, bss_start;
+
+static void relocate_typevector ();
+static void relocate_blockvector ();
+static void relocate_type ();
+static void relocate_block ();
+static void relocate_symbol ();
+
+/* Relocate a file symbol table so that all the pointers
+   are valid C pointers.  Pass the struct symtab for the file
+   and the amount to relocate by.  */
+
+static struct symtab *
+relocate_symtab (root)
+     struct symbol_root *root;
+{
+  struct symtab *sp = (struct symtab *) xmalloc (sizeof (struct symtab));
+  bzero (sp, sizeof (struct symtab));
+
+  relocation = (int) root;
+  text_relocation = root->textrel;
+  data_relocation = root->datarel;
+  bss_relocation = root->bssrel;
+  data_start = root->databeg;
+  bss_start = root->bssbeg;
+
+  sp->filename = root->filename;
+  sp->ldsymoff = root->ldsymoff;
+  sp->language = root->language;
+  sp->compilation = root->compilation;
+  sp->version = root->version;
+  sp->blockvector = root->blockvector;
+  sp->typevector = root->typevector;
+  sp->free_code = free_explicit;
+  sp->free_ptr = (char *) root;
+
+  RELOCATE (TYPEVECTOR (sp));
+  RELOCATE (BLOCKVECTOR (sp));
+  RELOCATE (sp->version);
+  RELOCATE (sp->compilation);
+  RELOCATE (sp->filename);
+
+  relocate_typevector (TYPEVECTOR (sp));
+  relocate_blockvector (BLOCKVECTOR (sp));
+
+  return sp;
+}
+
+static void
+relocate_typevector (tv)
+     struct typevector *tv;
+{
+  register int ntypes = TYPEVECTOR_NTYPES (tv);
+  register int i;
+
+  for (i = 0; i < ntypes; i++)
+    RELOCATE (TYPEVECTOR_TYPE (tv, i));
+  for (i = 0; i < ntypes; i++)
+    relocate_type (TYPEVECTOR_TYPE (tv, i));
+}
+
+static void
+relocate_blockvector (blp)
+     register struct blockvector *blp;
+{
+  register int nblocks = BLOCKVECTOR_NBLOCKS (blp);
+  register int i;
+  for (i = 0; i < nblocks; i++)
+    RELOCATE (BLOCKVECTOR_BLOCK (blp, i));
+  for (i = 0; i < nblocks; i++)
+    relocate_block (BLOCKVECTOR_BLOCK (blp, i));
+}
+
+static void
+relocate_block (bp)
+     register struct block *bp;
+{
+  register int nsyms = BLOCK_NSYMS (bp);
+  register int i;
+
+  TEXT_RELOCATE (BLOCK_START (bp));
+  TEXT_RELOCATE (BLOCK_END (bp));
+
+  /* These two should not be recursively processed.
+     The superblock need not be because all blocks are
+     processed from relocate_blockvector.
+     The function need not be because it will be processed
+     under the block which is its scope.  */
+  RELOCATE (BLOCK_SUPERBLOCK (bp));
+  RELOCATE (BLOCK_FUNCTION (bp));
+
+  for (i = 0; i < nsyms; i++)
+    RELOCATE (BLOCK_SYM (bp, i));
+
+  for (i = 0; i < nsyms; i++)
+    relocate_symbol (BLOCK_SYM (bp, i));
+}
+
+static void
+relocate_symbol (sp)
+     register struct symbol *sp;
+{
+  RELOCATE (SYMBOL_NAME (sp));
+  if (SYMBOL_CLASS (sp) == LOC_BLOCK)
+    {
+      RELOCATE (SYMBOL_BLOCK_VALUE (sp));
+      /* We can assume the block that belongs to this symbol
+        is not relocated yet, since it comes after
+        the block that contains this symbol.  */
+      BLOCK_FUNCTION (SYMBOL_BLOCK_VALUE (sp)) = sp;
+      UNRELOCATE (BLOCK_FUNCTION (SYMBOL_BLOCK_VALUE (sp)));
+    }
+  else if (SYMBOL_CLASS (sp) == LOC_STATIC)
+    CORE_RELOCATE (SYMBOL_VALUE (sp));
+  else if (SYMBOL_CLASS (sp) == LOC_LABEL)
+    TEXT_RELOCATE (SYMBOL_VALUE (sp));
+  RELOCATE (SYMBOL_TYPE (sp));
+}
+
+/* We cannot come up with an a priori spanning tree
+   for the network of types, since types can be used
+   for many symbols and also as components of other types.
+   Therefore, we need to be able to mark types that we
+   already have relocated (or are already in the middle of relocating)
+   as in a garbage collector.  */
+
+static void
+relocate_type (tp)
+     register struct type *tp;
+{
+  register int nfields = TYPE_NFIELDS (tp);
+  register int i;
+
+  RELOCATE (TYPE_NAME (tp));
+  RELOCATE (TYPE_TARGET_TYPE (tp));
+  RELOCATE (TYPE_FIELDS (tp));
+  RELOCATE (TYPE_POINTER_TYPE (tp));
+
+  for (i = 0; i < nfields; i++)
+    {
+      RELOCATE (TYPE_FIELD_TYPE (tp, i));
+      RELOCATE (TYPE_FIELD_NAME (tp, i));
+    }
+}
+\f
+/* Read symsegs from file named NAME open on DESC,
+   make symtabs from them, and return a chain of them.
+   Assumes DESC is prepositioned at the end of the string table,
+   just before the symsegs if there are any.  */
+
+struct symtab *
+read_symsegs (desc, name)
+     int desc;
+     char *name;
+{
+  struct symbol_root root;
+  register char *data;
+  register struct symtab *sp, *chain = 0;
+  register int len;
+
+  while (1)
+    {
+      len = myread (desc, &root, sizeof root);
+      if (len == 0 || root.format == 0)
+       break;
+      if (root.format != 1 ||
+         root.length < sizeof root)
+       error ("Invalid symbol segment format code");
+      data = (char *) xmalloc (root.length);
+      bcopy (&root, data, sizeof root);
+      len = myread (desc, data + sizeof root,
+                   root.length - sizeof root);
+      sp = relocate_symtab (data);
+      sp->next = chain;
+      chain = sp;
+    }
+
+  return chain;
+}
+\f
+static int block_depth ();
+static void print_spaces ();
+static void print_symbol ();
+
+print_symtabs (filename)
+     char *filename;
+{
+  FILE *outfile;
+  register struct symtab *s;
+  register int i, j;
+  int len, line, blen;
+  register struct linetable *l;
+  struct blockvector *bv;
+  register struct block *b;
+  int depth;
+  struct cleanup *cleanups;
+  extern int fclose();
+
+  if (filename == 0)
+    error_no_arg ("file to write symbol data in");
+  outfile = fopen (filename, "w");
+
+  cleanups = make_cleanup (fclose, outfile);
+  immediate_quit++;
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      /* First print the line table.  */
+      fprintf (outfile, "Symtab for file %s\n\n", s->filename);
+      fprintf (outfile, "Line table:\n\n");
+      l = LINETABLE (s);
+      len = l->nitems;
+      for (i = 0; i < len; i++)
+       {
+         if (l->item[i] < 0)
+           line = - l->item[i] - 1;
+         else
+           fprintf (outfile, " line %d at %x\n", ++line, l->item[i]);
+       }
+      /* Now print the block info.  */
+      fprintf (outfile, "\nBlockvector:\n\n");
+      bv = BLOCKVECTOR (s);
+      len = BLOCKVECTOR_NBLOCKS (bv);
+      for (i = 0; i < len; i++)
+       {
+         b = BLOCKVECTOR_BLOCK (bv, i);
+         depth = block_depth (b) * 2;
+         print_spaces (depth, outfile);
+         fprintf (outfile, "block #%03d (object 0x%x) ", i, b);
+         fprintf (outfile, "[0x%x..0x%x]", BLOCK_START (b), BLOCK_END (b));
+         if (BLOCK_SUPERBLOCK (b))
+           fprintf (outfile, " (under 0x%x)", BLOCK_SUPERBLOCK (b));
+         if (BLOCK_FUNCTION (b))
+           fprintf (outfile, " %s", SYMBOL_NAME (BLOCK_FUNCTION (b)));
+         fputc ('\n', outfile);
+         blen = BLOCK_NSYMS (b);
+         for (j = 0; j < blen; j++)
+           {
+             print_symbol (BLOCK_SYM (b, j), depth + 1, outfile);
+           }
+       }
+
+      fprintf (outfile, "\n\n");
+    }
+
+  immediate_quit--;
+  do_cleanups (cleanups);
+}
+
+static void
+print_symbol (symbol, depth, outfile)
+     struct symbol *symbol;
+     int depth;
+     FILE *outfile;
+{
+  print_spaces (depth, outfile);
+  if (SYMBOL_NAMESPACE (symbol) == LABEL_NAMESPACE)
+    {
+      fprintf (outfile, "label %s at 0x%x", SYMBOL_NAME (symbol),
+              SYMBOL_VALUE (symbol));
+      return;
+    }
+  if (SYMBOL_NAMESPACE (symbol) == STRUCT_NAMESPACE)
+    {
+      if (TYPE_NAME (SYMBOL_TYPE (symbol)))
+       {
+         type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth);
+       }
+      else
+       {
+         fprintf (outfile, "%s %s = ",
+              (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_ENUM
+               ? "enum"
+               : (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_STRUCT
+                  ? "struct" : "union")),
+              SYMBOL_NAME (symbol));
+         type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth);
+       }
+      fprintf (outfile, ";\n");
+    }
+  else
+    {
+      if (SYMBOL_CLASS (symbol) == LOC_TYPEDEF)
+       fprintf (outfile, "typedef ");
+      if (SYMBOL_TYPE (symbol))
+       {
+         type_print_1 (SYMBOL_TYPE (symbol), SYMBOL_NAME (symbol),
+                       outfile, 1, depth);
+         fprintf (outfile, "; ");
+       }
+      else
+       fprintf (outfile, "%s ", SYMBOL_NAME (symbol));
+
+      switch (SYMBOL_CLASS (symbol))
+       {
+       case LOC_CONST:
+         fprintf (outfile, "const %d (0x%x),",
+                  SYMBOL_VALUE (symbol), SYMBOL_VALUE (symbol));
+         break;
+
+       case LOC_CONST_BYTES:
+         fprintf (outfile, "const %d hex bytes:",
+                  TYPE_LENGTH (SYMBOL_TYPE (symbol)));
+         {
+           int i;
+           for (i = 0; i < TYPE_LENGTH (SYMBOL_TYPE (symbol)); i++)
+             fprintf (outfile, " %2x", SYMBOL_VALUE_BYTES (symbol) [i]);
+           fprintf (outfile, ",");
+         }
+         break;
+
+       case LOC_STATIC:
+         fprintf (outfile, "static at 0x%x,", SYMBOL_VALUE (symbol));
+         break;
+
+       case LOC_REGISTER:
+         fprintf (outfile, "register %d,", SYMBOL_VALUE (symbol));
+         break;
+
+       case LOC_ARG:
+         fprintf (outfile, "arg at 0x%x,", SYMBOL_VALUE (symbol));
+         break;
+
+       case LOC_LOCAL:
+         fprintf (outfile, "local at 0x%x,", SYMBOL_VALUE (symbol));
+         break;
+
+       case LOC_TYPEDEF:
+         break;
+
+       case LOC_LABEL:
+         fprintf (outfile, "label at 0x%x", SYMBOL_VALUE (symbol));
+         break;
+
+       case LOC_BLOCK:
+         fprintf (outfile, "block (object 0x%x) starting at 0x%x,",
+                  SYMBOL_VALUE (symbol),
+                  BLOCK_START (SYMBOL_BLOCK_VALUE (symbol)));
+         break;
+       }
+    }
+  fprintf (outfile, "\n");
+}
+
+/* Return the nexting depth of a block within other blocks in its symtab.  */
+
+static int
+block_depth (block)
+     struct block *block;
+{
+  register int i = 0;
+  while (block = BLOCK_SUPERBLOCK (block)) i++;
+  return i;
+}
+\f
+static
+initialize ()
+{
+  add_com ("printsyms", class_obscure, print_symtabs,
+          "Print dump of current symbol definitions to file OUTFILE.");
+}
+
+END_FILE
diff --git a/gdb/symseg.h b/gdb/symseg.h
new file mode 100644 (file)
index 0000000..11f4807
--- /dev/null
@@ -0,0 +1,323 @@
+/* GDB symbol table format definitions.
+   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!
+*/
+
+/* Format of GDB symbol table data.
+   There is one symbol segment for each source file or
+   independant compilation.  These segments are simply concatenated
+   to form the GDB symbol table.  A zero word where the beginning
+   of a segment is expected indicates there are no more segments.
+
+Format of a symbol segment:
+
+   The symbol segment begins with a word containing 1
+   if it is in the format described here.  Other formats may
+   be designed, with other code numbers.
+
+   The segment contains many objects which point at each other.
+   The pointers are offsets in bytes from the beginning of the segment.
+   Thus, each segment can be loaded into core and its pointers relocated
+   to make valid in-core pointers.
+
+   All the data objects in the segment can be found indirectly from
+   one of them, the root object, of type `struct symbol_root'.
+   It appears at the beginning of the segment.
+
+   The total size of the segment, in bytes, appears as the `length'
+   field of this object.  This size includes the size of the
+   root object.
+
+   All the object data types are defined here to contain pointer types
+   appropriate for in-core use on a relocated symbol segment.
+   Casts to and from type int are required for working with
+   unrelocated symbol segments such as are found in the file.
+
+   The ldsymaddr word is filled in by the loader to contain
+   the offset (in bytes) within the ld symbol table
+   of the first nonglobal symbol from this compilation.
+   This makes it possible to match those symbols
+   (which contain line number information) reliably with
+   the segment they go with.
+
+   Core addresses within the program that appear in the symbol segment
+   are not relocated by the loader.  They are inserted by the assembler
+   and apply to addresses as output by the assembler, so GDB must
+   relocate them when it loads the symbol segment.  It gets the information
+   on how to relocate from the textrel, datarel, bssrel, databeg and bssbeg
+   words of the root object.
+
+   The words textrel, datarel and bssrel
+   are filled in by ld with the amounts to relocate within-the-file
+   text, data and bss addresses by; databeg and bssbeg can be
+   used to tell which kind of relocation an address needs.  */
+
+enum language {language_c};
+
+struct symbol_root
+{
+  int format;                  /* Data format version */
+  int length;                  /* # bytes in this symbol segment */
+  int ldsymoff;                        /* Offset in ld symtab of this file's syms */
+  int textrel;                 /* Relocation for text addresses */
+  int datarel;                 /* Relocation for data addresses */
+  int bssrel;                  /* Relocation for bss addresses */
+  char *filename;              /* Name of source file compiled */
+  char *filedir;               /* Name of directory it was reached from */
+  struct blockvector *blockvector; /* Vector of all symbol naming blocks */
+  struct typevector *typevector; /* Vector of all data types */
+  enum language language;      /* Code identifying the language used */
+  char *version;               /* Version info.  Not fully specified */
+  char *compilation;           /* Compilation info.  Not fully specified */
+  int databeg;                 /* Address within the file of data start */
+  int bssbeg;                  /* Address within the file of bss start */
+};
+\f
+/* All data types of symbols in the compiled program
+   are represented by `struct type' objects.
+   All of these objects are pointed to by the typevector.
+   The type vector may have empty slots that contain zero.  */
+
+struct typevector
+{
+  int length;
+  struct type *type[1];
+};
+
+/* Different kinds of data types are distinguished by the `code' field.  */
+
+enum type_code
+{
+  TYPE_CODE_UNDEF,             /* Not used; catches errors */
+  TYPE_CODE_PTR,               /* Pointer type */
+  TYPE_CODE_ARRAY,             /* Array type, lower bound zero */
+  TYPE_CODE_STRUCT,            /* C struct or Pascal record */
+  TYPE_CODE_UNION,             /* C union or Pascal variant part */
+  TYPE_CODE_ENUM,              /* Enumeration type */
+  TYPE_CODE_FUNC,              /* Function type */
+  TYPE_CODE_INT,               /* Integer type */
+  TYPE_CODE_FLT,               /* Floating type */
+  TYPE_CODE_VOID,              /* Void type (values zero length) */
+  TYPE_CODE_SET,               /* Pascal sets */
+  TYPE_CODE_RANGE,             /* Range (integers within spec'd bounds) */
+  TYPE_CODE_PASCAL_ARRAY,      /* Array with explicit type of index */
+};
+
+/* 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.  */
+
+struct type
+{
+  /* Code for kind of type */
+  enum type_code code;
+  /* Name of this type, or zero if none.
+     This is used for printing only.
+     Type names specified as input are defined by symbols.  */
+  char *name;
+  /* Length in bytes of storage for a value of this type */
+  int length;
+  /* For a pointer type, describes the type of object pointed to.
+     For an array type, describes the type of the elements.
+     For a function type, describes the type of the value.
+     Unused otherwise.  */
+  struct type *target_type;
+  /* Type that is a pointer to this type.
+     Zero if no such pointer-to type is known yet.
+     The debugger may add the address of such a type
+     if it has to construct one later.  */ 
+  struct type *pointer_type;
+  /* Type that is a function returning this type.
+     Zero if no such function type is known here.
+     The debugger may add the address of such a type
+     if it has to construct one later.  */
+  struct type *function_type;
+  /* Flags about this type.  */
+  short flags;
+  /* Number of fields described for this type */
+  short nfields;
+  /* For structure and union types, a description of each field.
+     For set and pascal array types, there is one "field",
+     whose type is the domain type of the set or array.
+     For range types, there are two "fields",
+     the minimum and maximum values (both inclusive).
+     For enum types, each possible value is described by one "field".
+     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
+     because we can allocate the space for a type before
+     we know what to put in it.  */
+  struct field
+    {
+      /* Position of this field, counting in bits from start of
+        containing structure.  For a function type, this is the
+        position in the argument list of this argument.
+        For a range bound or enum value, this is the value itself.  */
+      int bitpos;
+      /* Size of this field, in bits, or zero if not packed.
+        For an unpacked field, the field's type's length
+        says how many bytes the field occupies.  */
+      int bitsize;
+      /* In a struct or enum type, type of this field.
+        In a function type, type of this argument.
+        In an array type, the domain-type of the array.  */
+      struct type *type;
+      /* Name of field, value or argument.
+        Zero for range bounds and array domains.  */
+      char *name;
+    } *fields;
+};
+\f
+/* All of the name-scope contours of the program
+   are represented by `struct block' objects.
+   All of these objects are pointed to by the blockvector.
+
+   Each block represents one name scope.
+   Each lexical context has its own block.
+
+   The first two blocks in the blockvector are special.
+   The first one contains all the symbols defined in this compilation
+   whose scope is the entire program linked together.
+   The second one contains all the symbols whose scope is the
+   entire compilation excluding other separate compilations.
+   In C, these correspond to global symbols and static symbols.
+
+   Each block records a range of core addresses for the code that
+   is in the scope of the block.  The first two special blocks
+   give, for the range of code, the entire range of code produced
+   by the compilation that the symbol segment belongs to.
+
+   The blocks appear in the blockvector
+   in order of increasing starting-address,
+   and, within that, in order of decreasing ending-address.
+
+   This implies that within the body of one function
+   the blocks appear in the order of a depth-first tree walk.  */
+
+struct blockvector
+{
+  /* Number of blocks in the list.  */
+  int nblocks;
+  /* The blocks themselves.  */
+  struct block *block[1];
+};
+
+struct block
+{
+  /* Addresses in the executable code that are in this block.
+     Note: in an unrelocated symbol segment in a file,
+     these are always zero.  They can be filled in from the
+     N_LBRAC and N_RBRAC symbols in the loader symbol table.  */
+  int startaddr, endaddr;
+  /* The symbol that names this block,
+     if the block is the body of a function;
+     otherwise, zero.
+     Note: In an unrelocated symbol segment in an object file,
+     this field may be zero even when the block has a name.
+     That is because the block is output before the name
+     (since the name resides in a higher block).
+     Since the symbol does point to the block (as its value),
+     it is possible to find the block and set its name properly.  */
+  struct symbol *function;
+  /* The `struct block' for the containing block, or 0 if none.  */
+  /* Note that in an unrelocated symbol segment in an object file
+     this pointer may be zero when the correct value should be
+     the second special block (for symbols whose scope is one compilation).
+     This is because the compiler ouptuts the special blocks at the
+     very end, after the other blocks.   */
+  struct block *superblock;
+  /* Number of local symbols.  */
+  int nsyms;
+  /* The symbols.  */
+  struct symbol *sym[1];
+};
+\f
+/* Represent one symbol name; a variable, constant, function or typedef.  */
+
+/* Different name spaces for symbols.  Looking up a symbol specifies
+   a namespace and ignores symbol definitions in other name spaces.
+
+   VAR_NAMESPACE is the usual namespace.
+   In C, this contains variables, function names, typedef names
+   and enum type values.
+
+   STRUCT_NAMESPACE is used in C to hold struct, union and enum type names.
+   Thus, if `struct foo' is used in a C program,
+   it produces a symbol named `foo' in the STRUCT_NAMESPACE.
+
+   LABEL_NAMESPACE may be used for names of labels (for gotos);
+   currently it is not used and labels are not recorded at all.  */
+
+/* For a non-global symbol allocated statically,
+   the correct core address cannot be determined by the compiler.
+   The compiler puts an index number into the symbol's value field.
+   This index number can be matched with the "desc" field of
+   an entry in the loader symbol table.  */
+
+enum namespace
+{
+  UNDEF_NAMESPACE, VAR_NAMESPACE, STRUCT_NAMESPACE, LABEL_NAMESPACE,
+};
+
+/* An address-class says where to find the value of the symbol in core.  */
+
+enum address_class
+{
+  LOC_UNDEF,           /* Not used; catches errors */
+  LOC_CONST,           /* Value is constant int */
+  LOC_STATIC,          /* Value is at fixed address */
+  LOC_REGISTER,                /* Value is in register */
+  LOC_ARG,             /* Value is at spec'd position in arglist */
+  LOC_LOCAL,           /* Value is at spec'd pos in stack frame */
+  LOC_TYPEDEF,         /* Value not used; definition in SYMBOL_TYPE
+                          Symbols in the namespace STRUCT_NAMESPACE
+                          all have this class.  */
+  LOC_LABEL,           /* Value is address in the code */
+  LOC_BLOCK,           /* Value is address of a `struct block'.
+                          Function names have this class.  */
+  LOC_EXTERNAL,                /* Value is at address not in this compilation.
+                          This is used for .comm symbols
+                          and for extern symbols within functions.
+                          Inside GDB, this is changed to LOC_STATIC once the
+                          real address is obtained from a loader symbol.  */
+  LOC_CONST_BYTES      /* Value is a constant byte-sequence.   */
+};
+
+struct symbol
+{
+  /* Symbol name */
+  char *name;
+  /* Name space code.  */
+  enum namespace namespace;
+  /* Address class */
+  enum address_class class;
+  /* Data type of value */
+  struct type *type;
+  /* constant value, or address if static, or register number,
+     or offset in arguments, or offset in stack frame.  */
+  union
+    {
+      long value;
+      struct block *block;      /* for LOC_BLOCK */
+      char *bytes;             /* for LOC_CONST_BYTES */
+    }
+  value;
+};
diff --git a/gdb/symtab.c b/gdb/symtab.c
new file mode 100644 (file)
index 0000000..a413bfa
--- /dev/null
@@ -0,0 +1,1099 @@
+/* Symbol table lookup for the GNU debugger, 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 "defs.h"
+#include "initialize.h"
+#include "symtab.h"
+#include "param.h"
+
+#include <stdio.h>
+#include <obstack.h>
+
+#ifdef mac_aux
+#define REGCMP
+#endif
+
+START_FILE
+
+/* Allocate an obstack to hold objects that should be freed
+   when we load a new symbol table.
+   This includes the symbols made by dbxread
+   and the types that are not permanent.  */
+
+struct obstack obstack1;
+
+struct obstack *symbol_obstack = &obstack1;
+
+/* These variables point to the objects
+   representing the predefined C data types.  */
+
+struct type *builtin_type_void;
+struct type *builtin_type_char;
+struct type *builtin_type_short;
+struct type *builtin_type_int;
+struct type *builtin_type_long;
+struct type *builtin_type_unsigned_char;
+struct type *builtin_type_unsigned_short;
+struct type *builtin_type_unsigned_int;
+struct type *builtin_type_unsigned_long;
+struct type *builtin_type_float;
+struct type *builtin_type_double;
+
+/* Lookup the symbol table of a source file named NAME.  */
+
+struct symtab *
+lookup_symtab (name)
+     char *name;
+{
+  register struct symtab *s;
+  register char *copy;
+
+  for (s = symtab_list; s; s = s->next)
+    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 = symtab_list; s; s = s->next)
+    if (!strcmp (copy, s->filename))
+      return s;
+
+  return 0;
+}
+\f
+/* Lookup a typedef or primitive type named NAME,
+   visible in lexical block BLOCK.
+   If NOERR is nonzero, return zero if NAME is not suitably defined.  */
+
+struct type *
+lookup_typename (name, block, noerr)
+     char *name;
+     struct block *block;
+     int noerr;
+{
+  register struct symbol *sym = lookup_symbol (name, block, VAR_NAMESPACE);
+  if (sym == 0 || SYMBOL_CLASS (sym) != LOC_TYPEDEF)
+    {
+      if (!strcmp (name, "int"))
+       return builtin_type_int;
+      if (!strcmp (name, "long"))
+       return builtin_type_long;
+      if (!strcmp (name, "short"))
+       return builtin_type_short;
+      if (!strcmp (name, "char"))
+       return builtin_type_char;
+      if (!strcmp (name, "float"))
+       return builtin_type_float;
+      if (!strcmp (name, "double"))
+       return builtin_type_double;
+      if (!strcmp (name, "void"))
+       return builtin_type_void;
+
+      if (noerr)
+       return 0;
+      error ("No type named %s.", name);
+    }
+  return SYMBOL_TYPE (sym);
+}
+
+struct type *
+lookup_unsigned_typename (name)
+     char *name;
+{
+  if (!strcmp (name, "int"))
+    return builtin_type_unsigned_int;
+  if (!strcmp (name, "long"))
+    return builtin_type_unsigned_long;
+  if (!strcmp (name, "short"))
+    return builtin_type_unsigned_short;
+  if (!strcmp (name, "char"))
+    return builtin_type_unsigned_char;
+  error ("No type named unsigned %s.", name);
+}
+
+/* Lookup a structure type named "struct NAME",
+   visible in lexical block BLOCK.  */
+
+struct type *
+lookup_struct (name, block)
+     char *name;
+     struct block *block;
+{
+  register struct symbol *sym = lookup_symbol (name, block, STRUCT_NAMESPACE);
+  if (sym == 0)
+    error ("No struct type named %s.", name);
+  if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_STRUCT)
+    error ("This context has union or enum %s, not a struct.", name);
+  return SYMBOL_TYPE (sym);
+}
+
+/* Lookup a union type named "union NAME",
+   visible in lexical block BLOCK.  */
+
+struct type *
+lookup_union (name, block)
+     char *name;
+     struct block *block;
+{
+  register struct symbol *sym = lookup_symbol (name, block, STRUCT_NAMESPACE);
+  if (sym == 0)
+    error ("No union type named %s.", name);
+  if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_UNION)
+    error ("This context has struct or enum %s, not a union.", name);
+  return SYMBOL_TYPE (sym);
+}
+
+/* Lookup an enum type named "enum NAME",
+   visible in lexical block BLOCK.  */
+
+struct type *
+lookup_enum (name, block)
+     char *name;
+     struct block *block;
+{
+  register struct symbol *sym = lookup_symbol (name, block, STRUCT_NAMESPACE);
+  if (sym == 0)
+    error ("No enum type named %s.", name);
+  if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_ENUM)
+    error ("This context has struct or union %s, not an enum.", name);
+  return SYMBOL_TYPE (sym);
+}
+
+/* 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.  */
+
+struct type *
+lookup_pointer_type (type)
+     struct type *type;
+{
+  register struct type *ptype = TYPE_POINTER_TYPE (type);
+  if (ptype) return ptype;
+
+  /* This is the first time anyone wanted a pointer to a TYPE.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    ptype  = (struct type *) xmalloc (sizeof (struct type));
+  else
+    ptype  = (struct type *) obstack_alloc (symbol_obstack,
+                                           sizeof (struct type));
+
+  bzero (ptype, sizeof (struct type));
+  TYPE_TARGET_TYPE (ptype) = type;
+  TYPE_POINTER_TYPE (type) = ptype;
+  /* New type is permanent if type pointed to is permanent.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    TYPE_FLAGS (ptype) |= TYPE_FLAG_PERM;
+  /* We assume the machine has only one representation for pointers!  */
+  TYPE_LENGTH (ptype) = sizeof (char *);
+  TYPE_CODE (ptype) = TYPE_CODE_PTR;
+  return ptype;
+}
+
+/* Given a type TYPE, return a type of functions that return that type.
+   May need to construct such a type if this is the first use.  */
+
+struct type *
+lookup_function_type (type)
+     struct type *type;
+{
+  register struct type *ptype = TYPE_FUNCTION_TYPE (type);
+  if (ptype) return ptype;
+
+  /* This is the first time anyone wanted a function returning a TYPE.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    ptype  = (struct type *) xmalloc (sizeof (struct type));
+  else
+    ptype  = (struct type *) obstack_alloc (symbol_obstack,
+                                           sizeof (struct type));
+
+  bzero (ptype, sizeof (struct type));
+  TYPE_TARGET_TYPE (ptype) = type;
+  TYPE_FUNCTION_TYPE (type) = ptype;
+  /* New type is permanent if type returned is permanent.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    TYPE_FLAGS (ptype) |= TYPE_FLAG_PERM;
+  TYPE_LENGTH (ptype) = 1;
+  TYPE_CODE (ptype) = TYPE_CODE_FUNC;
+  TYPE_NFIELDS (ptype) = 0;
+  return ptype;
+}
+\f
+/* Smash TYPE to be a type of pointers to TO_TYPE.
+   If TO_TYPE is not permanent and has no pointer-type yet,
+   record TYPE as its pointer-type.  */
+
+void
+smash_to_pointer_type (type, to_type)
+     struct type *type, *to_type;
+{
+  bzero (type, sizeof (struct type));
+  TYPE_TARGET_TYPE (type) = to_type;
+  /* We assume the machine has only one representation for pointers!  */
+  TYPE_LENGTH (type) = sizeof (char *);
+  TYPE_CODE (type) = TYPE_CODE_PTR;
+
+  if (TYPE_POINTER_TYPE (to_type) == 0
+      && !(TYPE_FLAGS (type) & TYPE_FLAG_PERM))
+    {
+      TYPE_POINTER_TYPE (to_type) = type;
+    }
+}
+
+/* Smash TYPE to be a type of functions returning TO_TYPE.
+   If TO_TYPE is not permanent and has no function-type yet,
+   record TYPE as its function-type.  */
+
+void
+smash_to_function_type (type, to_type)
+     struct type *type, *to_type;
+{
+  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_FUNCTION_TYPE (to_type) == 0
+      && !(TYPE_FLAGS (type) & TYPE_FLAG_PERM))
+    {
+      TYPE_FUNCTION_TYPE (to_type) = type;
+    }
+}
+\f
+static struct symbol *lookup_block_symbol ();
+
+/* Find the definition for a specified symbol name NAME
+   in namespace NAMESPACE, visible from lexical block BLOCK.
+   Returns the struct symbol pointer, or zero if no symbol is found.  */
+
+struct symbol *
+lookup_symbol (name, block, namespace)
+     char *name;
+     register struct block *block;
+     enum namespace namespace;
+{
+  register int i, n;
+  register struct symbol *sym;
+  register struct symtab *s;
+  struct blockvector *bv;
+
+  /* Search specified block and its superiors.  */
+
+  while (block != 0)
+    {
+      sym = lookup_block_symbol (block, name, namespace);
+      if (sym) return sym;
+      block = BLOCK_SUPERBLOCK (block);
+    }
+
+  /* Now search all symtabs' global blocks.  */
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      bv = BLOCKVECTOR (s);
+      block = BLOCKVECTOR_BLOCK (bv, 0);
+      sym = lookup_block_symbol (block, name, namespace);
+      if (sym) return sym;
+    }
+
+  /* Now search all symtabs' per-file blocks.
+     Not strictly correct, but more useful than an error.  */
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      bv = BLOCKVECTOR (s);
+      block = BLOCKVECTOR_BLOCK (bv, 1);
+      sym = lookup_block_symbol (block, name, namespace);
+      if (sym) return sym;
+    }
+  return 0;
+}
+
+/* Look for a symbol in block BLOCK using binary search.  */
+
+static struct symbol *
+lookup_block_symbol (block, name, namespace)
+     register struct block *block;
+     char *name;
+     enum namespace namespace;
+{
+  register int bot, top, inc;
+  register struct symbol *sym;
+
+  top = BLOCK_NSYMS (block);
+  bot = 0;
+
+  /* First, advance BOT to not far before
+     the first symbol whose name is NAME.  */
+
+  while (1)
+    {
+      inc = (top - bot + 1);
+      /* No need to keep binary searching for the last few bits worth.  */
+      if (inc < 7)
+       break;
+      inc >>= 1;
+      sym = BLOCK_SYM (block, bot + inc);
+      if (strcmp (SYMBOL_NAME (sym), name) < 0)
+       bot += inc;
+      else
+       top = bot + inc;
+    }
+
+  /* Now scan forward until we run out of symbols,
+     find one whose name is greater than NAME,
+     or find one we want.
+     If there is more than one symbol with the right name and namespace,
+     we return the first one.  dbxread.c is careful to make sure
+     that if one is a register then it comes first.  */
+
+  top = BLOCK_NSYMS (block);
+  while (bot < top)
+    {
+      sym = BLOCK_SYM (block, bot);
+      inc = strcmp (SYMBOL_NAME (sym), name);
+      if (inc == 0 && SYMBOL_NAMESPACE (sym) == namespace)
+       return sym;
+      if (inc > 0)
+       return 0;
+      bot++;
+    }
+  return 0;
+}
+\f
+/* Return the symbol for the function which contains a specified
+   lexical block, described by a struct block BL.  */
+
+struct symbol *
+block_function (bl)
+     struct block *bl;
+{
+  while (BLOCK_FUNCTION (bl) == 0 && BLOCK_SUPERBLOCK (bl) != 0)
+    bl = BLOCK_SUPERBLOCK (bl);
+
+  return BLOCK_FUNCTION (bl);
+}
+
+/* Subroutine of find_pc_line */
+
+static struct symtab *
+find_pc_symtab (pc)
+     register CORE_ADDR pc;
+{
+  register struct block *b;
+  struct blockvector *bv;
+  register struct symtab *s;
+
+  /* Search all symtabs for one whose file contains our pc */
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      bv = BLOCKVECTOR (s);
+      b = BLOCKVECTOR_BLOCK (bv, 0);
+      if (BLOCK_START (b) <= pc
+         && BLOCK_END (b) > pc)
+       break;
+    }
+
+  return s;
+}
+
+/* Find the source file and line number for a given PC value.
+   Return a structure containing a symtab pointer, a line number,
+   and a pc range for the entire source line.
+   The value's .pc field is NOT the specified pc.
+   NOTCURRENT nonzero means, if specified pc is on a line boundary,
+   use the line that ends there.  Otherwise, in that case, the line
+   that begins there is used.  */
+
+struct symtab_and_line
+find_pc_line (pc, notcurrent)
+     CORE_ADDR pc;
+     int notcurrent;
+{
+  struct symtab *s;
+  register struct linetable *l;
+  register int len;
+  register int i, item;
+  int line;
+  struct symtab_and_line value;
+  struct blockvector *bv;
+
+  /* Info on best line seen so far, and where it starts, and its file.  */
+
+  int best_line = 0;
+  CORE_ADDR best_pc = 0;
+  CORE_ADDR best_end = 0;
+  struct symtab *best_symtab = 0;
+
+  /* Store here the first line number
+     of a file which contains the line at the smallest pc after PC.
+     If we don't find a line whose range contains PC,
+     we will use a line one less than this,
+     with a range from the start of that file to the first line's pc.  */
+  int alt_line = 0;
+  CORE_ADDR alt_pc = 0;
+  struct symtab *alt_symtab = 0;
+
+  /* Info on best line seen in this file.  */
+
+  int prev_line;
+  CORE_ADDR prev_pc;
+
+  /* Info on first line of this file.  */
+
+  int first_line;
+  CORE_ADDR first_pc;
+
+  /* If this pc is not from the current frame,
+     it is the address of the end of a call instruction.
+     Quite likely that is the start of the following statement.
+     But what we want is the statement containing the instruction.
+     Fudge the pc to make sure we get that.  */
+
+  if (notcurrent) pc -= 1;
+
+  s = find_pc_symtab (pc);
+  if (s == 0)
+    {
+      value.symtab = 0;
+      value.line = 0;
+      value.pc = pc;
+      return value;
+    }
+
+  bv = BLOCKVECTOR (s);
+
+  /* Look at all the symtabs that share this blockvector.
+     They all have the same apriori range, that we found was right;
+     but they have different line tables.  */
+
+  for (; s && BLOCKVECTOR (s) == bv; s = s->next)
+    {
+      /* Find the best line in this symtab.  */
+      l = LINETABLE (s);
+      len = l->nitems;
+      prev_line = -1;
+      first_line = -1;
+      for (i = 0; i < len; i++)
+       {
+         item = l->item[i];
+         if (item < 0)
+           line = - item - 1;
+         else
+           {
+             line++;
+             if (first_line < 0)
+               {
+                 first_line = line;
+                 first_pc = item;
+               }
+             /* Return the last line that did not start after PC.  */
+             if (pc >= item)
+               {
+                 prev_line = line;
+                 prev_pc = item;
+               }
+             else
+               break;
+           }
+       }
+
+      /* Is this file's best line closer than the best in the other files?
+        If so, record this file, and its best line, as best so far.  */
+      if (prev_line >= 0 && prev_pc > best_pc)
+       {
+         best_pc = prev_pc;
+         best_line = prev_line;
+         best_symtab = s;
+         if (i < len)
+           best_end = item;
+         else
+           best_end = 0;
+       }
+      /* Is this file's first line closer than the first lines of other files?
+        If so, record this file, and its first line, as best alternate.  */
+      if (first_line >= 0 && first_pc > pc
+         && (alt_pc == 0 || first_pc < alt_pc))
+       {
+         alt_pc = first_pc;
+         alt_line = first_line;
+         alt_symtab = s;
+       }
+    }
+  if (best_symtab == 0)
+    {
+      value.symtab = alt_symtab;
+      value.line = alt_line - 1;
+      value.pc = BLOCK_END (BLOCKVECTOR_BLOCK (bv, 0));
+      value.end = alt_pc;
+    }
+  else
+    {
+      value.symtab = best_symtab;
+      value.line = best_line;
+      value.pc = best_pc;
+      value.end = (best_end ? best_end
+                  : (alt_pc ? alt_pc
+                     : BLOCK_END (BLOCKVECTOR_BLOCK (bv, 0))));
+    }
+  return value;
+}
+
+/* Find the range of pc values in a line.
+   Store the starting pc of the line into *STARTPTR
+   and the ending pc (start of next line) into *ENDPTR.
+   Returns 1 to indicate success.
+   Returns 0 if could not find the specified line.  */
+
+int
+find_line_pc_range (symtab, thisline, startptr, endptr)
+     struct symtab *symtab;
+     int thisline;
+     CORE_ADDR *startptr, *endptr;
+{
+  register struct linetable *l;
+  register int i, line, item;
+  int len;
+  register CORE_ADDR prev_pc;
+  CORE_ADDR last_pc;
+
+  if (symtab == 0)
+    return 0;
+
+  l = LINETABLE (symtab);
+  len = l->nitems;
+  prev_pc = -1;
+  for (i = 0; i < len; i++)
+    {
+      item = l->item[i];
+      if (item < 0)
+       line = - item - 1;
+      else
+       {
+         line++;
+         /* As soon as we find a line following the specified one
+            we know the end pc and can return.  */
+         if (line > thisline)
+           {
+             /* If we have not seen an entry for the specified line,
+                assume that means the specified line has zero bytes.  */
+             *startptr = prev_pc == -1 ? item : prev_pc;
+             *endptr = item;
+             return 1;
+           }
+         /* If we see an entry for the specified line,
+            it gives the beginning.  */
+         if (line == thisline)
+           prev_pc = item;
+         last_pc = item;
+       }
+    }
+  if (prev_pc != -1)
+    {
+      /* If we found the specified line but no later line, it's file's last.
+        Its range is from line's pc to file's end pc.  */
+      *startptr = last_pc;
+      *endptr = BLOCK_END (BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), 0));
+      return 1;
+    }
+
+  return 0;
+}
+
+/* Find the PC value for a given source file and line number.
+   Returns zero for invalid line number.
+   The source file is specified with a struct symtab.  */
+
+CORE_ADDR
+find_line_pc (symtab, line)
+     struct symtab *symtab;
+     int line;
+{
+  register struct linetable *l;
+  register int len;
+  register int i;
+  register int item;
+  register int nextline = -1;
+
+  if (line <= 0)
+    return 0;
+
+  l = LINETABLE (symtab);
+  len = l->nitems;
+  for (i = 0; i < len; i++)
+    {
+      item = l->item[i];
+      if (item < 0)
+       nextline = - item - 1;
+      else
+       {
+         nextline++;
+         if (line <= nextline)
+           return item;
+       }
+    }
+  return 0;
+}
+
+int
+find_pc_line_pc_range (pc, startptr, endptr)
+     CORE_ADDR pc;
+     CORE_ADDR *startptr, *endptr;
+{
+  struct symtab_and_line sal;
+  sal = find_pc_line (pc, 0);
+  *startptr = sal.pc;
+  *endptr = sal.end;
+  return sal.symtab != 0;
+}
+\f
+/* Parse a string that specifies a line number.
+   Pass the address of a char * variable; that variable will be
+   advanced over the characters actually parsed.
+
+   The string can be:
+
+   LINENUM -- that line number in current file.  PC returned is 0.
+   FILE:LINENUM -- that line in that file.  PC returned is 0.
+   FUNCTION -- line number of openbrace of that function.
+      PC returned is the start of the function.
+   FILE:FUNCTION -- likewise, but prefer functions in that file.
+   *EXPR -- line in which address EXPR appears.
+
+   FUNCTION may be an undebuggable function found in misc_function_vector.
+
+   If the argument FUNFIRSTLINE is nonzero, we want the first line
+   of real code inside a function when a function is specified.
+
+   DEFAULT_SYMTAB specifies the file to use if none is specified.
+   It defaults to current_source_symtab.
+   DEFAULT_LINE specifies the line number to use for relative
+   line numbers (that start with signs).  Defaults to current_source_line.
+
+   Note that it is possible to return zero for the symtab
+   if no file is validly specified.  Callers must check that.
+   Also, the line number returned may be invalid.  */
+
+struct symtab_and_line
+decode_line_1 (argptr, funfirstline, default_symtab, default_line)
+     char **argptr;
+     int funfirstline;
+     struct symtab *default_symtab;
+     int default_line;
+{
+  struct symtab_and_line value;
+  register char *p, *p1;
+  register struct symtab *s;
+  register struct symbol *sym;
+  register CORE_ADDR pc;
+  register int i;
+  char *copy;
+
+  /* Defaults have defaults.  */
+
+  if (default_symtab == 0)
+    {
+      default_symtab = current_source_symtab;
+      default_line = current_source_line;
+    }
+
+  /* See if arg is *PC */
+
+  if (**argptr == '*')
+    {
+      (*argptr)++;
+      pc = parse_and_eval_address_1 (argptr);
+      value = find_pc_line (pc, 0);
+      value.pc = pc;
+      return value;
+    }
+
+  /* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
+
+  s = 0;
+
+  for (p = *argptr; *p; p++)
+    {
+      if (p[0] == ':' || p[0] == ' ' || p[0] == '\t')
+       break;
+    }
+  while (p[0] == ' ' || p[0] == '\t') p++;
+
+  if (p[0] == ':')
+    {
+      /* Extract the file name.  */
+      p1 = p;
+      while (p != *argptr && p[-1] == ' ') --p;
+      copy = (char *) alloca (p - *argptr + 1);
+      bcopy (*argptr, copy, p - *argptr);
+      copy[p - *argptr] = 0;
+
+      /* Find that file's data.  */
+      s = lookup_symtab (copy);
+      if (s == 0)
+       {
+         if (symtab_list == 0)
+           error ("No symbol table is loaded.  Use the \"symbol-file\" command.");
+         error ("No source file named %s.", copy);
+       }
+
+      /* Discard the file name from the arg.  */
+      p = p1 + 1;
+      while (*p == ' ' || *p == '\t') p++;
+      *argptr = p;
+    }
+
+  /* S is specified file's symtab, or 0 if no file specified.
+     arg no longer contains the file name.  */
+
+  /* Check whether arg is all digits (and sign) */
+
+  p = *argptr;
+  if (*p == '-' || *p == '+') p++;
+  while (*p >= '0' && *p <= '9')
+    p++;
+
+  if (p != *argptr && (*p == 0 || *p == ' ' || *p == '\t' || *p == ','))
+    {
+      /* We found a token consisting of all digits -- at least one digit.  */
+      enum sign {none, plus, minus} sign = none;
+
+      if (**argptr == '+')
+       sign = plus, (*argptr)++;
+      else if (**argptr == '-')
+       sign = minus, (*argptr)++;
+      value.line = atoi (*argptr);
+      switch (sign)
+       {
+       case plus:
+         if (p == *argptr)
+           value.line = 5;
+         if (s == 0)
+           value.line = default_line + value.line;
+         break;
+       case minus:
+         if (p == *argptr)
+           value.line = 15;
+         if (s == 0)
+           value.line = default_line - value.line;
+         else
+           value.line = 1;
+         break;
+       }
+
+      while (*p == ' ' || *p == '\t') p++;
+      *argptr = p;
+      if (s == 0)
+       s = default_symtab;
+      value.symtab = s;
+      value.pc = 0;
+      return value;
+    }
+
+  /* Arg token is not digits => try it as a function name
+     Find the next token (everything up to end or next whitespace).  */
+  p = *argptr;
+  while (*p && *p != ' ' && *p != '\t' && *p != ',') p++;
+  copy = (char *) alloca (p - *argptr + 1);
+  bcopy (*argptr, copy, p - *argptr);
+  copy[p - *argptr] = 0;
+  while (*p == ' ' || *p == '\t') p++;
+  *argptr = p;
+
+  /* Look up that token as a function.
+     If file specified, use that file's per-file block to start with.  */
+
+  sym = lookup_symbol (copy, s ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 1) : 0,
+                      VAR_NAMESPACE);
+
+  if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+    {
+      /* Arg is the name of a function */
+      pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) + FUNCTION_START_OFFSET;
+      if (funfirstline)
+       SKIP_PROLOGUE (pc);
+      value = find_pc_line (pc, 0);
+      value.pc = (value.end && value.pc != pc) ? value.end : pc;
+      return value;
+    }
+
+  if (sym)
+    error ("%s is not a function.", copy);
+
+  for (i = 0; i < misc_function_count; i++)
+    if (!strcmp (misc_function_vector[i].name, copy))
+      {
+       value.symtab = 0;
+       value.line = 0;
+       value.pc = misc_function_vector[i].address + FUNCTION_START_OFFSET;
+       if (funfirstline)
+         SKIP_PROLOGUE (value.pc);
+       return value;
+      }
+
+  if (symtab_list == 0)
+    error ("No symbol table is loaded.  Use the \"symbol-file\" command.");
+  error ("Function %s not defined.", copy);
+}
+
+struct symtab_and_line
+decode_line_spec (string, funfirstline)
+     char *string;
+     int funfirstline;
+{
+  struct symtab_and_line sal;
+  if (string == 0)
+    error ("Empty line specification.");
+  sal = decode_line_1 (&string, funfirstline,
+                      current_source_symtab, current_source_line);
+  if (*string)
+    error ("Junk at end of line specification: %s", string);
+  return sal;
+}
+\f
+static void
+sources_info ()
+{
+  register struct symtab *s;
+  register int column = 0;
+
+  if (symtab_list == 0)
+    {
+      printf ("No symbol table is loaded.\n");
+      return;
+    }
+  printf ("Source files for which symbol table is known:\n");
+  for (s = symtab_list; s; s = s->next)
+    {
+      if (column != 0 && column + strlen (s->filename) >= 70)
+       {
+         printf ("\n");
+         column = 0;
+       }
+      else if (column != 0)
+       {
+         printf (" ");
+         column++;
+       }
+      printf ("%s", s->filename);
+      column += strlen (s->filename);
+      if (s->next)
+       {
+         printf (",");
+         column++;
+       }
+    }
+  printf ("\n");
+}
+
+/* List all symbols (if REGEXP is 0) or all symbols matching REGEXP.
+   If CLASS is zero, list all symbols except functions and type names.
+   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);         \
+      read_line (); } }
+
+static void
+list_symbols (regexp, class)
+     char *regexp;
+     int class;
+{
+  register struct symtab *s;
+  register struct blockvector *bv;
+  struct blockvector *prev_bv = 0;
+  register struct block *b;
+  register int i, j;
+  register struct symbol *sym;
+  char *val = 0;
+  int found_in_file;
+  static char *classnames[]
+    = {"variable", "function", "type"};
+  int print_count = 0;
+#ifdef REGCMP
+  extern char *regcmp(), *regex(), *loc1;
+#endif
+
+  if (regexp) {
+#ifdef REGCMP
+    val = regcmp(regexp, (char *)0);
+    if (val == 0)
+      error ("Invalid regexp: %s", regexp);
+#else
+    if (val = (char *) re_comp (regexp))
+      error ("Invalid regexp: %s", val);
+#endif
+  }
+
+  printf (regexp
+         ? "All %ss matching regular expression \"%s\":\n"
+         : "All defined %ss:\n",
+         classnames[class],
+         regexp);
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      found_in_file = 0;
+      bv = BLOCKVECTOR (s);
+      /* Often many files share a blockvector.
+        Scan each blockvector only once so that
+        we don't get every symbol many times.
+        It happens that the first symtab in the list
+        for any given blockvector is the main file.  */
+      if (bv != prev_bv)
+       for (i = 0; i < 2; i++)
+         {
+           b = BLOCKVECTOR_BLOCK (bv, i);
+           for (j = 0; j < BLOCK_NSYMS (b); j++)
+             {
+               QUIT;
+               sym = BLOCK_SYM (b, j);
+               if (regexp) {
+#ifdef REGCMP
+                 if (!regex(val, SYMBOL_NAME (sym)))
+                   continue;
+#else
+                 if (!re_exec (SYMBOL_NAME (sym)))
+                   continue;
+#endif
+               }
+               if ((class == 0 && SYMBOL_CLASS (sym) != LOC_TYPEDEF
+                        && SYMBOL_CLASS (sym) != LOC_BLOCK)
+                       || (class == 1 && SYMBOL_CLASS (sym) == LOC_BLOCK)
+                       || (class == 2 && SYMBOL_CLASS (sym) == LOC_TYPEDEF))
+                 {
+                   if (!found_in_file)
+                     {
+                       printf ("\nFile %s:\n", s->filename);
+                       print_count += 2;
+                     }
+                   found_in_file = 1;
+                   MORE;
+                   if (class != 2 && i == 1)
+                     printf ("static ");
+                   if (class == 2
+                       && SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE)
+                     printf ("typedef ");
+
+                   type_print (SYMBOL_TYPE (sym),
+                               (SYMBOL_CLASS (sym) == LOC_TYPEDEF
+                                ? "" : SYMBOL_NAME (sym)),
+                               stdout, 0);
+                   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));
+                   printf (";\n");
+                 }
+             }
+         }
+      prev_bv = bv;
+    }
+#ifdef REGCMP
+    if (val)
+      (void)free(val);
+#endif
+}
+
+static void
+variables_info (regexp)
+     char *regexp;
+{
+  list_symbols (regexp, 0);
+}
+
+static void
+functions_info (regexp)
+     char *regexp;
+{
+  list_symbols (regexp, 1);
+}
+
+static void
+types_info (regexp)
+     char *regexp;
+{
+  list_symbols (regexp, 2);
+}
+\f
+/* Initialize the standard C scalar types.  */
+
+static
+struct type *
+init_type (code, length, uns, name)
+     enum type_code code;
+     int length, uns;
+     char *name;
+{
+  register struct type *type;
+
+  type = (struct type *) xmalloc (sizeof (struct type));
+  bzero (type, sizeof *type);
+  TYPE_CODE (type) = code;
+  TYPE_LENGTH (type) = length;
+  TYPE_FLAGS (type) = uns ? TYPE_FLAG_UNSIGNED : 0;
+  TYPE_FLAGS (type) |= TYPE_FLAG_PERM;
+  TYPE_NFIELDS (type) = 0;
+  TYPE_NAME (type) = name;
+
+  return type;
+}
+
+static
+initialize ()
+{
+  add_info ("variables", variables_info,
+           "All global and static variable names, or those matching REGEXP.");
+  add_info ("functions", functions_info,
+           "All function names, or those matching REGEXP.");
+  add_info ("types", types_info,
+           "All types names, or those matching REGEXP.");
+  add_info ("sources", sources_info,
+           "Source files in the program.");
+
+  obstack_init (symbol_obstack);
+
+  builtin_type_void = init_type (TYPE_CODE_VOID, 0, 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");
+
+  builtin_type_char = init_type (TYPE_CODE_INT, sizeof (char), 0, "char");
+  builtin_type_short = init_type (TYPE_CODE_INT, sizeof (short), 0, "short");
+  builtin_type_long = init_type (TYPE_CODE_INT, sizeof (long), 0, "long");
+  builtin_type_int = init_type (TYPE_CODE_INT, sizeof (int), 0, "int");
+
+  builtin_type_unsigned_char = init_type (TYPE_CODE_INT, sizeof (char), 1, "unsigned char");
+  builtin_type_unsigned_short = init_type (TYPE_CODE_INT, sizeof (short), 1, "unsigned short");
+  builtin_type_unsigned_long = init_type (TYPE_CODE_INT, sizeof (long), 1, "unsigned long");
+  builtin_type_unsigned_int = init_type (TYPE_CODE_INT, sizeof (int), 1, "unsigned int");
+}
+
+END_FILE
diff --git a/gdb/symtab.h b/gdb/symtab.h
new file mode 100644 (file)
index 0000000..4d93355
--- /dev/null
@@ -0,0 +1,228 @@
+/* Symbol table definitions 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!
+*/
+
+/* An obstack to hold objects that should be freed
+   when we load a new symbol table.
+   This includes the symbols made by dbxread
+   and the types that are not permanent.  */
+
+extern struct obstack *symbol_obstack;
+
+/* Some definitions and declarations to go with use of obstacks.  */
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+extern char *xmalloc ();
+extern void free ();
+
+/* gdb can know one or several symbol tables at the same time;
+   the ultimate intent is to have one for each separately-compiled module.
+   Each such symbol table is recorded by a struct symtab, and they
+   are all chained together.  */
+
+/* In addition, gdb can record any number of miscellaneous undebuggable
+   functions' addresses.  In a system that appends _ to function names,
+   the _'s are removed from the names stored in this table.  */
+
+struct misc_function
+{
+  char *name;
+  CORE_ADDR address;
+};
+
+/* Address and length of the vector recording all misc function names/addresses.  */
+
+struct misc_function *misc_function_vector;
+int misc_function_count;
+\f
+#include "symseg.h"
+
+/* Each source file is represented by a struct symtab.
+   These objects are chained through the `next' field.  */
+
+struct symtab
+  {
+    /* Chain of all existing symtabs.  */
+    struct symtab *next;
+    /* List of all symbol scope blocks for this symtab.  */
+    struct blockvector *blockvector;
+    /* Table mapping core addresses to line numbers for this file.  */
+    struct linetable *linetable;
+    /* Vector containing all types defined for this symtab.  */
+    struct typevector *typevector;
+    /* Name of this source file.  */
+    char *filename;
+    /* This component says how to free the data we point to:
+       free_contents => do a tree walk and free each object.
+       free_explicit => free what free_ptr points at, and the linetable.
+       free_nothing => do nothing; some other symtab will free
+         the data this one uses.
+       free_linetable => free just the linetable.  */
+    enum free_code {free_nothing, free_contents, free_explicit, free_linetable}
+      free_code;
+    /* Pointer to one block storage to be freed, if nonzero.  */
+    char *free_ptr;
+    /* Total number of lines found in source file.  */
+    int nlines;
+    /* Array mapping line number to character position.  */
+    int *line_charpos;
+    /* Language of this source file.  */
+    enum language language;
+    /* String of version information.  May be zero.  */
+    char *version;
+    /* String of compilation information.  May be zero.  */
+    char *compilation;
+    /* Offset within loader symbol table
+       of first local symbol for this file.  */
+    int ldsymoff;
+  };
+
+/* This is the list of struct symtab's that gdb considers current.  */
+
+struct symtab *symtab_list;
+
+/* This symtab variable specifies the current file for printing source lines */
+
+struct symtab *current_source_symtab;
+
+/* This is the next line to print for listing source lines.  */
+
+int current_source_line;
+
+#define BLOCKLIST(symtab) (symtab)->blockvector
+#define BLOCKVECTOR(symtab) (symtab)->blockvector
+
+#define TYPEVECTOR(symtab) (symtab)->typevector
+
+#define LINELIST(symtab) (symtab)->linetable
+#define LINETABLE(symtab) (symtab)->linetable
+\f
+/* Recording the code addresses of source lines.  */
+
+struct linetable
+  {
+    int nitems;
+    int item[1];
+  };
+
+/* Each item is either minus a line number, or a program counter.
+   If it represents a line number, that is the line described by the next
+   program counter value.  If it is positive, it is the program
+   counter at which the code for the next line starts.
+
+   Consecutive lines can be recorded by program counter entries
+   with no line number entries between them.  Line number entries
+   are used when there are lines to skip with no code on them.
+   This is to make the table shorter.  */
+\f
+/* Macros normally used to access components of symbol table structures.  */
+
+#define BLOCKLIST_NBLOCKS(blocklist) (blocklist)->nblocks
+#define BLOCKLIST_BLOCK(blocklist,n) (blocklist)->block[n]
+#define BLOCKVECTOR_NBLOCKS(blocklist) (blocklist)->nblocks
+#define BLOCKVECTOR_BLOCK(blocklist,n) (blocklist)->block[n]
+
+#define TYPEVECTOR_NTYPES(typelist) (typelist)->length
+#define TYPEVECTOR_TYPE(typelist,n) (typelist)->type[n]
+
+#define BLOCK_START(bl) (bl)->startaddr
+#define BLOCK_END(bl) (bl)->endaddr
+#define BLOCK_NSYMS(bl) (bl)->nsyms
+#define BLOCK_SYM(bl, n) (bl)->sym[n]
+#define BLOCK_FUNCTION(bl) (bl)->function
+#define BLOCK_SUPERBLOCK(bl) (bl)->superblock
+
+#define SYMBOL_NAME(symbol) (symbol)->name
+#define SYMBOL_NAMESPACE(symbol) (symbol)->namespace
+#define SYMBOL_CLASS(symbol) (symbol)->class
+#define SYMBOL_VALUE(symbol) (symbol)->value.value
+#define SYMBOL_VALUE_BYTES(symbol) (symbol)->value.bytes
+#define SYMBOL_BLOCK_VALUE(symbol) (symbol)->value.block
+#define SYMBOL_TYPE(symbol) (symbol)->type
+
+/* 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
+
+#define TYPE_NAME(thistype) (thistype)->name
+#define TYPE_TARGET_TYPE(thistype) (thistype)->target_type
+#define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type
+#define TYPE_FUNCTION_TYPE(thistype) (thistype)->function_type
+#define TYPE_LENGTH(thistype) (thistype)->length
+#define TYPE_FLAGS(thistype) (thistype)->flags
+#define TYPE_UNSIGNED(thistype) ((thistype)->flags & TYPE_FLAG_UNSIGNED)
+#define TYPE_CODE(thistype) (thistype)->code
+#define TYPE_NFIELDS(thistype) (thistype)->nfields
+#define TYPE_FIELDS(thistype) (thistype)->fields
+
+#define TYPE_FIELD(thistype, n) (thistype)->fields[n]
+#define TYPE_FIELD_TYPE(thistype, n) (thistype)->fields[n].type
+#define TYPE_FIELD_NAME(thistype, n) (thistype)->fields[n].name
+#define TYPE_FIELD_VALUE(thistype, n) (* (int*) &(thistype)->fields[n].type)
+#define TYPE_FIELD_BITPOS(thistype, n) (thistype)->fields[n].bitpos
+#define TYPE_FIELD_BITSIZE(thistype, n) (thistype)->fields[n].bitsize
+#define TYPE_FIELD_PACKED(thistype, n) (thistype)->fields[n].bitsize
+\f
+/* Functions that work on the objects described above */
+
+extern struct symtab *lookup_symtab ();
+extern struct symbol *lookup_symbol ();
+extern struct type *lookup_typename ();
+extern struct type *lookup_unsigned_typename ();
+extern struct type *lookup_struct ();
+extern struct type *lookup_union ();
+extern struct type *lookup_enum ();
+extern struct type *lookup_pointer_type ();
+extern struct type *lookup_function_type ();
+extern struct symbol *block_function ();
+extern struct symbol *find_pc_function ();
+extern int find_pc_misc_function ();
+
+extern struct type *builtin_type_void;
+extern struct type *builtin_type_char;
+extern struct type *builtin_type_short;
+extern struct type *builtin_type_int;
+extern struct type *builtin_type_long;
+extern struct type *builtin_type_unsigned_char;
+extern struct type *builtin_type_unsigned_short;
+extern struct type *builtin_type_unsigned_int;
+extern struct type *builtin_type_unsigned_long;
+extern struct type *builtin_type_float;
+extern struct type *builtin_type_double;
+
+struct symtab_and_line
+{
+  struct symtab *symtab;
+  int line;
+  CORE_ADDR pc;
+  CORE_ADDR end;
+};
+
+/* Given a pc value, return line number it is in.
+   Second arg nonzero means if pc is on the boundary
+   use the previous statement's line number.  */
+
+struct symtab_and_line find_pc_line ();
+
+/* Given a string, return the line specified by it.
+   For commands like "list" and "breakpoint".  */
+
+struct symtab_and_line decode_line_spec ();
+struct symtab_and_line decode_line_1 ();
diff --git a/gdb/test2.c b/gdb/test2.c
new file mode 100644 (file)
index 0000000..e6964f0
--- /dev/null
@@ -0,0 +1,13 @@
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <stdio.h>
+
+main ()
+{
+  struct user u;
+  printf ("&u.u_ar0 - &u = %d, 0%o\n", (int) &u.u_ar0 - (int) &u,
+         (int) &u.u_ar0 - (int) &u);
+  printf ("sizeof (struct pcb) = %d, 0%o\n",
+         sizeof (struct pcb), sizeof (struct pcb));
+}
diff --git a/gdb/test3.c b/gdb/test3.c
new file mode 100644 (file)
index 0000000..cd27cdd
--- /dev/null
@@ -0,0 +1,25 @@
+enum foo {foo1, foo2};
+
+static double statdouble;
+
+newfun (ac)
+     struct haha {int a; } ac;
+{
+}
+
+struct temp {int a; };
+
+bar (a)
+     enum foo a;
+{
+  static int lose;
+  double happy;
+  typedef int myint;
+
+  {
+    union wow { int a; char b; } wowvar;
+    static union wow wowvar1;
+    typedef int yourint;
+    char *winner;
+  }
+}
diff --git a/gdb/testattach.c b/gdb/testattach.c
new file mode 100644 (file)
index 0000000..c56a0fe
--- /dev/null
@@ -0,0 +1,10 @@
+main ()
+{
+  int x = 0;
+
+  while (1)
+    {
+      sleep (1);
+      x++;
+    }
+}
diff --git a/gdb/testbf.c b/gdb/testbf.c
new file mode 100644 (file)
index 0000000..dd661a0
--- /dev/null
@@ -0,0 +1,13 @@
+struct foo
+{
+  int a : 5, : 4, b : 5;
+  char c;
+  int : 3, d : 8, : 0, e : 5;
+};
+
+struct foo x;
+
+main ()
+{
+  printf (x);
+}
diff --git a/gdb/testbit.c b/gdb/testbit.c
new file mode 100644 (file)
index 0000000..9359f0b
--- /dev/null
@@ -0,0 +1,12 @@
+struct foo
+{
+  unsigned bar : 1;
+  unsigned lose : 1;
+};
+
+main ()
+{
+  struct foo *win;
+
+  printf ("%d, %d\n", win->bar, win->lose);
+}
diff --git a/gdb/testenum.c b/gdb/testenum.c
new file mode 100644 (file)
index 0000000..3d85f5e
--- /dev/null
@@ -0,0 +1,25 @@
+/* Source file for showing ENUM lossage in GDB.
+   Compile with "cc -o foo -g foo.c".  */
+
+enum bar { value1, value2, value3 };
+
+struct foo {
+  enum bar enum_value;
+  int int_value;
+  char *pointer_value;
+};
+
+struct foo foo_instance;
+struct foo *foo_instance_pointer;
+
+main ()
+{
+  foo_instance_pointer = &foo_instance;
+  foo_instance.enum_value = value2;
+  foo_instance.int_value = 1;
+  foo_instance.pointer_value = "Text to make a char *";  
+
+  /* In GDB, set a breakpoint at this line.  Then try to change the
+     value of foo_instance.enum_value in any way.  I can't do it. */
+}
+
diff --git a/gdb/testfb.c b/gdb/testfb.c
new file mode 100644 (file)
index 0000000..1699471
--- /dev/null
@@ -0,0 +1,12 @@
+
+main ()
+{
+  foo(2);
+  foo(3);
+}
+
+foo (i)
+{
+  printf ("i is %d, ", i);
+  printf ("i*i is %d\n", i * i);
+}
diff --git a/gdb/testfun.c b/gdb/testfun.c
new file mode 100644 (file)
index 0000000..eeeebd7
--- /dev/null
@@ -0,0 +1,22 @@
+main ()
+{
+  register double a = 1.5;
+  foo (a);
+}
+
+foo (x)
+{
+  printf ("%f\n", x);
+}
+
+do_add (x, y)
+{
+  return x + y;
+}
+
+double
+do_float_add (x, y, z)
+     register double x, y, z;
+{
+  return x + y + z;
+}
diff --git a/gdb/testkill.c b/gdb/testkill.c
new file mode 100644 (file)
index 0000000..0e43c1f
--- /dev/null
@@ -0,0 +1,5 @@
+
+       main()
+       {
+               printf("foo\n");
+       }
diff --git a/gdb/testrec.c b/gdb/testrec.c
new file mode 100644 (file)
index 0000000..797c08b
--- /dev/null
@@ -0,0 +1,12 @@
+main ()
+{
+  foo (4);
+}
+
+foo (x)
+     int x;
+{
+  if (x > 0)
+    foo (x - 1);
+}
+
diff --git a/gdb/testreg.c b/gdb/testreg.c
new file mode 100644 (file)
index 0000000..f19ec05
--- /dev/null
@@ -0,0 +1,22 @@
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  register int d1 = 34;
+  register int d2 = 35;
+  register int d3 = 36;
+  register int d4 = 37;
+  register char *a1 = "1";
+  register char *a2 = "2";
+  register char *a3 = "3";
+  register char *a4 = "4";
+  register char *a5 = "5";
+  int x[4];
+  foo ();
+  foo (0x222, abort (), 0x444);
+}
+
+foo ()
+{
+  return 22;
+}
diff --git a/gdb/testregs.c b/gdb/testregs.c
new file mode 100644 (file)
index 0000000..7a5acb3
--- /dev/null
@@ -0,0 +1,20 @@
+typedef struct aa { int b;} *hack;
+
+static int
+foo (argc)
+{
+  register int a = 0x1234;
+  register int b = 0x56788765;
+  register char *x = (char *) 0xabababab;
+  register char *y = (char *) 0xcdcdcdcd;
+  register double d = 1.582;
+  int loser;
+  printf ("Address of loser is 0x%x.\n", &loser);
+  printf ("Address of argc is 0x%x.\n", &argc);
+  abort ();
+}
+
+main (argc)
+{
+  foo (argc);
+}
diff --git a/gdb/testshort.c b/gdb/testshort.c
new file mode 100644 (file)
index 0000000..2c60631
--- /dev/null
@@ -0,0 +1,16 @@
+main ()
+{
+  register int ntabs;
+  register short x;
+  short stops[30];
+
+  foo ();
+}
+
+foo ()
+{
+  register int ntabs;
+  register short x;
+
+  printf (x, ntabs);
+}
diff --git a/gdb/testsig.c b/gdb/testsig.c
new file mode 100644 (file)
index 0000000..ded2d20
--- /dev/null
@@ -0,0 +1,17 @@
+# include      <signal.h>
+
+main ()
+{
+       int     handle ();
+       int     i;
+       signal (SIGALRM, handle);
+       alarm (5);
+       for (i = 0; i < 100000; i++)
+               printf ("%d\n", i);
+}
+
+handle ()
+{
+       printf ("signal!\n");
+       alarm (5);
+}
diff --git a/gdb/utils.c.OK b/gdb/utils.c.OK
new file mode 100644 (file)
index 0000000..7c52ea4
--- /dev/null
@@ -0,0 +1,422 @@
+/* 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 <stdio.h>
+#include <sys/ioctl.h>
+#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;
+\f
+/* 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);
+}
+\f
+/* 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 TIOCFLUSH
+  ioctl (fileno (stdout), TIOCFLUSH, 0);
+#endif
+  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");
+    }
+}
+\f
+/* 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;
+    }
+}
+\f
+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);
+    }
+}
diff --git a/gdb/valarith.c b/gdb/valarith.c
new file mode 100644 (file)
index 0000000..03bc1e1
--- /dev/null
@@ -0,0 +1,365 @@
+/* Perform arithmetic and other operations on values, 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!
+*/
+
+#include "defs.h"
+#include "initialize.h"
+#include "param.h"
+#include "symtab.h"
+#include "value.h"
+#include "expression.h"
+
+START_FILE
+\f
+value
+value_add (arg1, arg2)
+       value arg1, arg2;
+{
+  register value val, valint, valptr;
+  register int len;
+
+  COERCE_ARRAY (arg1);
+  COERCE_ARRAY (arg2);
+
+  if ((TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR
+       || TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_PTR)
+      &&
+      (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT
+       || TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_INT))
+    /* Exactly one argument is a pointer, and one is an integer.  */
+    {
+      if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR)
+       {
+         valptr = arg1;
+         valint = arg2;
+       }
+      else
+       {
+         valptr = arg2;
+         valint = arg1;
+       }
+      len = TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (valptr)));
+      if (len == 0) len = 1;   /* For (void *) */
+      val = value_from_long (builtin_type_long,
+                            value_as_long (valptr)
+                            + (len * value_as_long (valint)));
+      VALUE_TYPE (val) = VALUE_TYPE (valptr);
+      return val;
+    }
+
+  return value_binop (arg1, arg2, BINOP_ADD);
+}
+
+value
+value_sub (arg1, arg2)
+       value arg1, arg2;
+{
+  register value val;
+
+  COERCE_ARRAY (arg1);
+  COERCE_ARRAY (arg2);
+
+  if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR
+      && 
+      TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_INT)
+    {
+      val = value_from_long (builtin_type_long,
+                            value_as_long (arg1)
+                            - TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) * value_as_long (arg2));
+      VALUE_TYPE (val) = VALUE_TYPE (arg1);
+      return val;
+    }
+
+  if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR
+      && 
+      VALUE_TYPE (arg1) == VALUE_TYPE (arg2))
+    {
+      val = value_from_long (builtin_type_long,
+                            (value_as_long (arg1) - value_as_long (arg2))
+                            / TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))));
+      return val;
+    }
+
+  return value_binop (arg1, arg2, BINOP_SUB);
+}
+
+/* Return the value of ARRAY[IDX].  */
+
+value
+value_subscript (array, idx)
+     value array, idx;
+{
+  return value_ind (value_add (array, idx));
+}
+
+/* Perform a binary operation on two integers or two floats.
+   Does not support addition and subtraction on pointers;
+   use value_add or value_sub if you want to handle those possibilities.  */
+
+value
+value_binop (arg1, arg2, op)
+     value arg1, arg2;
+     int op;
+{
+  register value val;
+
+  COERCE_ENUM (arg1);
+  COERCE_ENUM (arg2);
+
+  if ((TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_FLT
+       &&
+       TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_INT)
+      ||
+      (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_FLT
+       &&
+       TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_INT))
+    error ("Argument to arithmetic operation not a number.");
+
+  if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_FLT
+      ||
+      TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_FLT)
+    {
+      double v1, v2, v;
+      v1 = value_as_double (arg1);
+      v2 = value_as_double (arg2);
+      switch (op)
+       {
+       case BINOP_ADD:
+         v = v1 + v2;
+         break;
+
+       case BINOP_SUB:
+         v = v1 - v2;
+         break;
+
+       case BINOP_MUL:
+         v = v1 * v2;
+         break;
+
+       case BINOP_DIV:
+         v = v1 / v2;
+         break;
+
+       default:
+         error ("Integer-only operation on floating point number.");
+       }
+
+      val = allocate_value (builtin_type_double);
+      *(double *) VALUE_CONTENTS (val) = v;
+    }
+  else
+    {
+      long 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;
+
+       default:
+         error ("Invalid binary operation on numbers.");
+       }
+
+      val = allocate_value (builtin_type_long);
+      *(long *) VALUE_CONTENTS (val) = v;
+    }
+
+  return val;
+}
+\f
+/* Simulate the C operator ! -- return 1 if ARG1 contains zeros.  */
+
+int
+value_zerop (arg1)
+     value arg1;
+{
+  register int len;
+  register char *p;
+
+  COERCE_ARRAY (arg1);
+
+  len = TYPE_LENGTH (VALUE_TYPE (arg1));
+  p = VALUE_CONTENTS (arg1);
+
+  while (--len >= 0)
+    {
+      if (*p++)
+       break;
+    }
+
+  return len < 0;
+}
+
+/* Simulate the C operator == by returning a 1
+   iff ARG1 and ARG2 have equal contents.  */
+
+int
+value_equal (arg1, arg2)
+     register value arg1, arg2;
+
+{
+  register int len;
+  register char *p1, *p2;
+  enum type_code code1;
+  enum type_code code2;
+
+  COERCE_ARRAY (arg1);
+  COERCE_ARRAY (arg2);
+
+  code1 = TYPE_CODE (VALUE_TYPE (arg1));
+  code2 = TYPE_CODE (VALUE_TYPE (arg2));
+
+  if (code1 == TYPE_CODE_INT && code2 == TYPE_CODE_INT)
+    return value_as_long (arg1) == value_as_long (arg2);
+  else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT)
+          && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT))
+    return value_as_double (arg1) == value_as_double (arg2);
+  else if ((code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_INT)
+          || (code2 == TYPE_CODE_PTR && code1 == TYPE_CODE_INT))
+    return value_as_long (arg1) == value_as_long (arg2);
+  else if (code1 == code2
+          && ((len = TYPE_LENGTH (VALUE_TYPE (arg1)))
+              == TYPE_LENGTH (VALUE_TYPE (arg2))))
+    {
+      p1 = VALUE_CONTENTS (arg1);
+      p2 = VALUE_CONTENTS (arg2);
+      while (--len >= 0)
+       {
+         if (*p1++ != *p2++)
+           break;
+       }
+      return len < 0;
+    }
+  else
+    error ("Invalid type combination in equality test.");
+}
+
+/* Simulate the C operator < by returning 1
+   iff ARG1's contents are less than ARG2's.  */
+
+int
+value_less (arg1, arg2)
+     register value arg1, arg2;
+{
+  register enum type_code code1;
+  register enum type_code code2;
+
+  COERCE_ARRAY (arg1);
+  COERCE_ARRAY (arg2);
+
+  code1 = TYPE_CODE (VALUE_TYPE (arg1));
+  code2 = TYPE_CODE (VALUE_TYPE (arg2));
+
+  if (code1 == TYPE_CODE_INT && code2 == TYPE_CODE_INT)
+    return value_as_long (arg1) < value_as_long (arg2);
+  else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT)
+          && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT))
+    return value_as_double (arg1) < value_as_double (arg2);
+  else if ((code1 == TYPE_CODE_PTR || code1 == TYPE_CODE_INT)
+          && (code2 == TYPE_CODE_PTR || code2 == TYPE_CODE_INT))
+    return value_as_long (arg1) < value_as_long (arg2);
+  else
+    error ("Invalid type combination in ordering comparison.");
+}
+\f
+/* The unary operators - and ~.  Both free the argument ARG1.  */
+
+value
+value_neg (arg1)
+     register value arg1;
+{
+  register struct type *type;
+
+  COERCE_ENUM (arg1);
+
+  type = VALUE_TYPE (arg1);
+
+  if (TYPE_CODE (type) == TYPE_CODE_FLT)
+    return value_from_double (type, - value_as_double (arg1));
+  else if (TYPE_CODE (type) == TYPE_CODE_INT)
+    return value_from_long (type, - value_as_long (arg1));
+  else
+    error ("Argument to negate operation not a number.");
+}
+
+value
+value_lognot (arg1)
+     register value arg1;
+{
+  COERCE_ENUM (arg1);
+
+  if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_INT)
+    error ("Argument to complement operation not an integer.");
+
+  return value_from_long (VALUE_TYPE (arg1), ~ value_as_long (arg1));
+}
+\f
+static
+initialize ()
+{
+}
+
+END_FILE
diff --git a/gdb/valops.c b/gdb/valops.c
new file mode 100644 (file)
index 0000000..9f0e3cc
--- /dev/null
@@ -0,0 +1,600 @@
+/* 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!
+*/
+
+#include "defs.h"
+#include "initialize.h"
+#include "param.h"
+#include "symtab.h"
+#include "value.h"
+
+START_FILE
+\f
+/* Cast value ARG2 to type TYPE and return as a value.
+   More general than a C cast: accepts any two types of the same length,
+   and if ARG2 is an lvalue it can be cast into anything at all.  */
+
+value
+value_cast (type, arg2)
+     struct type *type;
+     register value arg2;
+{
+  register enum type_code code1;
+  register enum type_code code2;
+  register int scalar;
+
+  /* Coerce arrays but not enums.  Enums will work as-is
+     and coercing them would cause an infinite recursion.  */
+  if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_ENUM)
+    COERCE_ARRAY (arg2);
+
+  code1 = TYPE_CODE (type);
+  code2 = TYPE_CODE (VALUE_TYPE (arg2));
+  scalar = (code2 == TYPE_CODE_INT || code2 == TYPE_CODE_FLT
+           || code2 == TYPE_CODE_ENUM);
+
+  if (code1 == TYPE_CODE_FLT && scalar)
+    return value_from_double (type, value_as_double (arg2));
+  else if ((code1 == TYPE_CODE_INT || code1 == TYPE_CODE_ENUM)
+          && (scalar || code2 == TYPE_CODE_PTR))
+    return value_from_long (type, value_as_long (arg2));
+  else if (TYPE_LENGTH (type) == TYPE_LENGTH (VALUE_TYPE (arg2)))
+    {
+      VALUE_TYPE (arg2) = type;
+      return arg2;
+    }
+  else if (VALUE_LVAL (arg2) == lval_memory)
+    return value_at (type, VALUE_ADDRESS (arg2) + VALUE_OFFSET (arg2));
+  else
+    error ("Invalid cast.");
+}
+
+/* Return the value with a specified type located at specified address.  */
+
+value
+value_at (type, addr)
+     struct type *type;
+     CORE_ADDR addr;
+{
+  register value val = allocate_value (type);
+
+  read_memory (addr, VALUE_CONTENTS (val), TYPE_LENGTH (type));
+  VALUE_LVAL (val) = lval_memory;
+  VALUE_ADDRESS (val) = addr;
+
+  return val;
+}
+
+/* Store the contents of FROMVAL into the location of TOVAL.
+   Return a new value with the location of TOVAL and contents of FROMVAL.  */
+
+value
+value_assign (toval, fromval)
+     register value toval, fromval;
+{
+  register struct type *type = VALUE_TYPE (toval);
+  register value val;
+  char raw_buffer[MAX_REGISTER_RAW_SIZE];
+  char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+  int use_buffer = 0;
+
+  COERCE_ARRAY (fromval);
+
+  if (VALUE_LVAL (toval) != lval_internalvar)
+    fromval = value_cast (type, fromval);
+
+  /* If TOVAL is a special machine register requiring conversion
+     of program values to a special raw format,
+     convert FROMVAL's contents now, with result in `raw_buffer',
+     and set USE_BUFFER to the number of bytes to write.  */
+     
+  if (VALUE_REGNO (toval) >= 0
+      && REGISTER_CONVERTIBLE (VALUE_REGNO (toval)))
+    {
+      int regno = VALUE_REGNO (toval);
+      if (VALUE_TYPE (fromval) != REGISTER_VIRTUAL_TYPE (regno))
+       fromval = value_cast (REGISTER_VIRTUAL_TYPE (regno), fromval);
+      bcopy (VALUE_CONTENTS (fromval), virtual_buffer,
+            REGISTER_VIRTUAL_SIZE (regno));
+      REGISTER_CONVERT_TO_RAW (regno, virtual_buffer, raw_buffer);
+      use_buffer = REGISTER_RAW_SIZE (regno);
+    }
+
+  switch (VALUE_LVAL (toval))
+    {
+    case lval_internalvar:
+      set_internalvar (VALUE_INTERNALVAR (toval), fromval);
+      break;
+
+    case lval_internalvar_component:
+      set_internalvar_component (VALUE_INTERNALVAR (toval),
+                                VALUE_OFFSET (toval),
+                                VALUE_BITPOS (toval),
+                                VALUE_BITSIZE (toval),
+                                fromval);
+      break;
+
+    case lval_memory:
+      if (VALUE_BITSIZE (toval))
+       {
+         int val;
+         read_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+                      &val, sizeof val);
+         modify_field (&val, value_as_long (fromval),
+                       VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
+         write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+                       &val, sizeof val);
+       }
+      else if (use_buffer)
+       write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+                     raw_buffer, use_buffer);
+      else
+       write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+                     VALUE_CONTENTS (fromval), TYPE_LENGTH (type));
+      break;
+
+    case lval_register:
+      if (VALUE_BITSIZE (toval))
+       {
+         int val;
+
+         read_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+                              &val, sizeof val);
+         modify_field (&val, value_as_long (fromval),
+                       VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
+         write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+                               &val, sizeof val);
+       }
+      else if (use_buffer)
+       write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+                             raw_buffer, use_buffer);
+      else
+       write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+                             VALUE_CONTENTS (fromval), TYPE_LENGTH (type));
+      break;
+
+    default:
+      error ("Left side of = operation is not an lvalue.");
+    }
+
+  /* Return a value just like TOVAL except with the contents of FROMVAL.  */
+
+  val = allocate_value (type);
+  bcopy (toval, val, VALUE_CONTENTS (val) - (char *) val);
+  bcopy (VALUE_CONTENTS (fromval), VALUE_CONTENTS (val), TYPE_LENGTH (type));
+
+  return val;
+}
+
+/* Extend a value VAL to COUNT repetitions of its type.  */
+
+value
+value_repeat (arg1, count)
+     value arg1;
+     int count;
+{
+  register value val;
+
+  if (VALUE_LVAL (arg1) != lval_memory)
+    error ("Only values in memory can be extended with '@'.");
+  if (count < 1)
+    error ("Invalid number %d of repetitions.", count);
+
+  val = allocate_repeat_value (VALUE_TYPE (arg1), count);
+
+  read_memory (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1),
+              VALUE_CONTENTS (val),
+              TYPE_LENGTH (VALUE_TYPE (val)) * count);
+  VALUE_LVAL (val) = lval_memory;
+  VALUE_ADDRESS (val) = VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1);
+
+  return val;
+}
+
+value
+value_of_variable (var)
+     struct symbol *var;
+{
+  return read_var_value (var, (CORE_ADDR) 0);
+}
+
+/* Given a value which is an array, return a value which is
+   a pointer to its first element.  */
+
+value
+value_coerce_array (arg1)
+     value arg1;
+{
+  register struct type *type;
+  register value val;
+
+  if (VALUE_LVAL (arg1) != lval_memory)
+    error ("Attempt to take address of value not located in memory.");
+
+  /* Get type of elements.  */
+  if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_ARRAY)
+    type = TYPE_TARGET_TYPE (VALUE_TYPE (arg1));
+  else
+    /* A phony array made by value_repeat.
+       Its type is the type of the elements, not an array type.  */
+    type = VALUE_TYPE (arg1);
+
+  /* Get the type of the result.  */
+  type = lookup_pointer_type (type);
+  val = value_from_long (builtin_type_long,
+                        VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1));
+  VALUE_TYPE (val) = type;
+  return val;
+}
+
+/* Return a pointer value for the object for which ARG1 is the contents.  */
+
+value
+value_addr (arg1)
+     value arg1;
+{
+  register struct type *type;
+  register value val, arg1_coerced;
+
+  /* Taking the address of an array is really a no-op
+     once the array is coerced to a pointer to its first element.  */
+  arg1_coerced = arg1;
+  COERCE_ARRAY (arg1_coerced);
+  if (arg1 != arg1_coerced)
+    return arg1_coerced;
+
+  if (VALUE_LVAL (arg1) != lval_memory)
+    error ("Attempt to take address of value not located in memory.");
+
+  /* Get the type of the result.  */
+  type = lookup_pointer_type (VALUE_TYPE (arg1));
+  val = value_from_long (builtin_type_long,
+                        VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1));
+  VALUE_TYPE (val) = type;
+  return val;
+}
+
+/* Given a value of a pointer type, apply the C unary * operator to it.  */
+
+value
+value_ind (arg1)
+     value arg1;
+{
+  COERCE_ARRAY (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, 
+                    (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)),
+                    (CORE_ADDR) value_as_long (arg1));
+  error ("Attempt to take contents of a non-pointer value.");
+}
+\f
+/* Pushing small parts of stack frames.  */
+
+/* Push one word (the size of object that a register holds).  */
+
+CORE_ADDR
+push_word (sp, buffer)
+     CORE_ADDR sp;
+     REGISTER_TYPE buffer;
+{
+  register int len = sizeof (REGISTER_TYPE);
+
+#if 1 INNER_THAN 2
+  sp -= len;
+  write_memory (sp, &buffer, len);
+#else /* stack grows upward */
+  write_memory (sp, &buffer, len);
+  sp += len;
+#endif /* stack grows upward */
+
+  return sp;
+}
+
+/* Push LEN bytes with data at BUFFER.  */
+
+CORE_ADDR
+push_bytes (sp, buffer, len)
+     CORE_ADDR sp;
+     char *buffer;
+     int len;
+{
+#if 1 INNER_THAN 2
+  sp -= len;
+  write_memory (sp, buffer, len);
+#else /* stack grows upward */
+  write_memory (sp, buffer, len);
+  sp += len;
+#endif /* stack grows upward */
+
+  return sp;
+}
+
+/* Push onto the stack the specified value VALUE.  */
+
+CORE_ADDR
+value_push (sp, arg)
+     register CORE_ADDR sp;
+     value arg;
+{
+  register int len = TYPE_LENGTH (VALUE_TYPE (arg));
+
+#if 1 INNER_THAN 2
+  sp -= len;
+  write_memory (sp, VALUE_CONTENTS (arg), len);
+#else /* stack grows upward */
+  write_memory (sp, VALUE_CONTENTS (arg), len);
+  sp += len;
+#endif /* stack grows upward */
+
+  return sp;
+}
+
+/* Perform the standard coercions that are specified
+   for arguments to be passed to C functions.  */
+
+value
+value_arg_coerce (arg)
+     value arg;
+{
+  register struct type *type;
+
+  COERCE_ENUM (arg);
+
+  type = VALUE_TYPE (arg);
+
+  if (TYPE_CODE (type) == TYPE_CODE_INT
+      && TYPE_LENGTH (type) < sizeof (int))
+    return value_cast (builtin_type_int, arg);
+
+  if (type == builtin_type_float)
+    return value_cast (builtin_type_double, arg);
+
+  return arg;
+}
+
+/* Push the value ARG, first coercing it as an argument
+   to a C function.  */
+
+CORE_ADDR
+value_arg_push (sp, arg)
+     register CORE_ADDR sp;
+     value arg;
+{
+  return value_push (sp, value_arg_coerce (arg));
+}
+
+/* Perform a function call in the inferior.
+   ARGS is a vector of values of arguments (NARGS of them).
+   FUNCTION is a value, the function to be called.
+   Returns a value representing what the function returned.
+   May fail to return, if a breakpoint or signal is hit
+   during the execution of the function.  */
+
+value
+call_function (function, nargs, args)
+     value function;
+     int nargs;
+     value *args;
+{
+  register CORE_ADDR sp;
+  register int i;
+  CORE_ADDR start_sp;
+  static REGISTER_TYPE dummy[] = CALL_DUMMY;
+  REGISTER_TYPE dummy1[sizeof dummy / sizeof (REGISTER_TYPE)];
+  CORE_ADDR old_sp;
+  struct type *value_type;
+
+  PUSH_DUMMY_FRAME;
+
+  {
+    register CORE_ADDR funaddr;
+    register struct type *ftype = VALUE_TYPE (function);
+    register enum type_code code = TYPE_CODE (ftype);
+
+    /* Determine address to call.  */
+    if (code == TYPE_CODE_FUNC)
+      {
+       funaddr = VALUE_ADDRESS (function);
+       value_type = TYPE_TARGET_TYPE (ftype);
+      }
+    else if (code == TYPE_CODE_PTR)
+      {
+       funaddr = value_as_long (function);
+       if (TYPE_CODE (TYPE_TARGET_TYPE (ftype))
+           == TYPE_CODE_FUNC)
+         value_type = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (ftype));
+       else
+         value_type = builtin_type_int;
+      }
+    else if (code == TYPE_CODE_INT)
+      {
+       /* Handle the case of functions lacking debugging info.
+          Their values are characters since their addresses are char */
+       if (TYPE_LENGTH (ftype) == 1)
+         funaddr = value_as_long (value_addr (function));
+       else
+         /* Handle integer used as address of a function.  */
+         funaddr = value_as_long (function);
+
+       value_type = builtin_type_int;
+      }
+    else
+      error ("Invalid data type for function to be called.");
+
+    /* Create a call sequence customized for this function
+       and the number of arguments for it.  */
+    bcopy (dummy, dummy1, sizeof dummy);
+    FIX_CALL_DUMMY (dummy1, funaddr, nargs);
+  }
+
+  old_sp = sp = read_register (SP_REGNUM);
+
+#if 1 INNER_THAN 2  /* Stack grows down */
+  sp -= sizeof dummy;
+  write_memory (sp, dummy1, sizeof dummy);
+  start_sp = sp;
+  for (i = nargs - 1; i >= 0; i--)
+    sp = value_arg_push (sp, args[i]);
+#else  /* Stack grows up */
+  start_sp = sp;
+  write_memory (sp, dummy1, sizeof dummy);
+  sp += sizeof dummy;
+  for (i = 0; i < nargs; i++)
+    sp = value_arg_push (sp, args[i]);
+#endif  /* Stack grows up */
+
+  write_register (SP_REGNUM, sp);
+
+  /* Figure out the value returned by the function.  */
+  {
+    char retbuf[REGISTER_BYTES];
+
+    /* Execute the stack dummy routine, calling FUNCTION.
+       When it is done, discard the empty frame
+       after storing the contents of all regs into retbuf.  */
+    run_stack_dummy (start_sp + CALL_DUMMY_START_OFFSET, retbuf);
+
+    return value_being_returned (value_type, retbuf);
+  }
+}
+\f
+/* Create a value for a string constant:
+   Call the function malloc in the inferior to get space for it,
+   then copy the data into that space
+   and then return the address with type char *.
+   PTR points to the string constant data; LEN is number of characters.  */
+
+value
+value_string (ptr, len)
+     char *ptr;
+     int len;
+{
+  register value val;
+  register struct symbol *sym;
+  value blocklen;
+  register char *copy = (char *) alloca (len + 1);
+  char *i = ptr;
+  register char *o = copy, *ibeg = ptr;
+  register int c;
+
+  /* Copy the string into COPY, processing escapes.
+     We could not conveniently process them in expread
+     because the string there wants to be a substring of the input.  */
+
+  while (i - ibeg < len)
+    {
+      c = *i++;
+      if (c == '\\')
+       {
+         c = parse_escape (&i);
+         if (c == -1)
+           continue;
+       }
+      *o++ = c;
+    }
+  *o = 0;
+
+  /* Get the length of the string after escapes are processed.  */
+
+  len = o - copy;
+
+  /* Find the address of malloc in the inferior.  */
+
+  sym = lookup_symbol ("malloc", 0, VAR_NAMESPACE);
+  if (sym != 0)
+    {
+      if (SYMBOL_CLASS (sym) != LOC_BLOCK)
+       error ("\"malloc\" exists in this program but is not a function.");
+      val = value_of_variable (sym);
+    }
+  else
+    {
+      register int i;
+      for (i = 0; i < misc_function_count; i++)
+       if (!strcmp (misc_function_vector[i].name, "malloc"))
+         break;
+      if (i < misc_function_count)
+       val = value_from_long (builtin_type_long,
+                              misc_function_vector[i].address);
+      else
+       error ("String constants require the program to have a function \"malloc\".");
+    }
+
+  blocklen = value_from_long (builtin_type_int, len + 1);
+  val = call_function (val, 1, &blocklen);
+  if (value_zerop (val))
+    error ("No memory available for string constant.");
+  write_memory (value_as_long (val), copy, len + 1);
+  VALUE_TYPE (val) = lookup_pointer_type (builtin_type_char);
+  return val;
+}
+\f
+/* Given ARG1, a value of type (pointer to a)* structure/union,
+   extract the component named NAME from the ultimate target structure/union
+   and return it as a value with its appropriate type.
+   ERR is used in the error message if ARG1's type is wrong.  */
+   
+value
+value_struct_elt (arg1, name, err)
+     register value arg1;
+     char *name;
+     char *err;
+{
+  register struct type *t;
+  register int i;
+
+  COERCE_ARRAY (arg1);
+
+  t = VALUE_TYPE (arg1);
+
+  /* Follow pointers until we get to a non-pointer.  */
+
+  while (TYPE_CODE (t) == TYPE_CODE_PTR)
+    {
+      arg1 = value_ind (arg1);
+      COERCE_ARRAY (arg1);
+      t = VALUE_TYPE (arg1);
+    }
+
+  if (TYPE_CODE (t) != TYPE_CODE_STRUCT
+      &&
+      TYPE_CODE (t) != TYPE_CODE_UNION)
+    error ("Attempt to extract a component of a value that is not a %s.", err);
+
+  for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
+    {
+      if (!strcmp (TYPE_FIELD_NAME (t, i), name))
+       break;
+    }
+
+  if (i < 0)
+    error ("Structure has no component named %s.", name);
+
+  return value_field (arg1, i);
+}
+\f
+static
+initialize ()
+{ }
+
+END_FILE
diff --git a/gdb/valprint.c b/gdb/valprint.c
new file mode 100644 (file)
index 0000000..78c8d63
--- /dev/null
@@ -0,0 +1,622 @@
+/* Print values for GNU debugger 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!
+*/
+
+#include <stdio.h>
+#include "defs.h"
+#include "initialize.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 ();
+
+START_FILE
+
+char **unsigned_type_table;
+char **signed_type_table;
+char **float_type_table;
+\f
+/* Print the value VAL in C-ish syntax on stream STREAM.
+   If the object printed is a string pointer, returns
+   the number of string bytes printed.  */
+
+value_print (val, stream)
+     value val;
+     FILE *stream;
+{
+  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 (VALUE_TYPE (val) == builtin_type_char
+         || VALUE_TYPE (val) == builtin_type_unsigned_char)
+       {
+         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);
+           }
+         if (i < n)
+           fprintf (stream, "...");
+       }
+      fputc ('}', stream);
+    }
+  else
+    {
+      /* A simple (nonrepeated) value */
+      /* If it is a pointer, indicate what it points to.  */
+      if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR)
+       {
+         fprintf (stream, "(");
+         type_print (VALUE_TYPE (val), "", stream, -1);
+         fprintf (stream, ") ");
+       }
+      return val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
+                       VALUE_ADDRESS (val), stream);
+    }
+}
+\f
+/* Print on STREAM data stored in debugger at address VALADDR
+   according to the format of type TYPE.
+   ADDRESS is the location in the inferior that the data
+   is supposed to have come from.
+
+   If the data are a string pointer, returns the number of
+   sting characters printed.  */
+
+int
+val_print (type, valaddr, address, stream)
+     struct type *type;
+     char *valaddr;
+     CORE_ADDR address;
+     FILE *stream;
+{
+  register int i;
+  int len;
+  struct type *elttype;
+  int eltlen;
+  int 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 (elttype == builtin_type_char
+             || elttype == builtin_type_unsigned_char)
+           {
+             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);
+               }
+             if (i < len)
+               fprintf (stream, "...");
+           }
+         fprintf (stream, "}");
+         break;
+       }
+      /* Array of unspecified length: treat like pointer.  */
+
+    case TYPE_CODE_PTR:
+      fprintf (stream, "0x%x", * (int *) valaddr);
+      /* For a pointer to char or unsigned char,
+        also print the string pointed to, unless pointer is null.  */
+      if ((TYPE_TARGET_TYPE (type) == builtin_type_char
+          || TYPE_TARGET_TYPE (type) == builtin_type_unsigned_char)
+         && unpack_long (type, valaddr) != 0)
+       {
+         fputc (' ', stream);
+         fputc ('"', stream);
+         for (i = 0; i < print_max; i++)
+           {
+             QUIT;
+             read_memory (unpack_long (type, valaddr) + i, &c, 1);
+             if (c == 0)
+               break;
+             printchar (c, stream);
+           }
+         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 + (i != print_max);
+       }
+      break;
+
+    case TYPE_CODE_STRUCT:
+    case TYPE_CODE_UNION:
+      fprintf (stream, "{");
+      len = TYPE_NFIELDS (type);
+      for (i = 0; i < len; i++)
+       {
+         if (i) fprintf (stream, ", ");
+         fprintf (stream, "%s = ", TYPE_FIELD_NAME (type, i));
+         if (TYPE_FIELD_PACKED (type, i))
+           {
+             val = unpack_field_as_long (type, valaddr, i);
+             val_print (TYPE_FIELD_TYPE (type, i), &val, 0, stream);
+           }
+         else
+           val_print (TYPE_FIELD_TYPE (type, i), 
+                      valaddr + TYPE_FIELD_BITPOS (type, i) / 8,
+                      0, stream);
+       }
+      fprintf (stream, "}");
+      break;
+
+    case TYPE_CODE_ENUM:
+      len = TYPE_NFIELDS (type);
+      val = unpack_long (builtin_type_int, valaddr);
+      for (i = 0; i < len; i++)
+       {
+         QUIT;
+         if (val == TYPE_FIELD_VALUE (type, i))
+           break;
+       }
+      if (i < len)
+       fprintf (stream, "%s", TYPE_FIELD_NAME (type, i));
+      else
+       fprintf (stream, "%d", val);
+      break;
+
+    case TYPE_CODE_FUNC:
+      fprintf (stream, "{");
+      type_print (type, "", stream, -1);
+      fprintf (stream, "} ");
+      fprintf (stream, "0x%x", address);
+      break;
+
+    case TYPE_CODE_INT:
+      fprintf (stream,
+              TYPE_UNSIGNED (type) ? "%u" : "%d",
+              unpack_long (type, valaddr));
+      if (type == builtin_type_char
+         || type == builtin_type_unsigned_char)
+       {
+         fprintf (stream, " '");
+         printchar (unpack_long (type, valaddr), stream);
+         fputc ('\'', stream);
+       }
+      break;
+
+    case TYPE_CODE_FLT:
+#ifdef IEEE_FLOAT
+      if (is_nan (unpack_double (type, valaddr)))
+       {
+         fprintf (stream, "Nan");
+         break;
+       }
+#endif
+      fprintf (stream, "%g", unpack_double (type, valaddr));
+      break;
+
+    case TYPE_CODE_VOID:
+      fprintf (stream, "void");
+      break;
+
+    default:
+      error ("Invalid type code in symbol table.");
+    }
+  fflush (stream);
+}
+\f
+#ifdef IEEE_FLOAT
+
+union ieee {
+  int i[2];
+  double d;
+};
+
+/* Nonzero if ARG (a double) is a NAN.  */
+
+int
+is_nan (arg)
+     union ieee arg;
+{
+  int lowhalf, highhalf;
+  union { int i; char c; } test;
+
+  /* Separate the high and low words of the double.
+     Distinguish big and little-endian machines.  */
+  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];
+
+  /* Nan: exponent is the maximum possible, and fraction is nonzero.  */
+  return (((highhalf>>20) & 0x7ff) == 0x7ff
+         &&
+         ! ((highhalf & 0xfffff == 0) && (lowhalf == 0)));
+}
+#endif
+\f
+/* 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.  */
+
+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.  */
+
+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)))
+    fprintf (stream, " ");
+  type_print_varspec_prefix (type, stream, show, 0);
+  fprintf (stream, "%s", varstring);
+  type_print_varspec_suffix (type, stream, show, 0);
+}
+
+/* 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_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_FUNC:
+    case TYPE_CODE_ARRAY:
+      type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+      if (passed_a_ptr)
+       fputc ('(', stream);
+      break;
+    }
+}
+
+/* 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_NAME (type) && show <= 0)
+    return;
+
+  QUIT;
+
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_ARRAY:
+      type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+      if (passed_a_ptr)
+       fprintf (stream, ")");
+      fprintf (stream, "[");
+      if (TYPE_LENGTH (type) >= 0)
+       fprintf (stream, "%d",
+                TYPE_LENGTH (type) / TYPE_LENGTH (TYPE_TARGET_TYPE (type)));
+      fprintf (stream, "]");
+      break;
+
+    case TYPE_CODE_PTR:
+      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, 0);
+      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_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_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
+       {
+         fprintf (stream, "{");
+         len = TYPE_NFIELDS (type);
+         fprintf (stream, "\n");
+         for (i = 0; i < len; i++)
+           {
+             QUIT;
+             print_spaces (level + 4, stream);
+
+             /* If this is a bit-field and there is a gap before it,
+                print a nameless field to account for the gap.  */
+
+             if (TYPE_FIELD_PACKED (type, i))
+               {
+                 int gap = (TYPE_FIELD_BITPOS (type, i)
+                            - (i > 0
+                               ? (TYPE_FIELD_BITPOS (type, i - 1)
+                                  + (TYPE_FIELD_PACKED (type, i - 1)
+                                     ? TYPE_FIELD_BITSIZE (type, i - 1)
+                                     : TYPE_LENGTH (TYPE_FIELD_TYPE (type, i - 1)) * 8))
+                               : 0));
+                 if (gap != 0)
+                   {
+                     fprintf (stream, "int : %d;\n", gap);
+                     print_spaces (level + 4, stream);
+                   }
+               }
+
+             /* Print the declaration of this field.  */
+
+             type_print_1 (TYPE_FIELD_TYPE (type, i),
+                           TYPE_FIELD_NAME (type, i),
+                           stream, show - 1, level + 4);
+
+             /* Print the field width.  */
+
+             if (TYPE_FIELD_PACKED (type, i))
+               fprintf (stream, " : %d", TYPE_FIELD_BITSIZE (type, i));
+
+             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_VALUE (type, i))
+               {
+                 fprintf (stream, " : %d", TYPE_FIELD_VALUE (type, i));
+                 lastval = TYPE_FIELD_VALUE (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.");
+    }
+}
+\f
+static void
+set_maximum_command (arg)
+     char *arg;
+{
+  if (!arg) error_no_arg ("value for maximum elements to print");
+  print_max = atoi (arg);
+}
+
+static
+initialize ()
+{
+  add_com ("set-maximum", class_vars, set_maximum_command,
+          "Set NUMBER as limit on string chars or array elements to print.");
+
+  print_max = 200;
+
+  unsigned_type_table
+    = (char **) xmalloc ((1 + sizeof (unsigned long)) * sizeof (char *));
+  bzero (unsigned_type_table, (1 + sizeof (unsigned long)));
+  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";
+
+  signed_type_table
+    = (char **) xmalloc ((1 + sizeof (long)) * sizeof (char *));
+  bzero (signed_type_table, (1 + sizeof (long)));
+  signed_type_table[sizeof (char)] = "char";
+  signed_type_table[sizeof (short)] = "short";
+  signed_type_table[sizeof (long)] = "long";
+  signed_type_table[sizeof (int)] = "int";
+
+  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";
+}
+
+END_FILE
diff --git a/gdb/value.h b/gdb/value.h
new file mode 100644 (file)
index 0000000..9801d9a
--- /dev/null
@@ -0,0 +1,130 @@
+/* Definitions for values of C expressions, 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!
+*/
+
+enum lval_type { not_lval, lval_memory, lval_register, lval_internalvar,
+                lval_internalvar_component };
+
+struct value
+  {
+    enum lval_type lval;
+    union
+      {
+       CORE_ADDR address;
+       struct internalvar *internalvar;
+      } location;
+    int offset;
+    int bitsize;
+    int bitpos;
+    struct type *type;
+    struct value *next;
+    short repeated;
+    short repetitions;
+    short regno;
+    long contents[1];
+  };
+
+typedef struct value *value;
+
+#define VALUE_TYPE(val) (val)->type
+#define VALUE_CONTENTS(val) ((char *) (val)->contents)
+#define VALUE_LVAL(val) (val)->lval
+#define VALUE_ADDRESS(val) (val)->location.address
+#define VALUE_INTERNALVAR(val) (val)->location.internalvar
+#define VALUE_OFFSET(val) (val)->offset
+#define VALUE_BITSIZE(val) (val)->bitsize
+#define VALUE_BITPOS(val) (val)->bitpos
+#define VALUE_NEXT(val) (val)->next
+#define VALUE_REPEATED(val) (val)->repeated
+#define VALUE_REPETITIONS(val) (val)->repetitions
+#define VALUE_REGNO(val) (val)->regno
+
+/* If ARG is an array, convert it to a pointer.
+   If ARG is an enum, convert it to an integer.  */
+
+#define COERCE_ARRAY(arg)    \
+{ if (VALUE_REPEATED (arg)                                             \
+      || TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ARRAY)              \
+    arg = value_coerce_array (arg);                                    \
+  if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM)                  \
+    arg = value_cast (builtin_type_unsigned_int, arg);                 \
+}
+
+/* If ARG is an enum, convert it to an integer.  */
+
+#define COERCE_ENUM(arg)    \
+{ if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM)                  \
+    arg = value_cast (builtin_type_unsigned_int, arg);                 \
+}
+
+/* Internal variables (variables for convenience of use of debugger)
+   are recorded as a chain of these structures.  */
+
+struct internalvar
+{
+  struct internalvar *next;
+  char *name;
+  value value;
+};
+\f
+long value_as_long ();
+double value_as_double ();
+long unpack_long ();
+double unpack_double ();
+long unpack_field_as_long ();
+value value_from_long ();
+value value_from_double ();
+value value_at ();
+value value_of_variable ();
+value value_of_register ();
+value read_var_value ();
+value locate_var_value ();
+value allocate_value ();
+value allocate_repeat_value ();
+value value_string ();
+
+value value_binop ();
+value value_add ();
+value value_sub ();
+value value_coerce_array ();
+value value_ind ();
+value value_addr ();
+value value_assign ();
+value value_neg ();
+value value_lognot ();
+value value_struct_elt ();
+value value_field ();
+value value_cast ();
+value value_repeat ();
+value value_subscript ();
+
+value call_function ();
+value value_being_returned ();
+
+value evaluate_expression ();
+value evaluate_type ();
+value parse_and_eval ();
+
+value access_value_history ();
+value value_of_internalvar ();
+struct internalvar *lookup_internalvar ();
+
+int value_equal ();
+int value_less ();
+int value_zerop ();
diff --git a/gdb/values.c b/gdb/values.c
new file mode 100644 (file)
index 0000000..9af5d96
--- /dev/null
@@ -0,0 +1,749 @@
+/* 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 <stdio.h>
+#include "defs.h"
+#include "initialize.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 */
+
+START_FILE
+\f
+/* 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_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_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;
+}
+\f
+/* 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;
+{
+  register int i;
+
+  /* Get error now if about to store an invalid float.  */
+  if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FLT)
+    value_as_double (val);
+
+  /* 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);
+      printf ("\n");
+    }
+}
+\f
+/* 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;
+}
+
+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, 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);
+      printf ("\n");
+    }
+}
+\f
+/* 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.  */
+
+long
+value_as_long (val)
+     register value val;
+{
+  return unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val));
+}
+
+double
+value_as_double (val)
+     register value val;
+{
+  return unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val));
+}
+\f
+/* 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.  */
+
+long
+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;
+    }
+  else if (code == TYPE_CODE_PTR)
+    {
+      if (len == sizeof (char *))
+       return (CORE_ADDR) * (char **) valaddr;
+    }
+
+  error ("Value not integer or pointer.");
+}
+
+double
+unpack_double (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_FLT)
+    {
+      if (INVALID_FLOAT (valaddr, len))
+       error ("Invalid floating value found in program.");
+
+      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;
+    }
+
+  error ("Value not floating number.");
+}
+\f
+/* Given a value ARG1 of a struct or union type,
+   extract and return the value of one of its fields.
+   FIELDNO says which field.  */
+
+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,
+                          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;
+}
+
+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);
+  union { int i; char c; } test;
+
+  bcopy (valaddr + bitpos / 8, &val, sizeof val);
+
+  /* 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);
+
+  val &= (1 << bitsize) - 1;
+  return val;
+}
+
+modify_field (addr, fieldval, bitpos, bitsize)
+     char *addr;
+     int fieldval;
+     int bitpos, bitsize;
+{
+  long oword;
+  union { int i; char c; } test;
+
+  bcopy (addr, &oword, sizeof oword);
+
+  /* Shifting for bit field depends on endianness of the machine.  */
+  test.c = 1;
+  if (test.i != 1)
+    /* not little-endian: assume big-endian.  */
+    bitpos = sizeof oword * 8 - bitpos - bitsize;
+
+  oword &= ~(((1 << bitsize) - 1) << bitpos);
+  oword |= fieldval << bitpos;
+  bcopy (&oword, addr, sizeof oword);
+}
+\f
+/* Convert C numbers into newly allocated values */
+
+value
+value_from_long (type, num)
+     struct type *type;
+     register long 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;
+      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;
+}
+\f
+/* 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.  */
+
+value
+value_being_returned (valtype, retbuf)
+     register struct type *valtype;
+     char retbuf[REGISTER_BYTES];
+{
+  register value val;
+
+  if (TYPE_CODE (valtype) == TYPE_CODE_STRUCT
+      || TYPE_CODE (valtype) == TYPE_CODE_UNION)
+    return value_at (valtype, EXTRACT_STRUCT_VALUE_ADDRESS (retbuf));
+
+  val = allocate_value (valtype);
+  EXTRACT_RETURN_VALUE (valtype, retbuf, VALUE_CONTENTS (val));
+
+  return val;
+}
+
+/* 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;
+  long 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);
+    }
+}
+\f
+static
+initialize ()
+{
+  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).");
+}
+
+END_FILE
diff --git a/gdb/vax-opcode.h b/gdb/vax-opcode.h
new file mode 100644 (file)
index 0000000..1ad1454
--- /dev/null
@@ -0,0 +1,365 @@
+/* vax.opcode.h */
+
+#ifndef vax_opcodeT
+#define vax_opcodeT int
+#endif /* no vax_opcodeT */
+
+struct vot_wot                 /* vax opcode table: wot to do with this */
+                               /* particular opcode */
+{
+  char *            args;      /* how to compile said opcode */
+  vax_opcodeT       code;      /* op-code (may be > 8 bits!) */
+};
+
+struct vot                     /* vax opcode text */
+{
+  char *            name;      /* opcode name: lowercase string  [key]  */
+  struct vot_wot    detail;    /* rest of opcode table          [datum] */
+};
+
+#define vot_how args
+#define vot_code code
+#define vot_detail detail
+#define vot_name name
+
+static struct vot
+votstrs[] =
+{
+{    "halt",   {"",                    0x00    } },
+{    "nop",    {"",                    0x01    } },
+{    "rei",    {"",                    0x02    } },
+{    "bpt",    {"",                    0x03    } },
+{    "ret",    {"",                    0x04    } },
+{    "rsb",    {"",                    0x05    } },
+{    "ldpctx", {"",                    0x06    } },
+{    "svpctx", {"",                    0x07    } },
+{    "cvtps",  {"rwabrwab",            0x08    } },
+{    "cvtsp",  {"rwabrwab",            0x09    } },
+{    "index",  {"rlrlrlrlrlwl",        0x0a    } },
+{    "crc",    {"abrlrwab",            0x0b    } },
+{    "prober", {"rbrwab",              0x0c    } },
+{    "probew", {"rbrwab",              0x0d    } },
+{    "insque", {"abab",                0x0e    } },
+{    "remque", {"abwl",                0x0f    } },
+{    "bsbb",   {"bb",                  0x10    } },
+{    "brb",    {"bb",                  0x11    } },
+{    "bneq",   {"bb",                  0x12    } },
+{    "bnequ",  {"bb",                  0x12    } },
+{    "beql",   {"bb",                  0x13    } },
+{    "beqlu",  {"bb",                  0x13    } },
+{    "bgtr",   {"bb",                  0x14    } },
+{    "bleq",   {"bb",                  0x15    } },
+{    "jsb",    {"ab",                  0x16    } },
+{    "jmp",    {"ab",                  0x17    } },
+{    "bgeq",   {"bb",                  0x18    } },
+{    "blss",   {"bb",                  0x19    } },
+{    "bgtru",  {"bb",                  0x1a    } },
+{    "blequ",  {"bb",                  0x1b    } },
+{    "bvc",    {"bb",                  0x1c    } },
+{    "bvs",    {"bb",                  0x1d    } },
+{    "bcc",    {"bb",                  0x1e    } },
+{    "bgequ",  {"bb",                  0x1e    } },
+{    "blssu",  {"bb",                  0x1f    } },
+{    "bcs",    {"bb",                  0x1f    } },
+{    "addp4",  {"rwabrwab",            0x20    } },
+{    "addp6",  {"rwabrwabrwab",        0x21    } },
+{    "subp4",  {"rwabrwab",            0x22    } },
+{    "subp6",  {"rwabrwabrwab",        0x23    } },
+{    "cvtpt",  {"rwababrwab",          0x24    } },
+{    "mulp",   {"rwabrwabrwab",        0x25    } },
+{    "cvttp",  {"rwababrwab",          0x26    } },
+{    "divp",   {"rwabrwabrwab",        0x27    } },
+{    "movc3",  {"rwabab",              0x28    } },
+{    "cmpc3",  {"rwabab",              0x29    } },
+{    "scanc",  {"rwababrb",            0x2a    } },
+{    "spanc",  {"rwababrb",            0x2b    } },
+{    "movc5",  {"rwabrbrwab",          0x2c    } },
+{    "cmpc5",  {"rwabrbrwab",          0x2d    } },
+{    "movtc",  {"rwabrbabrwab",        0x2e    } },
+{    "movtuc", {"rwabrbabrwab",        0x2f    } },
+{    "bsbw",   {"bw",                  0x30    } },
+{    "brw",    {"bw",                  0x31    } },
+{    "cvtwl",  {"rwwl",                0x32    } },
+{    "cvtwb",  {"rwwb",                0x33    } },
+{    "movp",   {"rwabab",              0x34    } },
+{    "cmpp3",  {"rwabab",              0x35    } },
+{    "cvtpl",  {"rwabwl",              0x36    } },
+{    "cmpp4",  {"rwabrwab",            0x37    } },
+{    "editpc", {"rwababab",            0x38    } },
+{    "matchc", {"rwabrwab",            0x39    } },
+{    "locc",   {"rbrwab",              0x3a    } },
+{    "skpc",   {"rbrwab",              0x3b    } },
+{    "movzwl", {"rwwl",                0x3c    } },
+{    "acbw",   {"rwrwmwbw",            0x3d    } },
+{    "movaw",  {"awwl",                0x3e    } },
+{    "pushaw", {"aw",                  0x3f    } },
+{    "addf2",  {"rfmf",                0x40    } },
+{    "addf3",  {"rfrfwf",              0x41    } },
+{    "subf2",  {"rfmf",                0x42    } },
+{    "subf3",  {"rfrfwf",              0x43    } },
+{    "mulf2",  {"rfmf",                0x44    } },
+{    "mulf3",  {"rfrfwf",              0x45    } },
+{    "divf2",  {"rfmf",                0x46    } },
+{    "divf3",  {"rfrfwf",              0x47    } },
+{    "cvtfb",  {"rfwb",                0x48    } },
+{    "cvtfw",  {"rfww",                0x49    } },
+{    "cvtfl",  {"rfwl",                0x4a    } },
+{    "cvtrfl", {"rfwl",                0x4b    } },
+{    "cvtbf",  {"rbwf",                0x4c    } },
+{    "cvtwf",  {"rwwf",                0x4d    } },
+{    "cvtlf",  {"rlwf",                0x4e    } },
+{    "acbf",   {"rfrfmfbw",            0x4f    } },
+{    "movf",   {"rfwf",                0x50    } },
+{    "cmpf",   {"rfrf",                0x51    } },
+{    "mnegf",  {"rfwf",                0x52    } },
+{    "tstf",   {"rf",                  0x53    } },
+{    "emodf",  {"rfrbrfwlwf",          0x54    } },
+{    "polyf",  {"rfrwab",              0x55    } },
+{    "cvtfd",  {"rfwd",                0x56    } },
+                                        /* opcode 57 is not defined yet */
+{    "adawi",  {"rwmw",                0x58    } },
+                                        /* opcode 59 is not defined yet */
+                                        /* opcode 5a is not defined yet */
+                                        /* opcode 5b is not defined yet */
+{    "insqhi", {"abaq",                0x5c    } },
+{    "insqti", {"abaq",                0x5d    } },
+{    "remqhi", {"aqwl",                0x5e    } },
+{    "remqti", {"aqwl",                0x5f    } },
+{    "addd2",  {"rdmd",                0x60    } },
+{    "addd3",  {"rdrdwd",              0x61    } },
+{    "subd2",  {"rdmd",                0x62    } },
+{    "subd3",  {"rdrdwd",              0x63    } },
+{    "muld2",  {"rdmd",                0x64    } },
+{    "muld3",  {"rdrdwd",              0x65    } },
+{    "divd2",  {"rdmd",                0x66    } },
+{    "divd3",  {"rdrdwd",              0x67    } },
+{    "cvtdb",  {"rdwb",                0x68    } },
+{    "cvtdw",  {"rdww",                0x69    } },
+{    "cvtdl",  {"rdwl",                0x6a    } },
+{    "cvtrdl", {"rdwl",                0x6b    } },
+{    "cvtbd",  {"rbwd",                0x6c    } },
+{    "cvtwd",  {"rwwd",                0x6d    } },
+{    "cvtld",  {"rlwd",                0x6e    } },
+{    "acbd",   {"rdrdmdbw",            0x6f    } },
+{    "movd",   {"rdwd",                0x70    } },
+{    "cmpd",   {"rdrd",                0x71    } },
+{    "mnegd",  {"rdwd",                0x72    } },
+{    "tstd",   {"rd",                  0x73    } },
+{    "emodd",  {"rdrbrdwlwd",          0x74    } },
+{    "polyd",  {"rdrwab",              0x75    } },
+{    "cvtdf",  {"rdwf",                0x76    } },
+                                        /* opcode 77 is not defined yet */
+{    "ashl",   {"rbrlwl",              0x78    } },
+{    "ashq",   {"rbrqwq",              0x79    } },
+{    "emul",   {"rlrlrlwq",            0x7a    } },
+{    "ediv",   {"rlrqwlwl",            0x7b    } },
+{    "clrd",   {"wd",                  0x7c    } },
+{    "clrq",   {"wd",                  0x7c    } },
+{    "clrg",   {"wg",                  0x7c    } },
+{    "movq",   {"rqwq",                0x7d    } },
+{    "movaq",  {"aqwl",                0x7e    } },
+{    "movad",  {"adwl",                0x7e    } },
+{    "pushaq", {"aq",                  0x7f    } },
+{    "pushad", {"ad",                  0x7f    } },
+{    "addb2",  {"rbmb",                0x80    } },
+{    "addb3",  {"rbrbwb",              0x81    } },
+{    "subb2",  {"rbmb",                0x82    } },
+{    "subb3",  {"rbrbwb",              0x83    } },
+{    "mulb2",  {"rbmb",                0x84    } },
+{    "mulb3",  {"rbrbwb",              0x85    } },
+{    "divb2",  {"rbmb",                0x86    } },
+{    "divb3",  {"rbrbwb",              0x87    } },
+{    "bisb2",  {"rbmb",                0x88    } },
+{    "bisb3",  {"rbrbwb",              0x89    } },
+{    "bicb2",  {"rbmb",                0x8a    } },
+{    "bicb3",  {"rbrbwb",              0x8b    } },
+{    "xorb2",  {"rbmb",                0x8c    } },
+{    "xorb3",  {"rbrbwb",              0x8d    } },
+{    "mnegb",  {"rbwb",                0x8e    } },
+{    "caseb",  {"rbrbrb",              0x8f    } },
+{    "movb",   {"rbwb",                0x90    } },
+{    "cmpb",   {"rbrb",                0x91    } },
+{    "mcomb",  {"rbwb",                0x92    } },
+{    "bitb",   {"rbrb",                0x93    } },
+{    "clrb",   {"wb",                  0x94    } },
+{    "tstb",   {"rb",                  0x95    } },
+{    "incb",   {"mb",                  0x96    } },
+{    "decb",   {"mb",                  0x97    } },
+{    "cvtbl",  {"rbwl",                0x98    } },
+{    "cvtbw",  {"rbww",                0x99    } },
+{    "movzbl", {"rbwl",                0x9a    } },
+{    "movzbw", {"rbww",                0x9b    } },
+{    "rotl",   {"rbrlwl",              0x9c    } },
+{    "acbb",   {"rbrbmbbw",            0x9d    } },
+{    "movab",  {"abwl",                0x9e    } },
+{    "pushab", {"ab",                  0x9f    } },
+{    "addw2",  {"rwmw",                0xa0    } },
+{    "addw3",  {"rwrwww",              0xa1    } },
+{    "subw2",  {"rwmw",                0xa2    } },
+{    "subw3",  {"rwrwww",              0xa3    } },
+{    "mulw2",  {"rwmw",                0xa4    } },
+{    "mulw3",  {"rwrwww",              0xa5    } },
+{    "divw2",  {"rwmw",                0xa6    } },
+{    "divw3",  {"rwrwww",              0xa7    } },
+{    "bisw2",  {"rwmw",                0xa8    } },
+{    "bisw3",  {"rwrwww",              0xa9    } },
+{    "bicw2",  {"rwmw",                0xaa    } },
+{    "bicw3",  {"rwrwww",              0xab    } },
+{    "xorw2",  {"rwmw",                0xac    } },
+{    "xorw3",  {"rwrwww",              0xad    } },
+{    "mnegw",  {"rwww",                0xae    } },
+{    "casew",  {"rwrwrw",              0xaf    } },
+{    "movw",   {"rwww",                0xb0    } },
+{    "cmpw",   {"rwrw",                0xb1    } },
+{    "mcomw",  {"rwww",                0xb2    } },
+{    "bitw",   {"rwrw",                0xb3    } },
+{    "clrw",   {"ww",                  0xb4    } },
+{    "tstw",   {"rw",                  0xb5    } },
+{    "incw",   {"mw",                  0xb6    } },
+{    "decw",   {"mw",                  0xb7    } },
+{    "bispsw", {"rw",                  0xb8    } },
+{    "bicpsw", {"rw",                  0xb9    } },
+{    "popr",   {"rw",                  0xba    } },
+{    "pushr<", {"rw",                  0xbb    } },
+{    "chmk",   {"rw",                  0xbc    } },
+{    "chme",   {"rw",                  0xbd    } },
+{    "chms",   {"rw",                  0xbe    } },
+{    "chmu",   {"rw",                  0xbf    } },
+{    "addl2",  {"rlml",                0xc0    } },
+{    "addl3",  {"rlrlwl",              0xc1    } },
+{    "subl2",  {"rlml",                0xc2    } },
+{    "subl3",  {"rlrlwl",              0xc3    } },
+{    "mull2",  {"rlml",                0xc4    } },
+{    "mull3",  {"rlrlwl",              0xc5    } },
+{    "divl2",  {"rlml",                0xc6    } },
+{    "divl3",  {"rlrlwl",              0xc7    } },
+{    "bisl2",  {"rlml",                0xc8    } },
+{    "bisl3",  {"rlrlwl",              0xc9    } },
+{    "bicl2",  {"rlml",                0xca    } },
+{    "bicl3",  {"rlrlwl",              0xcb    } },
+{    "xorl2",  {"rlml",                0xcc    } },
+{    "xorl3",  {"rlrlwl",              0xcd    } },
+{    "mnegl",  {"rlwl",                0xce    } },
+{    "casel",  {"rlrlrl",              0xcf    } },
+{    "movl",   {"rlwl",                0xd0    } },
+{    "cmpl",   {"rlrl",                0xd1    } },
+{    "mcoml",  {"rlwl",                0xd2    } },
+{    "bitl",   {"rlrl",                0xd3    } },
+{    "clrf",   {"wf",                  0xd4    } },
+{    "clrl",   {"wl",                  0xd4    } },
+{    "tstl",   {"rl",                  0xd5    } },
+{    "incl",   {"ml",                  0xd6    } },
+{    "decl",   {"ml",                  0xd7    } },
+{    "adwc",   {"rlml",                0xd8    } },
+{    "sbwc",   {"rlml",                0xd9    } },
+{    "mtpr",   {"rlrl",                0xda    } },
+{    "mfpr",   {"rlwl",                0xdb    } },
+{    "movpsl", {"wl",                  0xdc    } },
+{    "pushl",  {"rl",                  0xdd    } },
+{    "moval",  {"alwl",                0xde    } },
+{    "movaf",  {"afwl",                0xde    } },
+{    "pushal", {"al",                  0xdf    } },
+{    "pushaf", {"af",                  0xdf    } },
+{    "bbs",    {"rlabbb",              0xe0    } },
+{    "bbc",    {"rlabbb",              0xe1    } },
+{    "bbss",   {"rlabbb",              0xe2    } },
+{    "bbcs",   {"rlabbb",              0xe3    } },
+{    "bbsc",   {"rlabbb",              0xe4    } },
+{    "bbcc",   {"rlabbb",              0xe5    } },
+{    "bbssi",  {"rlabbb",              0xe6    } },
+{    "bbcci",  {"rlabbb",              0xe7    } },
+{    "blbs",   {"rlbb",                0xe8    } },
+{    "blbc",   {"rlbb",                0xe9    } },
+{    "ffs",    {"rlrbvbwl",            0xea    } },
+{    "ffc",    {"rlrbvbwl",            0xeb    } },
+{    "cmpv",   {"rlrbvbrl",            0xec    } },
+{    "cmpzv",  {"rlrbvbrl",            0xed    } },
+{    "extv",   {"rlrbvbwl",            0xee    } },
+{    "extzv",  {"rlrbvbwl",            0xef    } },
+{    "insv",   {"rlrlrbvb",            0xf0    } },
+{    "acbl",   {"rlrlmlbw",            0xf1    } },
+{    "aoblss", {"rlmlbb",              0xf2    } },
+{    "aobleq", {"rlmlbb",              0xf3    } },
+{    "sobgeq", {"mlbb",                0xf4    } },
+{    "sobgtr", {"mlbb",                0xf5    } },
+{    "cvtlb",  {"rlwb",                0xf6    } },
+{    "cvtlw",  {"rlww",                0xf7    } },
+{    "ashp",   {"rbrwabrbrwab",        0xf8    } },
+{    "cvtlp",  {"rlrwab",              0xf9    } },
+{    "callg",  {"abab",                0xfa    } },
+{    "calls",  {"rlab",                0xfb    } },
+{    "xfc",    {"",                    0xfc    } },
+                                        /* undefined opcodes here */
+{    "cvtdh",  {"rdwh",                0x32fd  } },
+{    "cvtgf",  {"rgwh",                0x33fd  } },
+{    "addg2",  {"rgmg",                0x40fd  } },
+{    "addg3",  {"rgrgwg",              0x41fd  } },
+{    "subg2",  {"rgmg",                0x42fd  } },
+{    "subg3",  {"rgrgwg",              0x43fd  } },
+{    "mulg2",  {"rgmg",                0x44fd  } },
+{    "mulg3",  {"rgrgwg",              0x45fd  } },
+{    "divg2",  {"rgmg",                0x46fd  } },
+{    "divg3",  {"rgrgwg",              0x47fd  } },
+{    "cvtgb",  {"rgwb",                0x48fd  } },
+{    "cvtgw",  {"rgww",                0x49fd  } },
+{    "cvtgl",  {"rgwl",                0x4afd  } },
+{    "cvtrgl", {"rgwl",                0x4bfd  } },
+{    "cvtbg",  {"rbwg",                0x4cfd  } },
+{    "cvtwg",  {"rwwg",                0x4dfd  } },
+{    "cvtlg",  {"rlwg",                0x4efd  } },
+{    "acbg",   {"rgrgmgbw",            0x4ffd  } },
+{    "movg",   {"rgwg",                0x50fd  } },
+{    "cmpg",   {"rgrg",                0x51fd  } },
+{    "mnegg",  {"rgwg",                0x52fd  } },
+{    "tstg",   {"rg",                  0x53fd  } },
+{    "emodg",  {"rgrwrgwlwg",          0x54fd  } },
+{    "polyg",  {"rgrwab",              0x55fd  } },
+{    "cvtgh",  {"rgwh",                0x56fd  } },
+                                        /* undefined opcodes here */
+{    "addh2",  {"rhmh",                0x60fd  } },
+{    "addh3",  {"rhrhwh",              0x61fd  } },
+{    "subh2",  {"rhmh",                0x62fd  } },
+{    "subh3",  {"rhrhwh",              0x63fd  } },
+{    "mulh2",  {"rhmh",                0x64fd  } },
+{    "mulh3",  {"rhrhwh",              0x65fd  } },
+{    "divh2",  {"rhmh",                0x66fd  } },
+{    "divh3",  {"rhrhwh",              0x67fd  } },
+{    "cvthb",  {"rhwb",                0x68fd  } },
+{    "cvthw",  {"rhww",                0x69fd  } },
+{    "cvthl",  {"rhwl",                0x6afd  } },
+{    "cvtrhl", {"rhwl",                0x6bfd  } },
+{    "cvtbh",  {"rbwh",                0x6cfd  } },
+{    "cvtwh",  {"rwwh",                0x6dfd  } },
+{    "cvtlh",  {"rlwh",                0x6efd  } },
+{    "acbh",   {"rhrhmhbw",            0x6ffd  } },
+{    "movh",   {"rhwh",                0x70fd  } },
+{    "cmph",   {"rhrh",                0x71fd  } },
+{    "mnegh",  {"rhwh",                0x72fd  } },
+{    "tsth",   {"rh",                  0x73fd  } },
+{    "emodh",  {"rhrwrhwlwh",          0x74fd  } },
+{    "polyh",  {"rhrwab",              0x75fd  } },
+{    "cvthg",  {"rhwg",                0x76fd  } },
+                                        /* undefined opcodes here */
+{    "clrh",   {"wh",                  0x7cfd  } },
+{    "clro",   {"wo",                  0x7cfd  } },
+{    "movo",   {"rowo",                0x7dfd  } },
+{    "movah",  {"ahwl",                0x7efd  } },
+{    "movao",  {"aowl",                0x7efd  } },
+{    "pushah", {"ah",                  0x7ffd  } },
+{    "pushao", {"ao",                  0x7ffd  } },
+                                        /* undefined opcodes here */
+{    "cvtfh",  {"rfwh",                0x98fd  } },
+{    "cvtfg",  {"rfwg",                0x99fd  } },
+                                        /* undefined opcodes here */
+{    "cvthf",  {"rhwf",                0xf6fd  } },
+{    "cvthd",  {"rhwd",                0xf7fd  } },
+                                        /* undefined opcodes here */
+{    "bugl",   {"rl",                  0xfdff  } },
+{    "bugw",   {"rw",                  0xfeff  } },
+                                        /* undefined opcodes here */
+
+{      ""       ,   ""          } /* empty is end sentinel */
+
+};                             /* votstrs */
+
+/* end: vax.opcode.h */
diff --git a/gdb/vax-pinsn.c b/gdb/vax-pinsn.c
new file mode 100644 (file)
index 0000000..9d97415
--- /dev/null
@@ -0,0 +1,241 @@
+/* Print vax instructions 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 <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "vax-opcode.h"
+
+/* Vax instructions are never longer than this.  */
+#define MAXLEN 62
+
+/* Number of elements in the opcode table.  */
+#define NOPCODES (sizeof votstrs / sizeof votstrs[0])
+
+extern char *reg_names[];
+
+static unsigned char *print_insn_arg ();
+\f
+/* Print the vax 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;
+
+  read_memory (memaddr, buffer, MAXLEN);
+
+  for (i = 0; i < NOPCODES; i++)
+    if (votstrs[i].detail.code == buffer[0]
+       || votstrs[i].detail.code == *(unsigned short *)buffer)
+      break;
+
+  /* Handle undefined instructions.  */
+  if (i == NOPCODES)
+    {
+      fprintf (stream, "0%o", buffer[0]);
+      return 1;
+    }
+
+  fprintf (stream, "%s", votstrs[i].name);
+
+  /* Point at first byte of argument data,
+     and at descriptor for first argument.  */
+  p = buffer + 1 + (votstrs[i].detail.code >= 0x100);
+  d = votstrs[i].detail.args;
+
+  if (*d)
+    fputc (' ', stream);
+
+  while (*d)
+    {
+      p = print_insn_arg (d, p, memaddr + (p - buffer), stream);
+      d += 2;
+      if (*d)
+       fprintf (stream, ",");
+    }
+  return p - buffer;
+}
+
+static unsigned char *
+print_insn_arg (d, p, addr, stream)
+     char *d;
+     register char *p;
+     CORE_ADDR addr;
+     FILE *stream;
+{
+  register int regnum = *p & 0xf;
+  float floatlitbuf;
+
+  if (*d == 'b')
+    {
+      if (d[1] == 'b')
+       fprintf (stream, "0x%x", addr + *p++ + 1);
+      else
+       {
+         fprintf (stream, "0x%x", addr + *(short *)p + 2);
+         p += 2;
+       }
+    }
+  else
+    switch ((*p++ >> 4) & 0xf)
+      {
+      case 0:
+      case 1:
+      case 2:
+      case 3:                  /* Literal mode */
+       if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
+         {
+           *(int *)&floatlitbuf = 0x4000 + ((p[-1] & 0x3f) << 4);
+           fprintf (stream, "$%f", floatlitbuf);
+         }
+       else
+         fprintf (stream, "$%d", p[-1] & 0x3f);
+       break;
+
+      case 4:                  /* Indexed */
+       p = (char *) print_insn_arg (d, p, addr + 1, stream);
+       fprintf (stream, "[%s]", reg_names[regnum]);
+       break;
+
+      case 5:                  /* Register */
+       fprintf (stream, reg_names[regnum]);
+       break;
+
+      case 7:                  /* Autodecrement */
+       fputc ('-', stream);
+      case 6:                  /* Register deferred */
+       fprintf (stream, "(%s)", reg_names[regnum]);
+       break;
+
+      case 9:                  /* Autoincrement deferred */
+       fputc ('@', stream);
+       if (regnum == PC_REGNUM)
+         {
+           fputc ('#', stream);
+           print_address (*(long *)p, stream);
+           p += 4;
+           break;
+         }
+      case 8:                  /* Autoincrement */
+       if (regnum == PC_REGNUM)
+         {
+           fputc ('#', stream);
+           switch (d[1])
+             {
+             case 'b':
+               fprintf (stream, "%d", *p++);
+               break;
+
+             case 'w':
+               fprintf (stream, "%d", *(short *)p);
+               p += 2;
+               break;
+
+             case 'l':
+               fprintf (stream, "%d", *(long *)p);
+               p += 4;
+               break;
+
+             case 'q':
+               fprintf (stream, "0x%x%08x", ((long *)p)[1], ((long *)p)[0]);
+               p += 8;
+               break;
+
+             case 'o':
+               fprintf (stream, "0x%x%08x%08x%08x",
+                        ((long *)p)[3], ((long *)p)[2],
+                        ((long *)p)[1], ((long *)p)[0]);
+               p += 16;
+               break;
+
+             case 'f':
+               if (INVALID_FLOAT (p, 4))
+                 fprintf (stream, "<<invalid float 0x%x>>", *(int *) p);
+               else
+                 fprintf (stream, "%f", *(float *) p);
+               p += 4;
+               break;
+
+             case 'd':
+               if (INVALID_FLOAT (p, 8))
+                 fprintf (stream, "<<invalid float 0x%x%08x>>",
+                          ((long *)p)[1], ((long *)p)[0]);
+               else
+                 fprintf (stream, "%f", *(double *) p);
+               p += 8;
+               break;
+
+             case 'g':
+               fprintf (stream, "g-float");
+               p += 8;
+               break;
+
+             case 'h':
+               fprintf (stream, "h-float");
+               p += 16;
+               break;
+
+             }
+         }
+       else
+         fprintf (stream, "(%s)+", reg_names[regnum]);
+       break;
+
+      case 11:                 /* Byte displacement deferred */
+       fputc ('@', stream);
+      case 10:                 /* Byte displacement */
+       if (regnum == PC_REGNUM)
+         print_address (addr + *p + 2, stream);
+       else
+         fprintf (stream, "%d(%s)", *p, reg_names[regnum]);
+       p += 1;
+       break;
+
+      case 13:                 /* Word displacement deferred */
+       fputc ('@', stream);
+      case 12:                 /* Word displacement */
+       if (regnum == PC_REGNUM)
+         print_address (addr + *(short *)p + 3, stream);
+       else
+         fprintf (stream, "%d(%s)", *(short *)p, reg_names[regnum]);
+       p += 2;
+       break;
+
+      case 15:                 /* Long displacement deferred */
+       fputc ('@', stream);
+      case 14:                 /* Long displacement */
+       if (regnum == PC_REGNUM)
+         print_address (addr + *(long *)p + 5, stream);
+       else
+         fprintf (stream, "%d(%s)", *(long *)p, reg_names[regnum]);
+       p += 4;
+      }
+
+  return (unsigned char *) p;
+}
diff --git a/gdb/version.c b/gdb/version.c
new file mode 100644 (file)
index 0000000..452ccd8
--- /dev/null
@@ -0,0 +1,3 @@
+/* Define the current version number of GDB.  */
+
+char *version = "2.4+";
diff --git a/gdb/wait.h b/gdb/wait.h
new file mode 100644 (file)
index 0000000..fe7f384
--- /dev/null
@@ -0,0 +1,25 @@
+
+/* Define how to access the structure that the wait system call stores.
+   On many systems, there is a structure defined for this.
+   But on vanilla-ish USG systems there is not.  */
+
+#ifndef HAVE_WAIT_STRUCT
+#define WAITTYPE int
+#define WIFSTOPPED(w) (((w)&0377) == 0177)
+#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
+#define WIFEXITED(w) (((w)&0377) == 0)
+#define WRETCODE(w) ((w) >> 8)
+#define WSTOPSIG(w) ((w) >> 8)
+#define WCOREDUMP(w) (((w)&0200) != 0)
+#define WTERMSIG(w) ((w) & 0177)
+#define WSETSTOP(w,sig)  ((w) = (0177 | ((sig) << 8)))
+#else
+#include <sys/wait.h>
+#define WAITTYPE union wait
+#define WRETCODE(w) (w).w_retcode
+#define WSTOPSIG(w) (w).w_stopsig
+#define WCOREDUMP(w) (w).w_coredump
+#define WTERMSIG(w) (w).w_termsig
+#define WSETSTOP(w,sig)  \
+  ((w).stopsig = (sig), (w).coredump = 0, (w).termsig = 0177)
+#endif
diff --git a/gdb/xgdb.c b/gdb/xgdb.c
new file mode 100644 (file)
index 0000000..1b858e8
--- /dev/null
@@ -0,0 +1,672 @@
+/* Interface from GDB to X windows.
+   Copyright (C) 1987 Free Software Foundation, Inc.
+
+GDB is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY.  No author or distributor accepts responsibility to anyone
+for the consequences of using it or for whether it serves any
+particular purpose or works at all, unless he says so in writing.
+Refer to the GDB General Public License for full details.
+
+Everyone is granted permission to copy, modify and redistribute GDB,
+but only under the conditions described in the GDB General Public
+License.  A copy of this license is supposed to have been given to you
+along with GDB so you can know your rights and responsibilities.  It
+should be in a file named COPYING.  Among other things, the copyright
+notice and this notice must be preserved on all copies.
+
+In other words, go ahead and share GDB, but don't try to stop
+anyone else from sharing it farther.  Help stamp out software hoarding!
+*/
+
+/* Original version was contributed by Derek Beatty, 30 June 87.  */
+
+#include "defs.h"
+#include "initialize.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+
+#include <X11/Xlib.h>
+#include <X11/Intrinsic.h>
+#include <X11/Xresource.h>
+#include <X11/Atoms.h>
+#include <X11/TopLevel.h>
+#include <X11/VPane.h>
+#include <X11/Label.h>
+#include <X11/Text.h>
+#include <X11/Command.h>
+#include <X11/ButtonBox.h>
+
+#include <stdio.h>
+
+/* Cursor used in GDB window.  */
+
+#define gdb_width 16
+#define gdb_height 16
+#define gdb_x_hot 7
+#define gdb_y_hot 0
+static short gdb_bits[] = {
+   0x0000, 0x0140, 0x0220, 0x0220,
+   0x23e2, 0x13e4, 0x09c8, 0x0ff8,
+   0x0220, 0x3ffe, 0x0630, 0x03e0,
+   0x0220, 0x1ffc, 0x2632, 0x01c0};
+
+#define gdb_mask_width 16
+#define gdb_mask_height 16
+#define gdb_mask_x_hot 7
+#define gdb_mask_y_hot 0
+static short gdb_mask_bits[] = {
+   0x0360, 0x07f0, 0x07f0, 0x77f7,
+   0x7fff, 0x7fff, 0x1ffc, 0x1ffc,
+   0x7fff, 0x7fff, 0x7fff, 0x0ff8,
+   0x3ffe, 0x7fff, 0x7fff, 0x7fff};
+
+/* The X display on which the window appears.  */
+
+Display *screen_display;
+
+/* The graphics context.  */
+
+GC default_gc;
+
+/* Windows manipulated by this package.  */
+
+static Window icon_window;
+static Widget containing_widget;
+static Widget source_name_widget;
+static Widget source_text_widget;
+static Widget exec_name_widget;
+static Widget button_box_widget;
+
+/* Source text display.  */
+
+static struct symtab *source_window_symtab = 0;
+
+/* Forward declarations */
+
+static Widget create_text_widget ();
+
+START_FILE
+\f
+/* Display an appropriate piece of source code in the source window.  */
+
+xgdb_display_source ()
+{
+  char *filename;
+  static Arg labelArgs[1];
+  int linenumbers_changed = 0;
+  static int new = 1;
+
+  struct symtab_and_line get_selected_frame_sal ();
+  struct symtab_and_line sal;
+  struct frame_info fi;
+
+  /* Do nothing if called before we are initialized */
+
+  if (!containing_widget) return;
+
+  /* Get the symtab and line number of the selected frame.  */
+
+  fi = get_frame_info (selected_frame);
+  sal = find_pc_line (fi.pc, fi.next_frame);
+
+  /* Strictly this is wrong, but better than a blank display */
+
+  if (sal.symtab == NULL) 
+    {
+      sal.symtab = current_source_symtab;
+      /* current_source_line may be off by a small number like 4 */
+      sal.line = current_source_line;
+    }
+
+  /* Do a path search and get the exact filename of this source file.
+     Also scan it and find its source lines if not already done.  */
+
+  if (sal.symtab)
+    linenumbers_changed = get_filename_and_charpos (sal.symtab, sal.line,
+                                                   &filename);
+
+  if (!filename) sal.symtab = NULL;
+
+  /* If the source window may be wrong, destroy it (and make a new one).  */
+
+  if (linenumbers_changed || source_window_symtab != sal.symtab)
+    {
+      static Arg fileArgs[1];
+      new = 1;
+      source_window_symtab = sal.symtab;
+
+      XtSetArg (fileArgs[0], XtNfile, filename);
+      XtSetValues (source_text_widget, fileArgs, XtNumber (fileArgs));
+
+      XtSetArg (labelArgs[0], XtNlabel,
+               filename ? filename : "No source displayed.");
+      XtSetValues (source_name_widget, labelArgs, XtNumber (labelArgs));
+      if (filename) free (filename);
+    }
+
+  /* Update display and cursor positions as necessary.
+     Cursor should be placed on line sal.line.  */
+
+  {
+    static int top_line_number, bottom_line_number;
+    int current_top;
+    Arg textArgs[1];
+
+    if (! new)
+      {
+       int new_top;
+
+       /* Get positions of start of display, and caret */
+       XtSetArg (textArgs[0], XtNdisplayPosition, NULL);
+       XtGetValues (source_text_widget, textArgs, XtNumber (textArgs));
+       new_top = source_charpos_line (source_window_symtab,
+                                      (int) textArgs[0].value);
+       bottom_line_number += new_top - top_line_number;
+       top_line_number = new_top;
+      }
+
+    /* If appropriate, scroll the text display.  */
+    if (sal.line < top_line_number
+       || sal.line > bottom_line_number
+       || new)
+      {
+       /* yes, these magic numbers are ugly, but I don't know how
+        * to get the height of a text widget in a V11-portable way
+        */
+       top_line_number = (sal.line > 15) ? sal.line - 15 : 0;
+       bottom_line_number = top_line_number + 35;
+      
+       XtSetArg (textArgs[0], XtNdisplayPosition,
+                 source_line_charpos (source_window_symtab, top_line_number));
+       XtSetValues (source_text_widget, textArgs, XtNumber (textArgs));
+      }
+
+    /* Set the text display cursor position within the text.  */
+
+    XtSetArg (textArgs[0], XtNinsertPosition, 
+             source_line_charpos (source_window_symtab, sal.line));
+    XtSetValues (source_text_widget, textArgs, XtNumber (textArgs));
+  }
+}
+\f
+/* Display FILENAME in the title bar at bottom of window.  */
+
+xgdb_display_exec_file (filename)
+     char *filename;
+{
+  static Arg labelArgs[1];
+
+  XtSetArg (labelArgs[0], XtNlabel, filename);
+  XtSetValues (exec_name_widget, labelArgs, XtNumber (labelArgs));
+}
+
+/* Do any necessary prompting, etc.  */
+
+static char *prompt_string;
+
+static void
+print_prompt ()
+{
+  if (prompt_string)
+    printf ("%s", prompt_string);
+}
+
+/* Handlers for buttons.  */
+
+/* Subroutine used by "print" and "print*" buttons.
+   STARFLAG is 1 for print*, 0 for print.
+   Get the "selection" from X and use it as the operand of a print command.  */
+
+static void
+print_1 (starflag)
+     int starflag;
+{
+  int selected_length;
+  char *selected_text;
+
+  char *cmd = starflag ? "print * " : "print ";
+  register int cmdlen = strlen (cmd);
+  
+  selected_text = XFetchBytes (&selected_length);
+  if (selected_length)
+    {
+      char *line = xmalloc (cmdlen + selected_length + 1);
+      strcpy (line, cmd);
+      strncpy (line + cmdlen, selected_text, selected_length);
+      line[cmdlen + selected_length] = 0;
+
+      execute_command (line, 0);
+
+      free (selected_text);
+      free (line);
+    }
+
+  print_prompt ();
+}
+
+static void
+print_button () 
+{
+  print_1 (0);
+}
+
+static void
+print_star_button () 
+{
+  print_1 (1);
+}
+\f
+/* Subroutine used by "stop at" and "go till" buttons.
+   Set a breakpoint at the position indicated by the "selection"
+   in the source window, and, if RUNFLAG is nonzero, continue.  */
+
+static void
+breakpoint_button_1 (runflag)
+     int runflag;
+{
+  XtTextPosition start, finish;
+  
+  XtTextGetSelectionPos (screen_display, source_text_widget, &start, &finish);
+  if (!source_window_symtab)
+    printf ("No source file displayed.\n");
+  else
+    {
+      set_breakpoint (source_window_symtab, 
+                     source_charpos_line (source_window_symtab, start),
+                     runflag);
+      if (runflag)
+       {
+         cont_command (0, 1);
+         xgdb_display_source ();
+       }
+    }
+  print_prompt ();
+}
+
+static void
+breakpoint_button ()
+{
+  breakpoint_button_1 (0);
+}
+
+static void
+until_button ()
+{
+  breakpoint_button_1 (1);
+}
+
+/* decide if a character is trash */
+static int
+garbage (c)
+     char c;
+{
+  if ('a' <= c && c <= 'z') return 0;
+  if ('A' <= c && c <= 'Z') return 0;
+  if ('0' <= c && c <= '9') return 0;
+  if (c == '_') return 0;
+  return 1;
+}
+
+/* Set a breakpoint at the place specified by the "selection" in X.  */
+
+static void
+explicit_breakpoint_button ()
+{
+  int selected_length;
+  char *selected_text;
+
+  selected_text = XFetchBytes (screen_display, &selected_length);
+  if (selected_length)
+    {
+      char *line = (char *) xmalloc (selected_length + 6);
+      register char *p, *sp, *end;
+
+      strcpy (line, "break ");
+
+      /* Copy selection but exclude "garbage" characters.  */
+
+      p = selected_text;
+      end = p + selected_length;
+      sp = line + strlen (line);
+
+      while (garbage (*p) && p != end) p++;
+      while (!garbage (*p) && p != end)
+       *sp++ = *p++;
+      *sp = 0;
+
+      execute_command (line, 0);
+      free (selected_text);
+      free (line);
+    }
+  print_prompt ();
+}
+\f
+/* Various trivial buttons,
+   most of which just run one GDB command with no arg.  */
+
+static void
+next_button ()
+{
+  execute_command ("next", 0);
+  xgdb_display_source ();
+  print_prompt ();
+}
+
+static void
+step_button ()
+{
+  execute_command ("step", 0);
+  xgdb_display_source ();
+  print_prompt ();
+}
+
+static void
+cont_button ()
+{
+  execute_command ("cont", 0);
+  xgdb_display_source ();
+  print_prompt ();
+}
+
+static void
+finish_button ()
+{
+  execute_command ("finish", 0);
+  xgdb_display_source ();
+  print_prompt ();
+}
+
+#if 0
+static void
+deiconify_button ()
+{
+  XUnmapWindow (screen_display, icon_window);
+  XMapWindow (screen_display, containing_widget);
+}
+
+static void
+iconify_button ()
+{
+#if 0
+  static Arg iconArgs[1];
+  XtSetArg (iconArgs[0], XtNlabel, prompt_string);
+  XtCommandSetValues (icon_window, iconArgs, XtNumber (iconArgs));
+#endif 0
+  XUnmapWindow (screen_display, containing_widget);
+  XMapWindow (screen_display, icon_window);
+}
+#endif 0
+
+static void
+up_button ()
+{
+  execute_command ("up", 0);
+  xgdb_display_source ();
+  print_prompt ();
+}
+
+static void
+down_button ()
+{
+  execute_command ("down", 0);
+  xgdb_display_source ();
+  print_prompt ();
+}
+\f
+/* Define and display all the buttons.  */
+
+static void
+addbutton (parent, name, function)
+     Widget parent;
+     char *name;
+     void (*function) ();
+{
+  static Arg commandArgs[2];
+
+  XtSetArg (commandArgs[0], XtNlabel, name);
+  XtSetArg (commandArgs[1], XtNfunction, function);
+  XtCreateWidget (name, commandWidgetClass, parent,
+                 commandArgs, XtNumber (commandArgs));
+}
+
+/* Create the button windows and store them in `buttons'.  */
+
+static void
+create_buttons (parent)
+     Widget parent;
+{
+  addbutton (parent, "Brk At", breakpoint_button);
+  addbutton (parent, "Brk In", explicit_breakpoint_button);
+  addbutton (parent, "Go 'til", until_button);
+
+  addbutton (parent, "Print", print_button);
+  addbutton (parent, "Print*", print_star_button);
+
+  addbutton (parent, "Next", next_button);
+  addbutton (parent, "Step", step_button);
+  addbutton (parent, "Cont", cont_button);
+  addbutton (parent, "Finish", finish_button);
+  
+  addbutton (parent, "Up", up_button);
+  addbutton (parent, "Down", down_button);
+
+/*  addbutton (parent, "Iconify", iconify_button); */
+}
+\f
+/* Create a "label window" that just displays the string LABEL.  */
+
+static Widget
+create_label (name, label)
+     char *name, *label;
+{
+  static Arg labelArgs[2];
+  
+  XtSetArg (labelArgs[0], XtNname, name);
+  XtSetArg (labelArgs[1], XtNlabel, label);
+  return XtCreateWidget ("label1", labelWidgetClass, containing_widget,
+                        labelArgs, XtNumber (labelArgs));
+}
+
+/* Create a subwindow of PARENT that displays and scrolls the contents
+   of file FILENAME.  */
+
+static Widget
+create_text_widget (parent, filename)
+     Window parent;
+     char *filename;
+{
+  static Arg fileArgs[2];
+  
+  XtSetArg (fileArgs[0], XtNfile, filename);
+  XtSetArg (fileArgs[1], XtNtextOptions, scrollVertical);
+  return XtTextDiskCreate (parent, fileArgs, XtNumber (fileArgs));
+}
+\f
+/* Entry point to create the widgets representing our display.  */
+
+int
+xgdb_create_window ()
+{
+  static Arg frameArgs[]= {
+      {XtNwidth, (XtArgVal) 600},
+      {XtNheight, (XtArgVal) 700},
+  };
+  
+  XrmResourceDataBase db;
+  FILE *rdb_file;
+  XGCValues dummy;
+  
+  /* Init and database stuff.  */
+  screen_display = XOpenDisplay (NULL);
+  if (screen_display == 0)
+    {
+      fprintf (stderr, "Cannot connect to X server");
+      return 0;
+    }
+
+  {
+    char *dummy1[1];
+    dummy1[0] = 0;
+    XtInitialize ("gdb", "gdb", 0, 0, 0, dummy1);
+  }
+
+  /* should be checking .Xdefaults in $HOME */
+  rdb_file = fopen (".Xresources", "r");
+  if (rdb_file != NULL)
+    {
+      XrmGetDataBase (rdb_file, &db);
+      XrmSetCurrentDataBase (db);
+      fclose (rdb_file);
+    }
+  
+  /* Create the containing_widget.  */
+
+  containing_widget = XtCreateWidget ("frame", vPaneWidgetClass, 0,
+                                     frameArgs, XtNumber (frameArgs));
+  
+  default_gc = XCreateGC (screen_display, containing_widget, 0, dummy);
+
+  /* Create source file name window and add to containing_widget */
+  source_name_widget
+    = create_label ("Source File", "No source file yet.");
+
+  /* Create an empty source-display window and add to containing_widget */
+  source_text_widget = create_text_widget (containing_widget, "/dev/null");
+
+  /* Create window full of buttons.  */
+  button_box_widget = XtCreateWidget ("Buttons", buttonBoxWidgetClass,
+                                     containing_widget, NULL, 0);
+  create_buttons (button_box_widget);
+
+  /* Create exec file name window and add */
+  exec_name_widget = create_label ("Executable", "No executable specified.");
+
+#if 0
+  /* Create icon window.  */
+  {
+    static Arg iconArgs[2];
+    void (*compiler_bug) () = deiconify_button;
+    XtSetArg (iconArgs[0], XtNlabel, "(gdb)");
+    XtSetArg (iconArgs[1], XtNfunction, compiler_bug);
+    icon_window = XtCommandCreate (DefaultRootWindow (screen_display),
+                                  iconArgs, XtNumber (iconArgs));
+    XMoveWindow (screen_display, icon_window, 100, 100);       /* HACK */
+#if 0
+    XSetIconWindow (screen_display, containing_widget, icon_window);
+#endif 0
+  }
+#endif 0
+
+#if 0
+  /* Now make the whole thing appear on the display.  */
+  {
+    Pixmap pm1, pm2;
+    XImage image;
+    Cursor curse;
+
+    image.width = gdb_width;
+    image.height = gdb_height;
+    image.xoffset = 0;
+    image.format = XYBitmap;
+    image.byte_order = LSBFirst;
+    image.bitmap_unit = 16;
+    image.bitmap_bit_order = LSBFirst;
+    image.depth = 1;
+    image.bytes_per_line = 2;
+    image.bits_per_pixel = 1;
+
+    pm1 = XCreatePixmap (screen_display, DefaultScreen (screen_display),
+                        gdb_width, gdb_height, 1);
+    pm2 = XCreatePixmap (screen_display, DefaultScreen (screen_display),
+                        gdb_width, gdb_height, 1);
+
+    image.data = (char *) gdb_bits;
+    XPutImage (screen_display, pm1, default_gc, &image, 0, 0, 0, 0,
+              gdb_width, gdb_height);
+
+    image.data = (char *) gdb_mask_bits;
+    XPutImage (screen_display, pm2, default_gc, &image, 0, 0, 0, 0,
+              gdb_width, gdb_height);
+
+    curse = XCreatePixmapCursor (screen_display, pm1, pm2,
+                                BlackPixel (screen_display,
+                                            DefaultScreen (screen_display)),
+                                WhitePixel (screen_display,
+                                            DefaultScreen (screen_display)),
+                                gdb_x_hot, gdb_y_hot);
+
+    XFreePixmap (screen_display, pm1);
+    XFreePixmap (screen_display, pm2);
+
+    XDefineCursor (screen_display, containing_widget, curse);
+    XDefineCursor (screen_display, icon_window, curse);
+  }
+#endif 0
+
+  XtRealizeWidget (containing_widget);
+  XFlush (screen_display);
+
+  return 1;
+}
+\f
+/* xgdb_dispatch -- Loop, dispatching on window events,
+   until data is available on FP (which is normally stdin).
+   Then return, so the data on FP can be processed.  */
+
+void
+xgdb_dispatch (fp)
+     FILE *fp;
+{
+  int inmask = 1 << fileno (fp);
+  int xmask = 1 << ConnectionNumber (screen_display);
+  int rfds = 0;
+  int nfds;
+  XEvent ev;
+  int pend;
+  
+  while (! (rfds & inmask))
+    {
+      pend = XPending ();
+      if (!pend)
+       {
+         rfds = inmask | xmask;
+         /* this isn't right for 4.3 but it works 'cuz of 4.2 compatibility */
+         nfds = select (32, &rfds, 0, 0, (struct timeval *) 0);
+       }
+      if (pend || rfds & xmask)
+       {
+         XNextEvent (screen_display, &ev);
+         XtDispatchEvent (&ev);
+       }
+    }
+}  
+\f
+/* If we use an X window, the GDB command loop is told to call this function
+   before reading a command from stdin.
+   PROMPT is saved for later use so buttons can print a prompt-string.  */
+
+void
+xgdb_window_hook (infile, prompt)
+     FILE *infile;
+     char *prompt;
+{
+  prompt_string = prompt;
+  xgdb_display_source ();
+  xgdb_dispatch (infile);
+}
+
+static
+initialize ()
+{
+  extern void (*window_hook) ();
+  extern int inhibit_windows;
+
+  if (getenv ("DISPLAY") && ! inhibit_windows)
+    if (xgdb_create_window ())
+      window_hook = xgdb_window_hook;
+
+  specify_exec_file_hook (xgdb_display_exec_file);
+}
+
+END_FILE
This page took 0.513514 seconds and 4 git commands to generate.