--- /dev/null
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 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);
+}
+
--- /dev/null
+===================================================================
+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
+
--- /dev/null
+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, ®isters[regbyte], len);
+ if (have_inferior_p ())
+ store_inferior_registers (0);
+
+should be:
+
+ bcopy (myaddr, ®isters[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
+
--- /dev/null
+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
--- /dev/null
+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-
+
+
+
--- /dev/null
+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 ()
+ {
+
--- /dev/null
+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
--- /dev/null
+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.
+
--- /dev/null
+
+ 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.
--- /dev/null
+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:
--- /dev/null
+# -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
--- /dev/null
+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
+@
--- /dev/null
+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
--- /dev/null
+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 *)®isters[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps;
+ *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc;
+ bcopy (corestr.c_fpstatus.fps_regs,
+ ®isters[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof corestr.c_fpstatus.fps_regs);
+ bcopy (&corestr.c_fpstatus.fps_control,
+ ®isters[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
+@
--- /dev/null
+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
+@
--- /dev/null
+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, <c_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, <c_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, <c_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 *)<c_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, ®isters[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.fps_regs);
+ *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+ *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+ bcopy (&inferior_fp_registers.fps_control,
+ ®isters[REGISTER_BYTE (FPC_REGNUM)],
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+store_inferior_registers (regno)
+ int regno;
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+ extern char registers[];
+
+ bcopy (registers, &inferior_registers, 16 * 4);
+ bcopy (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+ sizeof inferior_fp_registers.fps_regs);
+ inferior_registers.r_ps = *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
+ inferior_registers.r_pc = *(int *)®isters[REGISTER_BYTE (PC_REGNUM)];
+ bcopy (®isters[REGISTER_BYTE (FPC_REGNUM)],
+ &inferior_fp_registers.fps_control,
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+
+ ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
+ 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, <c_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
+@
--- /dev/null
+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
+@
--- /dev/null
+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
+@
--- /dev/null
+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");
+@
--- /dev/null
+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
+@
--- /dev/null
+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
+@
--- /dev/null
+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);
+@
--- /dev/null
+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
+@
--- /dev/null
+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
+@
--- /dev/null
+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.
--- /dev/null
+\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
--- /dev/null
+/*
+ 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));
+ }
+}
+
--- /dev/null
+main() {
+ int i;
+
+ for (i = 0; i >= 0; i++)
+ bar();
+}
+
+bar()
+{
+ int i;
+
+ i = 10;
+}
--- /dev/null
+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)
--- /dev/null
+ .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
--- /dev/null
+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,
+
+
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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 */
+
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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 ();
--- /dev/null
+/* 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 *)®isters[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps;
+ *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc;
+ bcopy (corestr.c_fpstatus.fps_regs,
+ ®isters[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof corestr.c_fpstatus.fps_regs);
+ bcopy (&corestr.c_fpstatus.fps_control,
+ ®isters[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
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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 ();
--- /dev/null
+/* 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;
+ }
+}
--- /dev/null
+
+/* 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 ();
--- /dev/null
+/* 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
--- /dev/null
+/* 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, ")");
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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 ();
--- /dev/null
+/* 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 (®isters[regbyte], myaddr, len);
+}
+
+/* Copy LEN bytes of consecutive data from memory at MYADDR
+ into registers starting with the REGBYTE'th byte of register data. */
+
+write_register_bytes (regbyte, myaddr, len)
+ int regbyte;
+ char *myaddr;
+ int len;
+{
+ bcopy (myaddr, ®isters[regbyte], len);
+ if (have_inferior_p ())
+ store_inferior_registers (-1);
+}
+
+/* Return the contents of register REGNO,
+ regarding it as an integer. */
+
+CORE_ADDR
+read_register (regno)
+ int regno;
+{
+ /* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
+ return *(int *) ®isters[REGISTER_BYTE (regno)];
+}
+
+/* Store VALUE in the register number REGNO, regarded as an integer. */
+
+void
+write_register (regno, val)
+ int regno, val;
+{
+ /* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
+ *(int *) ®isters[REGISTER_BYTE (regno)] = val;
+
+ if (have_inferior_p ())
+ store_inferior_registers (regno);
+}
+
+/* Record that register REGNO contains VAL.
+ This is used when the value is obtained from the inferior or core dump,
+ so there is no need to store the value there. */
+
+void
+supply_register (regno, val)
+ int regno;
+ char *val;
+{
+ bcopy (val, ®isters[REGISTER_BYTE (regno)], REGISTER_RAW_SIZE (regno));
+}
+\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
--- /dev/null
+/* 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
--- /dev/null
+main() {
+ int i;
+
+ for (i = 0; i >= 0; i++)
+ bar();
+}
+
+bar()
+{
+ int i;
+
+ i = 10;
+}
--- /dev/null
+
+
+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| | | |
--- /dev/null
+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
--- /dev/null
+ 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
--- /dev/null
+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)
+
+
--- /dev/null
+/* 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 ();
--- /dev/null
+.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.
+
--- /dev/null
+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
--- /dev/null
+/* 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
--- /dev/null
+/* 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;
--- /dev/null
+/* 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, <c_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, <c_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, <c_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 *)<c_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, ®isters[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.fps_regs);
+ *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+ *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+ bcopy (&inferior_fp_registers.fps_control,
+ ®isters[REGISTER_BYTE (FPC_REGNUM)],
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+store_inferior_registers (regno)
+ int regno;
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+ extern char registers[];
+
+ bcopy (registers, &inferior_registers, 16 * 4);
+ bcopy (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+ sizeof inferior_fp_registers.fps_regs);
+ inferior_registers.r_ps = *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
+ inferior_registers.r_pc = *(int *)®isters[REGISTER_BYTE (PC_REGNUM)];
+ bcopy (®isters[REGISTER_BYTE (FPC_REGNUM)],
+ &inferior_fp_registers.fps_control,
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+
+ ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
+ 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, <c_ours);
+ ioctl (0, TIOCLGET, &lmode_ours);
+#endif
+ fcntl (0, F_GETFL, tflags_ours);
+ ioctl (0, TIOCGPGRP, &pgrp_ours);
+
+ terminal_is_ours = 1;
+}
+
+END_FILE
--- /dev/null
+/* 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
--- /dev/null
+/* 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); }
--- /dev/null
+#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);
+}
--- /dev/null
+/* 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 ()
+{
+}
--- /dev/null
+/*
+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"); }
--- /dev/null
+/* 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"); }
--- /dev/null
+
+/* 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)
--- /dev/null
+/* 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
--- /dev/null
+/* 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
+
--- /dev/null
+/* 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)
--- /dev/null
+/* 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"); }
--- /dev/null
+/* 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"); }
--- /dev/null
+
+/* This is how the size of an individual .o file's text segment
+ is rounded on a sun. */
+
+#define FILEADDR_ROUND(addr) (addr)
--- /dev/null
+/* 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; \
+}
--- /dev/null
+/* 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"); }
--- /dev/null
+
+/* 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)
--- /dev/null
+/* 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]);;
--- /dev/null
+/* 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
+}
--- /dev/null
+/* 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.");
+}
--- /dev/null
+/* 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
--- /dev/null
+/* 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 */
+}
--- /dev/null
+../gcc/gcc-1.22/obstack.c
\ No newline at end of file
--- /dev/null
+../gcc/gcc-1.19/obstack.h
\ No newline at end of file
--- /dev/null
+#include "m-mac-aux.h"
--- /dev/null
+#include "m68k-pinsn.c"
--- /dev/null
+/* 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
--- /dev/null
+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 :-)
+
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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
--- /dev/null
+/* 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;
+};
--- /dev/null
+/* 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
--- /dev/null
+/* 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 ();
--- /dev/null
+#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));
+}
--- /dev/null
+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;
+ }
+}
--- /dev/null
+main ()
+{
+ int x = 0;
+
+ while (1)
+ {
+ sleep (1);
+ x++;
+ }
+}
--- /dev/null
+struct foo
+{
+ int a : 5, : 4, b : 5;
+ char c;
+ int : 3, d : 8, : 0, e : 5;
+};
+
+struct foo x;
+
+main ()
+{
+ printf (x);
+}
--- /dev/null
+struct foo
+{
+ unsigned bar : 1;
+ unsigned lose : 1;
+};
+
+main ()
+{
+ struct foo *win;
+
+ printf ("%d, %d\n", win->bar, win->lose);
+}
--- /dev/null
+/* 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. */
+}
+
--- /dev/null
+
+main ()
+{
+ foo(2);
+ foo(3);
+}
+
+foo (i)
+{
+ printf ("i is %d, ", i);
+ printf ("i*i is %d\n", i * i);
+}
--- /dev/null
+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;
+}
--- /dev/null
+
+ main()
+ {
+ printf("foo\n");
+ }
--- /dev/null
+main ()
+{
+ foo (4);
+}
+
+foo (x)
+ int x;
+{
+ if (x > 0)
+ foo (x - 1);
+}
+
--- /dev/null
+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;
+}
--- /dev/null
+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);
+}
--- /dev/null
+main ()
+{
+ register int ntabs;
+ register short x;
+ short stops[30];
+
+ foo ();
+}
+
+foo ()
+{
+ register int ntabs;
+ register short x;
+
+ printf (x, ntabs);
+}
--- /dev/null
+# 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);
+}
--- /dev/null
+/* 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);
+ }
+}
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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 ();
--- /dev/null
+/* 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
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* Define the current version number of GDB. */
+
+char *version = "2.4+";
--- /dev/null
+
+/* 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
--- /dev/null
+/* 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