macsbug.gdb   [plain text]


#################################################################################
#                                                                               #
#                                .gdbinit-MacsBug                               #
#                                                                               #                                                                               #
#                      Macsbug-syle gdb command definitions                     #
#                                                                               #
#                                 Ira L. Ruben                                  #
#                      Copyright Apple Computer, Inc. 2000                      #
#                                                                               #
#################################################################################

# This file can be either sourced'ed in by .gdbinit or explicitly to define a set
# of gdb commands that simulate a subset of MacsBug commands.  It is as faithful
# a simulation as possible within the limits of the gdb command language.  There
# may also be an extension or two where it makes sense in the context of the
# debugging paradigm imposed by gdb.

# See MACSBUG_HELP below (or execute it) for summary documentation of the 
# supported MacsBug commands.  See individual help documentation for more
# details and any MacsBug restrictions imposed on the commands.

# NOTE: The expression syntax used in these functions is written using C
#       syntax so this script is only applicable for debugging C/C++.  If
#       you are trying to debug any other language, you're probably 
#	screwed!

# The author has endeavored to produce as complete a set of MacsBug commands as
# feasible within the restrictions imposed by the rather limited gdb command
# language.  But others may have additional ideas.  So contributions and
# embellishments are welcome, particularly to the types supported by the DM
# command.  The only restrictions are that to be placed in this particular
# universe of commands (i.e., this file), they must be variants of *EXISTING*
# MacsBug commands.  Any other "flavors" do not belong here.

# Revision history
#
#	 1-Sep-2000	ILR	Initial creation.
#	 2-Sep-2000	ILR	Added basic type support to DM.
#				Fixed DB and DW decimal display bug.
#				Changed __print_char to bold octals and handle more
#				  known escape letters.
#				Fixed argument handling to not cause possible
#				  reevaluation of their values in private 
#				  functions.
#				Prefixed all "local" internal function variables
#				  with double underbars to minimize potential
#				  name conflicts with their callers. Damn gdb!
#				More tutorial info in MACSBUG_HELP.
#	 3-Sep-2000	ILR	Added ES, FIND, FB, FW, FL, and FILL commands.
#				Allow SB, SW, SL, SM to have string values using
#				  the same machinery created for FIND and FILL.
#	 4-Sept-2000	ILR	Fixed size checking in SM and set.
#				Add __lower_case function.
#				Set $dot in DM for addr n case and let DM call
#				  __lower_case instead of doing it in DM command.
#				Added GT, DMA, BRM, DX, MSET, and Rn commands.
#				Enhanced DMA and __hexdump to check for repeated
#				  lines under the MSET DITTO state switch.
#				Polished everything up for initial "release",
#				  whatever that means.
#	 5-Sept-2000	ILR	Added PC command.
#				Made memory and disassembly displays contiguous
#				  when possible (i.e., removed the gdb prompt).
#	 9-Sept-2000	ILR	Changed MacsBug S to SI since it's a superset of
#				  gdb's S but essentially the same action.  This
#				  free's up S to be gdb's S which executes single
#				  statements including stepping into called functions.
#				  I prefer to back the MacsBug compatibilty with S
#				  to preserve gdb's S.
#				Changed T command to call SO to emphasize their
#				   same-ness and to have the actual code in one
#				   place just like I do for other aliased commands.
#	12-Sept-2000	ILR	Added 2nd argument to T, SO and SI to disassemble m
#				  lines (default 4) instead of just 1.
#				Removed a debugging printf from IP that I forgot
#				  to previously remove when I was debugging it.
#				T was not missing in the MACSBUG_HELP display.
#				ID's "Disassembly from" format string was missing
#				  a '%' causing a gdb error report.
#	25-Sept-2000	ILR	Added __branch_taken to determine if a conditional
#				  branch at $pc will be taken or not.
#				Added routines to display the registers in various
#				  ways along with disassembly.  Only added, it's
#				  work in progress, and not yet hooked in.
#	 9-Oct-2000	ILR	Call __display_registers_h from __disasmN so that
#				  all disassemblies cause a register display at a
#				  fixed place at the top to the screen.  This is
#				  brain dead version, i.e., no split screen scrolling.
#	 			SM of log values was missing 3rd byte.
#	10-Oct-2000	ILR	MSET UNMANGLE used as toggle was not setting gdb.
#	13-Oct-2000	ILR	Fix DM so that repeated DM commands even with
#				  arguments (i.e., just hitting return to repeat the
#				  DM) causes a contiguous hexdump display.
#				Similar fix for DMA.

###################################################################################
###################################################################################

# Current highest command identifier value for $__lastcmd__ is 41

# In each command assign $__lastcmd__ to a unique command number for each new
# command where applicable and update the above comment to make it easier to
# remember what to assign to future commands.

# $__lastcmd__ is not just "noise".  Some MacsBug simulated commands need to
# know what the previous command was to perform the required MacsBug semantics. 

###################################################################################
###################################################################################
#
# MACSBUG_HELP - List of supported commands.
#
define MACSBUG_HELP
    #       12345678901234567890123456789012345678901234567890123456789012345678901234567890
    printf "\n"
    printf "BRC [addr]                  Clear all breakpoints or one breakpoint at addr\n"
    printf "BRD                         Show all breakpoints (or breakpoint n)\n"
    printf "BRM regex                   Set breakpoints at all functs matching regular expr\n"
    printf "BRP [gdb-spec [expr]]       Break at gdb-spec (under specified condition)\n"
    printf "DB addr                     Display in hex the byte at addr (or pc)\n"
    printf "DL [addr]                   Display in hex the 4 bytes at addr (or pc)\n"
    printf "DM [addr [n | basic type]]  Display memory from addr for n bytes or as a basic type\n"
    printf "DMA [addr [n]]              Display memory as ASCII from addr for n (default 512) bytes\n"
    printf "DP [addr]                   Display 128 bytes at addr (or pc)\n"
    printf "DW [addr]                   Display in hex the two bytes at addr (or pc)\n"
    printf "DX [ON|OFF|NOW|SHOW]        Temporarily enable/disable/toggle breakpoints\n"
    printf "ES                          Exit to shell (unconditionally quit gdb)\n"
    printf "FB addr n expr|\"string\"     Search from addr to addr+n-1 for the byte\n"
    printf "FILL addr n expr|\"string\"   Fill from addr to addr+n with expr or string\n"
    printf "FL addr n expr|\"string\"     Search from addr to addr+n-1 for the 4-byte long\n"
    printf "FIND addr n expr            Search from addr to addr+n-1 for the pattern\n"
    printf "FW addr n expr|\"string\"     Search from addr to addr+n-1 for the 2-byte word\n"
    printf "G [addr]                    Continue execution (at addr if supplied)\n"
    printf "GT gdb-spec                 Go (continue) until the gdb-spec is reached\n"
    printf "ID [addr]                   Disassemble 1 line starting at addr (or pc)\n"
    printf "IDP [addr]                  Same as ID\n"
    printf "IL [addr [n]]               Disassemble n (default 20) lines from the addr or pc\n"
    printf "ILP [addr [n]]              Same as IL\n"
    printf "IP [addr]                   Disassemble 20 lines centered around the addr (or pc)\n"
    printf "MR                          Return from current frame\n"
    printf "MSET opt [ON|OFF|NOW|SHOW]  Temporarially change the specified behavior\n"
    printf "PC                          Display the contents of the PC\n"
    printf "Rn  (n = 0, ... ,31)        Display the contents of register Rn\n"
    printf "SB addr value1 [... value9] Assign up to 9 values to bytes starting at addr\n"
    printf "SC                          Display back trace\n"
    printf "SC6                         Same as SC\n"
    printf "SC7                         Same as SC\n"
    printf "SI [n] [m]                  Step n (or 1) instruction(s), disassmble m lines\n"
    printf "SL addr value1 [... value9] Assign up to 9 values to (4-byte) longs starting at addr\n"
    printf "SM addr value1 [... value9] Assign up to 9 values to memory starting at add\n"
    printf "SO [n] [m]                  Step over n instructions, disassmble m lines\n"
    printf "SW addr value1 [... value9] Assign up to 9 values to (2-byte) words starting at addr\n"
    printf "T [n] [m]                   Same as SO\n"
    printf "TD                          Display integer and machine registers\n"
    printf "TF                          Display the floating point registers\n"
    printf "TV                          Display the vector registers (not yet supported)\n"
    printf "\n"
    printf "The $dot gdb variable is the last address referenced by certain commands.\n"
    printf "For instance, SM sets $dot to the first address that was changed.  The\n"
    printf "default for many commands is to use $dot as their address argument.  Typing\n"
    printf "DM will display the memory just set and set the last command to DM.  A\n"
    printf "return after the parameterless DM command will use the $dot set by it to\n"
    printf "display then next block of memory in sequence.\n\n"
    printf "This isn't quite like MacsBug but its as close an approximation as\n"
    printf "possible in the gdb environment.\n"
    printf "\n"
    printf "Other differences between the gdb MacsBug commands and MacsBug itself:\n"
    printf "\n"
    printf "  1. Only C/C++ can be debugged since the gdb commands use C/C++ syntax\n"
    printf "     for their implementation (restriction imposed by gdb).\n\n"
    printf "  2. Arguments are written using C/C++ syntax (e.g., use -> instead of\n"
    printf "     ^, != instead of <>, etc.).\n"
    printf "\n"
    printf "  3. Only one command per line allowed (gdb restriction).\n"
    printf "\n"
    printf "  4. Return executes previous command (gdb convention).  This works\n"
    printf "     like MacsBug after a parameterless version of the command is entered\n"
    printf "     following a parameterized version (like the SM/DM example mentioned\n"
    printf "     above).\n"
    printf "\n"
    printf "  5. $dot instead of '.'.\n"
    printf "\n"
    printf "  6. Some restrictions on the commands that are supported.  Do help on\n"
    printf "     individual commands for details.\n"
    printf "\n"
    printf "  7. Decimal values are shown without leading '#' and hex is shown with\n"
    printf "     a '0x' prefix.\n"
    printf "\n"
    printf "  8. The input radix is as defined by the gdb 'set input-radix' command.\n"
    printf "     The default is decimal unlike MacsBug which is hex.  Use the gdb\n"
    printf "     command 'show input-radix' do verify the input radix.\n"
    printf "\n"
    printf "  9. Most of the MacsBug commands will cause gdb error reports until there\n"
    printf "     is a thread to debug (sometimes the error messages are rather cryptic).\n"
    printf "     So unlike MacsBug where you can issue commands as soon as you enter\n"
    printf "     MacsBug, you will need to start a debugging thread before issuing many\n"
    printf "     of the gdb MacsBug commands.\n"
    printf "\n"
    printf " 10. MSET is a subset of the macsBug SET command (gdb SET already exists).\n"
    printf "\n"
    printf " 11. SI is defined as the MacsBug S command (gdb S already exists).\n"
    printf "\n"
end
document MACSBUG_HELP
MACSBUG_HELP <------- Summarize just the MacsBug commands -------
end

#printf "Type MACSBUG_HELP for help on the MacsBug commands.\n"

###################################################################################
###################################################################################
#
# BRC [addr]
#
define BRC
    if ($argc == 0)
	delete
    else
	clear $arg0
    end
    
    set $__lastcmd__ = 1
end
document BRC
BRC [addr] -- Clear all breakpoints or one breakpoint at addr.
See also gdb's DELETE command (clears breakpoints by number), and DISABLE.
end

###################################################################################
#
# BRD [n]
#
define BRD
    if ($argc == 0)
    	info breakpoints
    else
    	info breakpoints $arg0
    end
    
    set $__lastcmd__ = 2
end
document BRD
BRD -- Show all breakpoints (or breakpoint n).
end

###################################################################################
#
# BRM regex
#
define BRM
    if ($argc == 0)
    	printf "usage: BRM regex (regex expected)\n"
    else
    	if ($argc == 1)
    	    rbreak $arg0
    	else
    	    if ($argc == 2)
    	    	rbreak $arg0 $arg1
    	    else
    	    	if ($argc == 3)
    	    	    rbreak $arg0 $arg1 $arg2
    	    	else
    	    	    if ($argc == 4)
    	    	    	rbreak $arg0 $arg1 $arg2 $arg3
    	    	    else
    	    	    	if ($argc == 5)
    	    	    	    rbreak $arg0 $arg1 $arg2 $arg3 $arg4
    	    	    	else
    	    	    	    if ($argc == 6)
   	    	    	    	rbreak $arg0 $arg1 $arg2 $arg3 $arg4 $arg5
    	    	    	    else
    	    	    	    	if ($argc == 7)
    	    	    	    	    rbreak $arg0 $arg1 $arg2 $arg3 $arg4 $arg5 $arg6
    	    	    	    	else
    	    	    	    	    if ($argc == 8)
    	    	    	    	    	rbreak $arg0 $arg1 $arg2 $arg3 $arg4 $arg5 $arg6 $arg7
    	    	    	    	    else
    	    	    	    	    	if ($argc == 9)
    	    	    	    	    	    rbreak $arg0 $arg1 $arg2 $arg3 $arg4 $arg5 $arg6 $arg7 $arg8
    	    	    	    	    	else
    	    	    	    	    	    # gdb will report error if > 10 args
    	    	    	    	    	    rbreak $arg0 $arg1 $arg2 $arg3 $arg4 $arg5 $arg6 $arg7 $arg8 $arg9
    	    	    	    	    	end
    	    	    	    	    end
    	    	    	    	end
    	    	    	    end
    	    	    	end
    	    	    end
    	    	end
    	    end
    	end
    end
    
    set $__lastcmd__ = 38
end
document BRM
BRM regex -- Set breakpoints at all functions matching regular expression.
This sets unconditional breakpoins on all matches, printing a list of all
breakpoints set.
Κ
Note, due to gdb function limitations there can be no more than 10 "words"
in the BRM regular expression, where a word is a sequence of non-blanks
characters.
end

###################################################################################
#
# BRP [gdb-spec [expr]]
#
define BRP
    if ($argc == 0)
    	br
    else
    	if ($argc == 1)
    	    br $arg0
    	else
    	    if ($argc == 2)
    	    	br $arg0 if $arg1
    	    else
    	    	if ($argc == 3)
    	    	    br $arg0 if $arg1 $arg2
    	    	else
    	    	    if ($argc == 4)
    	    	    	br $arg0 if $arg1 $arg2 $arg3
    	    	    else
    	    	    	if ($argc == 5)
    	    	    	    br $arg0 if $arg1 $arg2 $arg3 $arg4
    	    	    	else
    	    	    	    if ($argc == 6)
   	    	    	    	br $arg0 if $arg1 $arg2 $arg3 $arg4 $arg5
    	    	    	    else
    	    	    	    	if ($argc == 7)
    	    	    	    	    br $arg0 if $arg1 $arg2 $arg3 $arg4 $arg5 $arg6
    	    	    	    	else
    	    	    	    	    if ($argc == 8)
    	    	    	    	    	br $arg0 if $arg1 $arg2 $arg3 $arg4 $arg5 $arg6 $arg7
    	    	    	    	    else
    	    	    	    	    	if ($argc == 9)
    	    	    	    	    	    br $arg0 if $arg1 $arg2 $arg3 $arg4 $arg5 $arg6 $arg7 $arg8
    	    	    	    	    	else
    	    	    	    	    	    # gdb will report error if > 10 args
    	    	    	    	    	    br $arg0 if $arg1 $arg2 $arg3 $arg4 $arg5 $arg6 $arg7 $arg8 $arg9
    	    	    	    	    	end
    	    	    	    	    end
    	    	    	    	end
    	    	    	    end
    	    	    	end
    	    	    end
    	    	end
    	    end
    	end
    end
    
    set $__lastcmd__ = 33
end
document BRP
BRP [gdb-spec [expr]] -- Break at gdb-spec (under specified condition).
This implements the gdb "BREAK gdb-spec [if condition]".  See gdb BREAK
documentation for further details.
Κ
Note, due to gdb function limitations there can be no more than 8 "words"
in the BRP condition expr, where a word is a sequence of non-blanks
characters.
Κ
Macsbug features not supported: Interation count.
Κ                               No semicolon before the command.
Κ                               Command is not enclosed in quotes.
Κ                               Only a single command is allowed.
Κ
Anything more complicated then you should probably use the COMMANDS
syntax in gdb.
end

###################################################################################
#
# DB [addr]
#
define DB
    if ($argc == 0)
    	if ($__lastcmd__ == 3)
    	    set $dot = (unsigned char *)$dot + 1
     	    # The following makes the displays contiguous by moving the cursor
    	    # up over the gdb prompt.  But just in case the display would fail
    	    # because the memory is inaccessible we try to access the first
    	    # byte of the display and let gdb error it out before moving the
    	    # cursor if the memory is inaccessible.
    	    set $accessible = *(char *)$dot
    	    printf "%c[2A\n", 0x1B
    	end
    else
    	set $dot = $arg0
    end
        
    set $value = *(unsigned char *)$dot
    
    printf "Byte at %.8X = 0x%.2X   %u    %d    ", $dot, $value, $value, (char)$value
    __print_1 $value
    printf "\n"
    
    set $__lastcmd__ = 3
end
document DB
DB addr -- Display in hex the byte at addr (or pc).
end

###################################################################################
#
# DL [addr]
#
define DL
    if ($argc == 0)
    	if ($__lastcmd__ == 4)
    	    set $dot = (unsigned char *)$dot + 4
     	    # The following makes the displays contiguous by moving the cursor
    	    # up over the gdb prompt.  But just in case the display would fail
    	    # because the memory is inaccessible we try to access the first
    	    # byte of the display and let gdb error it out before moving the
    	    # cursor if the memory is inaccessible.
    	    set $accessible = *(char *)$dot
    	    printf "%c[2A\n", 0x1B
    	end
    else
    	set $dot = $arg0
    end
    
    set $addr  = $dot
    
    set $value = *(unsigned char *)$addr
    set $addr  = (unsigned char *)$addr + 1
    
    set $value = ((unsigned long)$value << 8) | *(unsigned char *)$addr
    set $addr  = (unsigned char *)$addr + 1
    
    set $value = ((unsigned long)$value << 8) | *(unsigned char *)$addr
    set $addr  = (unsigned char *)$addr + 1

    set $value = ((unsigned long)$value << 8) | *(unsigned char *)$addr

    printf "Four bytes at %.8X = 0x%.8X   %u    %d    ", $dot, $value, $value, $value
    __print_4 $value
    printf "\n"
    
    set $__lastcmd__ = 4
end
document DL
DL [addr] -- Display in hex the 4 bytes at addr (or pc).
end

# This is written assuming no alignment requiremnts.  However, most machines
# actuall allow unaligned access.   We could actually get away with set
# $value = *(unsigned long *)$addr.  But I'll leave it the way it is since
# that way never has alignement concerns.

###################################################################################
#
# DM [addr [n | basic type]]
#
define DM
    if ($argc == 0)
    	if ($__lastcmd__ == 5)
	    set $dot = (unsigned char *)$dot + $__prev_dm_n__
     	    # The following makes the displays contiguous by moving the cursor
    	    # up over the gdb prompt.  But just in case the display would fail
    	    # because the memory is inaccessible we try to access the first
    	    # byte of the display and let gdb error it out before moving the
    	    # cursor if the memory is inaccessible.
    	    set $accessible = *(char *)$dot
    	    printf "%c[2A\n", 0x1B
    	else
	    printf "Displaying memory from %.8X\n", $dot
	end
	set $__prev_dm_n__ = 16
	__hexdump $dot
	set $__next_addr__ = (unsigned char *)$dot + 16
	set $__lastcmd__ = 5
    else
	if ($argc == 1)
	    if (0 && $__lastcmd__ == 5 && $__next_addr__ == (unsigned char *)$dot + $__prev_dm_n__)
	    	set $dot = (unsigned char *)$dot + $__prev_dm_n__
	    	set $accessible = *(char *)$dot
	    	printf "%c[2A\n", 0x1B
	    else
	    	set $dot = (unsigned char *)$arg0
	    	printf "Displaying memory from %.8X\n", $dot
	    end
	    set $__prev_dm_n__ = 16
	    __hexdump $dot
	    set $__next_addr__ = (unsigned char *)$dot + 16
	    set $__lastcmd__ = 5
	else
	    set $addr0 = (unsigned char *)$arg0
	    set $n     = (char *)"$arg1"
	    if ($n[0] >= '0' && $n[0] <= '9')
	    	if (0 && $__lastcmd__ == 5 && $__next_addr__ == (unsigned char *)$dot + $__prev_dm_n__)
	    	    set $addr0 = (unsigned char *)$dot + $__prev_dm_n__
	    	    set $accessible = *(char *)$dot
	    	    printf "%c[2A\n", 0x1B
	    	else
	    	    printf "Displaying memory from %.8X\n", $dot
	    	end
	    	set $dot           = $addr0
	    	set $__prev_dm_n__ = $arg1
	    	__hexdump $dot $__prev_dm_n__
	    	set $__next_addr__ = (unsigned char *)$dot + $__prev_dm_n__
	    	set $__lastcmd__ = 5
	    else
	    	# Basic types displays have no effect on $dot and invalidate the
	    	# previous command ($__lastcmd__) state for all other commands forcing
	    	# them to use the current $dot value as their default.
	    	
	    	set $__lastcmd__ = -5
	    	
	    	# Handle the types specified by MacsBug (or at least trhy to where we can).
	    	
	    	# The types are: Byte, Word, Long, SignedByte, SignedWord, SignedLong,
	    	#                UnsignedByte, UnsignedWord, UnsignedLong, PString,
	    	#                CString, Boolean, Text, Pointer, Handle, IORefNum,
		#		 VRefNum, Seconds, ATrapWord, Binary8, Binary16, Binary32,
		#		 OSType, AbsTicks, TickInterval, RgnHandle, IOTrapWord,
		#		 Version, RGBColor, Fixed, ShortFixed, UnsignedFixed,
		#		 Fract, Rect, and Region.  Who knows what else?  These,
		#		 (actually except for Region) are the only ones
		#		 documented in MacsBug help command.
	    	
		# Because of gdb's brain-dead command language this leads to the mother
		# of all nested if statements!  To avoid overly indenting this turkey and
		# to at least give the taste of a switch statement each "case" is not
		# indented.  Of course this means all the 'end's for the if's pile up at
		# the end of this "switch".  And NO, gdb won't let me comment them either
		# to indicate which 'end' goes with which 'if'.  Trust me, I tried.  I
		# also tried "else if".  Like I said, gdb's command language is brain
		# dead :-(
		
		__lower_case $arg1
		
		set $unsupported = 0
		
		__strcmp $lower_case "byte"
		if ($strcmp)
		    printf "Displaying Byte\n"
		    printf " %.8X: %.2X\n", $addr0, *(unsigned char *)$addr0 & 0xFF
		else
		__strcmp $lower_case "word"
		if ($strcmp)
		    printf "Displaying Word\n"
		    printf " %.8X: %.4X\n", $addr0, *(unsigned short *)$addr0 & 0xFFFF
		else
		__strcmp $lower_case "long"
		if ($strcmp)
		    printf "Displaying Long\n"
		    printf " %.8X: %.8X\n", $addr0, *(unsigned long *)$addr0
		else
		__strcmp $lower_case "signedbyte"
		if ($strcmp)
		    printf "Displaying SignedByte\n"
		    printf " %.8X: %d\n", $addr0, *(char *)$addr0
		else
		__strcmp $lower_case "signedword"
		if ($strcmp)
		    printf "Displaying SignedWord\n"
		    printf " %.8X: %d\n", $addr0, *(short *)$addr0
		else
		__strcmp $lower_case "signedlong"
		if ($strcmp)
		    printf "Displaying SignedLong\n"
		    printf " %.8X: %d\n", $addr0, *(long *)$addr0
		else
		__strcmp $lower_case "unsignedbyte"
		if ($strcmp)
		    printf "Displaying UnsignedByte\n"
		    printf " %.8X: %u\n", $addr0, *(unsigned char *)$addr0
		else
		__strcmp $lower_case "unsignedword"
		if ($strcmp)
		    printf "Displaying UnsignedWord\n"
		    printf " %.8X: %u\n", $addr0, *(unsigned short *)$addr0
		else
		__strcmp $lower_case "unsignedlong"
		if ($strcmp)
		    printf "Displaying UnsignedLong\n"
		    printf " %.8X: %u\n", $addr0, *(unsigned long *)$addr0
		else
		__strcmp $lower_case "pstring"
		if ($strcmp)
		    printf "Displaying PString\n"
		    set $len = *((unsigned char *)$addr0)++
		    printf " %.8X: (%d) \"", $addr0, $len
		    while ($len--)
			set $c = *((unsigned char *)$addr0)++
			__print_char $c 1
		    end
		    printf "\"\n"
		else
		__strcmp $lower_case "cstring"
		if ($strcmp)
		    printf "Displaying CString\n"
		    printf " %.8X: \"",  $addr0
		    set $c = *((unsigned char *)$addr0)++
		    while ($c)
			__print_char $c 1
			set $c = *((unsigned char *)$addr0)++
		    end
		    printf "\"\n"
		else
		__strcmp $lower_case "boolean"
		if ($strcmp)
		    printf "Displaying Boolean\n"
		    if (*(unsigned char *)$addr0)
			printf " %.8X: true\n", $addr0
		    else
			printf " %.8X: false\n", $addr0
		    end
		else
		__strcmp $lower_case "binary8"
		if ($strcmp)
		    printf "Displaying Binary8\n"
		    set $value = *(unsigned char *)$addr0
		    printf " %.8X: %.2X = ", $addr0, $value & 0xFF
		    __binary ($value>>4&15) 4
		    printf " "
		    __binary ($value&15) 4
		    printf "\n"
		else
		__strcmp $lower_case "binary16"
		if ($strcmp)
		    printf "Displaying Binary16\n"
		    set $value = *(unsigned short *)$addr0
		    printf " %.8X: %.4X = ", $addr0, $value & 0xFFFF
		    __binary ($value>>12&15) 4
		    printf " "
		    __binary ($value>>8&15) 4
		    printf " "
		    __binary ($value>>4&15) 4
		    printf " "
		    __binary ($value&15) 4
		    printf "\n"
		else
		__strcmp $lower_case "binary32"
		if ($strcmp)
		    printf "Displaying Binary32\n"
		    set $value = *(unsigned long *)$addr0
		    printf " %.8X: %.8X = ", $addr0, $value
		    __binary ($value>>28&15) 4
		    printf " "
		    __binary ($value>>24&15) 4
		    printf " "
		    __binary ($value>>20&15) 4
		    printf " "
		    __binary ($value>>16&15) 4
		    printf " "
		    __binary ($value>>12&15) 4
		    printf " "
		    __binary ($value>>8&15) 4
		    printf " "
		    __binary ($value>>4&15) 4
		    printf " "
		    __binary ($value&15) 4
		    printf "\n"
		else
		__strcmp $lower_case "ostype"
		if ($strcmp)
		    printf "Displaying OSType\n"
		    set $value = *(unsigned long *)$addr0
		    printf " %.8X: %.8X = ", $addr0, $value
		    __print_4 $value
		    printf "\n"
		else
		__strcmp $lower_case "rect"
		if ($strcmp)
		     printf "Displaying Rect\n"
		     set $addr   = $addr0
		     set $top    = *((unsigned short *)$addr)++
		     set $left   = *((unsigned short *)$addr)++
		     set $bottom = *((unsigned short *)$addr)++
		     set $right  = *((unsigned short *)$addr)
		     printf " %.8X: %d %d %d %d (t,l,b,r) %d %d (w,h)\n", $addr0, \
			      $top, $left, $bottom, $right, $right-$left, $bottom-$top
		else
		__strcmp $lower_case "pointer"
		if ($strcmp)
		    set $unsupported = "Pointer"
		else
		__strcmp $lower_case "handle"
		if ($strcmp)
		    set $unsupported = "Handle"
		else
		__strcmp $lower_case "region"
		if ($strcmp)
		    set $unsupported = "Region"
		else
		__strcmp $lower_case "rgnhandle"
		if ($strcmp)
		    set $unsupported = "RgnHandle"
		else
		__strcmp $lower_case "fixed"
		if ($strcmp)
		    set $unsupported = "Fixed"
		else
		__strcmp $lower_case "shortfixed"
		if ($strcmp)
		    set $unsupported = "ShortFixed"
		else
		__strcmp $lower_case "unsignedfixed"
		if ($strcmp)
		    set $unsupported = "UnsignedFixed"
		else
		__strcmp $lower_case "fract"
		if ($strcmp)
		    set $unsupported = "Fract"
		else
		__strcmp $lower_case "rgbcolor"
		if ($strcmp)
		    set $unsupported = "RGBColor"
		else
		__strcmp $lower_case "text"
		if ($strcmp)
		    set $unsupported = "Text"
		else
		__strcmp $lower_case "iorefnum"
		if ($strcmp)
		    set $unsupported = "IORefNum"
		else
		__strcmp $lower_case "vrefnum"
		if ($strcmp)
		    set $unsupported = "VRefNum"
		else
		__strcmp $lower_case "seconds"
		if ($strcmp)
		    set $unsupported = "Seconds"
		else
		__strcmp $lower_case "atrapword"
		if ($strcmp)
		    set $unsupported = "ATrapWord"
		else
		__strcmp $lower_case "absticks"
		if ($strcmp)
		    set $unsupported = "AbsTicks"
		else
		__strcmp $lower_case "tickinterval"
		if ($strcmp)
		    set $unsupported = "TickInterval"
		else
		__strcmp $lower_case "iotrapword"
		if ($strcmp)
		    set $unsupported = "IOTrapWord"
		else
		__strcmp $lower_case "version"
		if ($strcmp)
		    set $unsupported = "Version"
		else
		    printf "Unrecognized type.\n"
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		end
		
		if ($unsupported)
		    printf "%s is not supported in the gdb MacsBug commands.\n", $unsupported
		    printf "Use the gdb PRINT command.  With appropriate type\n"
		    printf "casts you'll probably get better results anyhow.\n"
		end
	    end
	end
    end
end
document DM
DM [addr [n | basic type]] -- Display memory from addr for n bytes or as a basic type.
The basic types are Byte, Word, Long, SignedByte, SignedWord, SignedLong,
UnsignedByte, UnsignedWord, UnsignedLong, PString, CString, Boolean,
Binary8, Binary16, Binary32, OSType, and Rect.
Κ
Also see MSET for DITTO mode.
Κ
Macsbug features not supported: templates and the following basic types.
Κ                               Pointer, Handle, RGBColor, Text, IORefNum,
Κ                               VRefNum, Seconds, ATrapWord, AbsTicks,
Κ                               TickInterval, Region, RgnHandle, IOTrapWord,
Κ                               Version, Fixed, ShortFixed, UnsignedFixed,
Κ                               and Fract.
end

###################################################################################
#
# DMA [addr [n]]
#
define DMA
    if ($argc == 0)
    	if ($__lastcmd__ == 37)
	    set $dot = (unsigned char *)$dot + $__prev_dma_n__
     	    # The following makes the displays contiguous by moving the cursor
    	    # up over the gdb prompt.  But just in case the display would fail
    	    # because the memory is inaccessible we try to access the first
    	    # byte of the display and let gdb error it out before moving the
    	    # cursor if the memory is inaccessible.
    	    set $accessible = *(char *)$dot
    	    printf "%c[2A\n", 0x1B
    	else
    	    printf "Displaying memory from %.8X\n", $dot
	end
	set $__prev_dma_n__ = 512
    else
    	if (0 && $__lastcmd__ == 37 && $__next_addr__ == (unsigned char *)$dot + $__prev_dma_n__)
    	    set $dot = (unsigned char *)$dot + $__prev_dma_n__
    	    set $accessible = *(char *)$dot
    	    printf "%c[2A\n", 0x1B
    	else
    	    set $dot = (unsigned char *)$arg0
    	    printf "Displaying memory from %.8X\n", $dot
    	end
	if ($argc == 1)
	    set $__prev_dma_n__ = 512
	else
	    set $__prev_dma_n__ = $arg1
    	end
    end
    
    set $addr  = $dot
    set $addr1 = (unsigned char *)$addr + $__prev_dma_n__
    
    set $prevaddr = (unsigned char *)$addr
    set $rep_count = 0
    
    while ($addr < $addr1)
   	# Only allow full ditto lines and never the last line
    	if ((unsigned char *)$addr + 64 < $addr1)
    	    __repeated_dump_line $prevaddr $addr 64
    	else
    	    set $repeated = 0
    	end
    	set $prevaddr = (unsigned char *)$addr

     	if ($repeated)
     	    if ($rep_count++ == 0)
     		printf " %.8X: ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''\n", $addr
     	    end
      	    set $addr = (char *)$addr + 64
	else
	    set $rep_count = 0
	    printf " %.8X: ", $addr
	    set $i = 0
	    while ($i++ < 64 && $addr < $addr1)
		set $x = *((unsigned char *)$addr)++
	   	if ($x >= 0x20 && $x <= 0x7F)
	   	    printf "%c", $x
	   	else
	   	    printf "."
	   	end
	    end
	    printf "\n"
	end
    end
    
    set $__next_addr__ = $addr1
    
    set $__lastcmd__ = 37
end
document DMA
DMA [addr [n]] -- Display memory as ASCII from addr for n (default 512) bytes.
ASCII characters outside the range 0x20 to 0x7F are shown as '.'s.
Κ
Also see MSET for DITTO mode.
end

###################################################################################
#
# DP [addr]
#
define DP
    if ($argc == 0)
    	if ($__lastcmd__ == 6)
    	    set $dot = (unsigned char *)$dot + 128
     	    # The following makes the displays contiguous by moving the cursor
    	    # up over the gdb prompt.  But just in case the display would fail
    	    # because the memory is inaccessible we try to access the first
    	    # byte of the display and let gdb error it out before moving the
    	    # cursor if the memory is inaccessible.
    	    set $accessible = *(char *)$dot
    	    printf "%c[2A\n", 0x1B
    	else
    	    printf "Displaying memory from %.8X\n", $dot
    	end
    else
    	set $dot = $arg0
        printf "Displaying memory from %.8X\n", $dot
    end
        
    __hexdump $dot 128
    
    set $__lastcmd__ = 6
end
document DP
DP [addr] -- Display 128 bytes at addr (or pc).
end

###################################################################################
#
# DW [addr]
#
define DW
    if ($argc == 0)
    	if ($__lastcmd__ == 7)
    	    set $dot = (unsigned char *)$dot + 2
     	    # The following makes the displays contiguous by moving the cursor
    	    # up over the gdb prompt.  But just in case the display would fail
    	    # because the memory is inaccessible we try to access the first
    	    # byte of the display and let gdb error it out before moving the
    	    # cursor if the memory is inaccessible.
    	    set $accessible = *(char *)$dot
    	    printf "%c[2A\n", 0x1B
    	end
    else
    	set $dot = $arg0
    end
    
    set $addr = $dot
    
    set $value = *(unsigned char *)$addr
    set $addr  = (unsigned char *)$addr + 1

    set $value = ((unsigned long)$value << 8) | *(unsigned char *)$addr
    
    printf "Two bytes at %.8X = 0x%.4X   %u    %d    ", $dot, $value, $value, (short)$value
    __print_2 $value
    printf "\n"
    
    set $__lastcmd__ = 7
end
document DW
DW [addr] -- Display in hex the two bytes at addr (or pc).
end

# This is written assuming no alignment requiremnts.  However, most machines
# actuall allow unaligned access.   We could actually get away with set
# $value = *(unsigned short *)$addr.  But I'll leave it the way it is since
# that way never has alignement concerns.

###################################################################################
#
# DX [ON | OFF | NOW | SHOW]
#
# Note the "polarity" of the DX state switch is reversed, i.e., 0 means enabled/on,
# 1 means disabled/off.  The reason for this is that if this command could be done
# before the DX state switch is defined (void in gdb, setting it outside the function
# has no effect).  We can only test undefined gdb convenience variables with 'if ($dx)'
# (can't even negate it) which would be false when the switch is undefined, i.e., same
# result as if it were 0.  Our initial default is to be ON, so undefined must also
# mean ON.  Hence the polarity reversal.  #%$@!()& gdb!
#
define DX
    if ($argc == 0)
    	if ($__dx__)
	    set $__dx__ = 0
	    enable breakpoints
	    printf "Breakpoints enabled\n"
	else
	    set $__dx__ = 1
	    disable breakpoints
	    printf "Breakpoints disabled\n"
	end
    else
	__lower_case $arg0
	__strcmp $lower_case "on"
	if ($strcmp)
	    if ($__dx__)
		set $__dx__ = 0
		enable breakpoints
		printf "Breakpoints enabled\n"
	    else
		printf "Breakpoints still enabled\n"
	    end
	else
	    __strcmp $lower_case "off"
	    if ($strcmp)
		if ($__dx__)
		    printf "Breakpoints still disabled\n"
		else
		    set $__dx__ = 1
		    disable breakpoints
		    printf "Breakpoints disabled\n"
		end
	    else
	    	set $e = 1
	    	__strcmp $lower_case "now"
		if ($strcmp)
		    set $e = 0
		else
		    __strcmp $lower_case "show"
		    if ($strcmp)
		    	set $e = 0
		    end
		end
		if ($e || $argc > 1)
		    printf "usage: DX [ON | OFF | NOW | SHOW] (invalid setting)\n"
		else
		    if ($__dx__)
		    	printf "Breakpoints still disabled\n"
		    else
		    	printf "Breakpoints still enabled\n"
		    end
		end
	    end
	end
    end
    
    set $__lastcmd__ = 39
end
document DX
DX [ON | OFF | NOW | SHOW] -- Temporarily enable/disable/toggle breakpoints.
The setting is toggled when there is no argument.
Κ
SHOW is the same as NOW to display the current setting.  It was added
since gdb uses SHOW to show settings.
end

###################################################################################
#
# ES
#
define ES
    set confirm off
    quit
end
document ES
ES -- exit to shell (unconditionally quit gdb).
end

###################################################################################
#
# FB addr n expr|"string"
#
define FB
    FIND $arg0 $arg1 $arg2 1
end
document FB
FB addr n expr|"string" -- Search from addr to addr+n-1 for the byte.
end

###################################################################################
#
# FILL addr n expr|"string"
#
define FILL
    set $addr = $arg0
    set $n    = $arg1
    
    set $dot = $addr
    
    __is_string ($arg2)
    
    if ($string)
    	set $p = (unsigned char *)$string
    	__strlen $string
    	set $b = 0
    	while ($n--)
    	    set *((unsigned char *)$addr)++ = $string[$b]
    	    if (++$b >= $strlen)
    	    	set $b = 0
    	    end
    	end
    else
    	set $value = (long)$arg2
    	if ($value >= -128 && $value <= 255)
    	    while ($n--)
    	    	set *((unsigned char *)$addr)++ = (unsigned char)$value & 0xFF
    	    end
    	else
    	    if ($value >= -32768 && $value <= 65535)
    	    	set $b = 0
    	    	while ($n--)
    	    	    if ($b == 0)
    	    	    	set *((unsigned char *)$addr)++ = ((unsigned short)$value >> 8) & 0xFF
    	    	    	set $b = 1
    	    	    else
    	    	    	set *((unsigned char *)$addr)++ = (unsigned short)$value & 0xFF
    	    	    	set $b = 0
    	    	    end
    	    	end
    	    else
    	    	set $b = 0
    	    	while ($n--)
    	    	    if ($b == 0)
    	    	    	set *((unsigned char *)$addr)++ = ((unsigned long)$value >> 24) & 0xFF
    	    	    	set $b = 1
    	    	    else
    	    	    	if ($b == 1)
    	    	    	    set *((unsigned char *)$addr)++ = ((unsigned long)$value >> 16) & 0xFF
    	    	    	    set $b = 2
    	    	    	else
    	    	    	    if ($b == 2)
    	    	    		set *((unsigned char *)$addr)++ = ((unsigned long)$value >> 8) & 0xFF
    	    	    	    	set $b = 3
    	    	    	    else
    	    	    		set *((unsigned char *)$addr)++ = (unsigned long)$value & 0xFF
    	    	    		set $b = 0
    	    	    	    end
    	    	    	end
		    end
    	    	end
    	    end
    	end
    end
    
    printf "Memory set starting at %.8X\n", $dot
    __hexdump $dot $arg1
    
    set $__lastcmd__ = 34
end
document FILL
FILL addr n expr|"string" -- Fill from addr to addr+n with expr or string.
The fill is repeatedly used as a byte, word, or long (determined by the size
of the expr value) or the string.
end

###################################################################################
#
# FIND addr n expr|"string" [size]
#
# The size is an INTERNAL option to be able to use the general FIND function for
# FB, FW, and FL.
#
define FIND
    set $e = 0
    
    if ($argc > 3)
    	if ($arg3 != 1 && $arg3 != 2 && $arg3 != 4)
    	    printf "usage: FIND addr n expr|"string" (wrong number of arguments)\n"
    	    set $e = 1
    	else
    	    set $size = $arg3
    	end
    else
    	set $size = 0
    end
    
    if (!$e)
	set $addr  = $arg0
	set $addr1 = (unsigned char *)$addr + ($arg1)
	set $found = 0
	
	__is_string ($arg2)
	
	if ($string)
	    set $n = $arg1
	    while (!$found && $addr < $addr1)
		__strncmp $string $addr $n
		if ($strncmp)
		    set $found = $addr
		else
		    set ++((unsigned char *)$addr)
		end
	    end
	else
	    set $value = (long)$arg2
	    if ($size == 1 || ($value >= -128 && $value <= 255))
	    	set $size = 1
	    	set $value = (unsigned char)$value & 0xFF
	    	while (!$found && $addr < $addr1)
		    if (*(unsigned char *)$addr == (unsigned char)$value)
		    	set $found = $addr
		    else
		    	set ++((unsigned char *)$addr)
		    end
		end
	    else
		if ($size == 2 || ($value >= -32768 && $value <= 65535))
		    set $size = 2
		    set $value = (unsigned short)$value & 0xFFFF
		    while (!$found && $addr < $addr1)
		    	if (*(unsigned char *)$addr     == (((unsigned short)$value >> 8) & 0xFF) && \
			    *((unsigned char *)$addr+1) == ((unsigned short)$value & 0xFF))
			    set $found = $addr
			else
			    set ++((unsigned char *)$addr)
			end
		    end
		else
		    set $size = 4
		    while (!$found && $addr < $addr1)
		    	if (*(unsigned char *)$addr     == (((unsigned long)$value >> 24) & 0xFF) && \
			    *((unsigned char *)$addr+1) == (((unsigned long)$value >> 16) & 0xFF) && \
			    *((unsigned char *)$addr+2) == (((unsigned long)$value >>  8) & 0xFF) && \
			    *((unsigned char *)$addr+3) == ((unsigned long)$value & 0xFF))
			    set $found = $addr
			else
			    set ++((unsigned char *)$addr)
			end
		    end
		end
	    end
	end
    end
    
    if (!$e)
    	printf "Searching for "
    	if ($string)
    	    __strlen $string
    	    printf "\""
    	    set $i = 0
    	    while ($strlen--)
    	    	__print_char $string[$i++]
    	    end
    	    printf "\""
    	else
    	    if ($size == 1)
    	    	 printf "%.2X", $value
    	    else
    	    	if ($size == 2)
    	    	    printf "%.4X", $value
    	    	else
    	    	    printf "%.8X", $value
    	    	end
    	    end
    	end
    	printf " from %.8X to %.8X\n", $addr, (char *)$addr1-1
	
    	if (!$found)
	    printf "%c[31m Not found%c[0m\n", 0x1B, 0x1B
	else
	    set $dot = $found
	    __hexdump $dot
	end
    end
    
    set $__lastcmd__ = 35
end
document FIND
FIND addr n expr -- Search from addr to addr+n-1 for the pattern.
If pattern is an expr then the width of the pattern is the smallest
unit (byte, word or long) that contains its value.
Κ
Restriction: The expr value may not have any embedded blanks.  For example
Κ            a value like (unsigned char *)&a is invalid.
Κ
Macsbug features not supported: MacsBug F must be FIND here since F conflicts
Κ                               with the gdb FRAME command abbreviation.
Κ
Κ                               Double quoted "string" instead of single quoted
Κ                               'string'.
Κ
Κ                               To keep the same semantics as MacsBug you run
Κ                               the risk of trying to search beyond the end of
Κ                               your memory since the comparison limit is based
Κ                               on the first byte of the objects to be matched
Κ                               rather than the last.
end

###################################################################################
#
# FL addr n expr|"string"
#
define FL
    FIND $arg0 $arg1 $arg2 4
end
document FL
FL addr n expr|"string" -- Search from addr to addr+n-1 for the 4-byte long.
end

###################################################################################
#
# FW addr n expr|"string"
#
define FW
    FIND $arg0 $arg1 $arg2 2
end
document FW
FW addr n expr|"string" -- Search from addr to addr+n-1 for the 2-byte word.
end

###################################################################################
#
# G [addr]
#
define G
    if ($argc != 0)
	set $pc = $arg0
    end
    
    set $__lastcmd__ = 8
    continue
end
document G
G [addr] -- Continue execution (at addr if supplied)
end

###################################################################################
#
# GT gdb-spec
#
define GT
    tbreak $arg0
    set $__lastcmd__ = 36
    continue
end
document GT
GT gdb-spec -- Go (continue) until the gdb-spec is reached.
This implements the gdb "TBREAK gdb-spec".  See gdb TBREAK
documentation for further details.
Κ
Macsbug features not supported: Command list not allowed
end

###################################################################################
#
# ID [addr]
#
define ID
    if ($argc == 1)
    	set $dot = $arg0
    else
    	if ($__lastcmd__ == 9)
    	    set $dot = (unsigned char *)$dot + 4
     	    # The following makes the displays contiguous by moving the cursor
    	    # up over the gdb prompt.  But just in case the display would fail
    	    # because the memory is inaccessible we try to access the first
    	    # byte of the display and let gdb error it out before moving the
    	    # cursor if the memory is inaccessible.
    	    set $accessible = *(char *)$dot
    	    printf "%c[%dA\n", 0x1B, 2+($branch_taken!=0)
    	else
    	    set $dot = $pc
    	    printf "Disassembly from %.8X\n", $dot
    	end
    end
    __disasmN $dot 1
    
    set $__lastcmd__ = 9
end
document ID
ID [addr] -- Disassemble 1 line starting ar addr (or pc).
Κ
Macsbug features not supported: -c option.
end

###################################################################################
#
# IDP [addr]
#
define IDP
    if ($argc == 1)
    	id $arg0
    else
    	id
    end
    
    #set $__lastcmd__ = $__lastcmd__ 
end
document IDP
IDP [addr] -- Same as ID.
end

###################################################################################
#
# IL [addr [n]]
#
define IL
    if ($argc == 0)
    	if ($__lastcmd__ == 11)
    	    set $dot = (unsigned char *)$dot + (4*20)
     	    # The following makes the displays contiguous by moving the cursor
    	    # up over the gdb prompt.  But just in case the display would fail
    	    # because the memory is inaccessible we try to access the first
    	    # byte of the display and let gdb error it out before moving the
    	    # cursor if the memory is inaccessible.
    	    set $accessible = *(char *)$dot
    	    printf "%c[%dA\n", 0x1B, 2+($branch_taken!=0)
   	else
    	    set $dot = $pc
    	end
    	set $n = 20
    else
    	if ($argc == 1)
    	    set $dot = $arg0
    	    set $n   = 20
    	else
    	    set $dot = $arg0
    	    set $n   = $arg1
    	end
    end
    
    __disasmN $dot $n
    
    set $__lastcmd__ = 11
end
document IL
IL [addr [n]] -- Disassemble n (default 20) lines from the addr or pc.
Κ
Macsbug features not supported: -c option.
end

###################################################################################
#
# ILP [addr [n]]
#
define ILP
    if ($argc == 0)
    	il
    else
    	if ($argc == 1)
    	    il $arg0
    	else
    	    il $arg0 $arg1
    	end
    end
    
    #set $__lastcmd__ = $__lastcmd__ 
end
document ILP
ILP [addr [n]] -- Same as IL.
end

###################################################################################
#
# IP [addr]
#
define IP
    if ($argc == 1)
    	set $dot = $arg0
    else
    	if ($__lastcmd__ == 13)
    	    set $dot = (unsigned char *)$dot + (21*4)
    	    # The following makes the displays contiguous by moving the cursor
    	    # up over the gdb prompt.  But just in case the display would fail
    	    # because the memory is inaccessible we try to access the first
    	    # byte of the display and let gdb error it out before moving the
    	    # cursor if the memory is inaccessible.
    	    set $accessible = *((char *)$dot - 40)
    	    printf "%c[%dA\n", 0x1B, 2+($branch_taken!=0)
    	else
    	    set $dot = $pc
    	end
    end
    
    # __disasmN takes a third argument only used here.  This third argument is
    # $dot so we can specially flag the $dot address in the disassembly to make
    # it more easily identifiable in the display.
    
    __disasmN ($dot-40) 21 $dot
    
    set $__lastcmd__ = 13
end
document IP
IP [addr] -- Disassemble 20 lines centered around the addr (or pc).
Κ
Macsbug features not supported: -c option.
end

###################################################################################
#
# IPP [addr]
#
define IPP
    if ($argc == 1)
    	ip $arg0
    else
    	ip
    end
    
    #set $__lastcmd__ = $__lastcmd__
end
document IPP
IPP [addr] -- Same as IP.
end

###################################################################################
#
# MR
#
define MR
    if ($argc != 0)
    	printf "Only the parameterless form of MR is supported.\n"
    else
	finish
    end
    
    set $__lastcmd__ = 15
end
document MR
MR -- Return from current frame.
Κ
Macsbug features not supported: offset and addr arguments
end

###################################################################################
#
# MSET DITTO | UNMANGLE [ON | OFF | NOW | SHOW]
#
# Note that the initial settings for these state switches is OFF.  I'm mentioning this
# to point out the fact because it is possible that this command could be executed
# BEFORE the switches are defined (void in gdb, setting it outside the function has no
# effect).  We can only test undefined gdb convenience variables with 'if ($dx)'
# (can't even negate it) which would be false when the switch is undefined, i.e., same
# result as if it were 0.  Our initial default for these switches is OFF, so undefined
# and 0 have the same effect to indicate OFF.  Bit if any future switches are added,
# and their default is to be ON, then their polarity will have to be reversed; 0 meaning
# ON and 1 meaning OFF.  This is so the testing for those switches when they are
# initially undefined has the desired effect.  #%$@!()& gdb!
#
define MSET
    set $e = 0
    
    if ($argc == 0)
	printf "usage: MSET DITTO | UNMANGLE [ON | OFF | NOW | SHOW] (missing arguments)\n"
    else
	__lower_case $arg0
	__strcmp $lower_case "ditto"
	if ($strcmp)
	    set $which = 1
	else
	    __strcmp $lower_case "unmangle"
	    if ($strcmp)
	    	set $which = 2
	    else
	    	set $e = 1
		printf "usage: MSET DITTO | UNMANGLE [ON | OFF | NOW | SHOW] (invalid option)\n"
	    end
	end
	
	if (!$e)
	    if ($argc == 1)
	    	if ($which == 1)
		    if ($__ditto__)
		    	set $__ditto__ = 0
	    		printf "Ditto-display in memory dumps disabled\n"
		    else
		    	set $__ditto__ = 1
	    		printf "Ditto-display in memory dumps enabled\n"
		    end
	    	else
		    if ($__unmangle__)
		    	set $__unmangle__ = 0
	    		printf "Unmangling of symbols disabled\n"
			set print demangle off
			set print asm-demangle off
		    else
		    	set $__unmangle__ = 1
			set print demangle on
			set print asm-demangle on
	    		printf "Unmangling of symbols enabled\n"
		    end
		end
	    else
		__lower_case $arg1
		__strcmp $lower_case "on"
		if ($strcmp)
		    if ($which == 1)
			if ($__ditto__)
			    printf "Ditto-display in memory dumps is still enabled\n"
			else
			    set $__ditto__ = 1
			    printf "Ditto-display in memory dumps is enabled\n"
			end
		    else
			if ($__unmangle__)
			    printf "Unmangling of symbols is still enabled\n"
			else
			    set $__unmangle__ = 1
			    set print demangle on
			    set print asm-demangle on
			    printf "Unmangling of symbols is enabled\n"
			end
		    end
		else
		    __strcmp $lower_case "off"
		    if ($strcmp)
			if ($which == 1)
			    if ($__ditto__)
				set $__ditto__ = 0
				printf "Ditto-display in memory dumps is disabled\n"
			    else
				printf "Ditto-display in memory dumps is still disabled\n"
			    end
			else
			    if ($__unmangle__)
				set $__unmangle__ = 0
				set print demangle off
				set print asm-demangle off
				printf "Unmangling of symbols is disabled\n"
			    else
				printf "Unmangling of symbols is still disabled\n"
			    end
			end
		    else
			__strcmp $lower_case "now"
			if (!$strcmp)
			    __strcmp $lower_case "show"
			    if (!$strcmp)
				set $e = 1
			    end
			end
			if ($e || $argc > 2)
			    printf "usage: MSET DITTO | UNMANGLE [ON | OFF | NOW | SHOW] (invalid setting)\n"
			else
			    if ($which == 1)
				if ($__ditto__)
				    printf "Ditto-display in memory dumps is enabled\n"
				else
				    printf "Ditto-display in memory dumps is disabled\n"
				end
			    else
				if ($__unmangle__)
				    printf "Unmangling of symbols is still enabled\n"
				else
				    printf "Unmangling of symbols is still disabled\n"
				end
			    end
			end
		    end
		end
	    end
	end
    end
    
    set $__lastcmd__ = 40
end
document MSET
MSET option [ON|OFF|NOW|SHOW] -- Temporarially change the specified gdb MacsBug behavior.
On/off options toggle if you don't specify ON or OFF.  NOW or SHOW lets you check
the setting without disturbing it.  The options are:
Κ
Κ  DITTO:    When on, DM and DMA show ditto marks (''''''') instead of groups
Κ            of identical lines.
       
Κ  UNMANGLE: When on, C++ symbols appear as in source code, such as "TFoo::Bar()".
Κ            When off, you'll see stuff like "Bar__4TFooFv" instead.

SHOW is the same as NOW to display the current setting.  It was added since gdb
uses SHOW to show settings.
Κ
Macsbug features not supported: The is the MacsBug SET command was changed to
Κ                               MSET since SET conflicts with the SET gdb command.
Κ
Κ                               Options AUTOGP, ECHO, MOUSE, MENUBAR, SCROLLPROMPT,
Κ                               SUSPENDPROMPT, and SIMPLIFIED not supported.
end

###################################################################################
#
# PC, R0 - R31
#
define PC
    __rn $pc
end
document PC
PC -- display the value of PC
end
#
define R0
    __Rn $r0
end
document R0
R0 -- display the value of R0
end
#
define R1
    __Rn $r1
end
document R1
R1 -- display the value of R1
end
#
define R2
    __Rn $r2
end
document R2
R2 -- display the value of R2
end
#
define R3
    __Rn $r3
end
document R3
R3 -- display the value of R3
end
#
define R4
    __Rn $r4
end
document R4
R4 -- display the value of R4
end
#
define R5
    __Rn $r5
end
document R5
R5 -- display the value of R5
end
#
define R6
    __Rn $r6
end
document R6
R6 -- display the value of R6
end
#
define R7
    __Rn $r7
end
document R7
R7 -- display the value of R7
end
#
define R8
    __Rn $r8
end
document R8
R8 -- display the value of R8
end
#
define R9
    __Rn $r9
end
document R9
R9 -- display the value of R9
end
#
define R10
    __Rn $r10
end
document R10
R10 -- display the value of R10
end
#
define R11
    __Rn $r11
end
document R11
R11 -- display the value of R11
end
#
define R12
    __Rn $r12
end
document R12
R12 -- display the value of R12
end
#
define R13
    __Rn $r13
end
document R13
R13 -- display the value of R13
end
#
define R14
    __Rn $r14
end
document R14
R14 -- display the value of R14
end
#
define R15
    __Rn $r15
end
document R15
R15 -- display the value of R15
end
#
define R16
    __Rn $r16
end
document R16
R16 -- display the value of R16
end
#
define R17
    __Rn $r17
end
document R17
R17 -- display the value of R17
end
#
define R18
    __Rn $r18
end
document R18
R18 -- display the value of R18
end
#
define R19
    __Rn $r19
end
document R19
R19 -- display the value of R19
end
#
define R20
    __Rn $r20
end
document R20
R20 -- display the value of R20
end
#
define R21
    __Rn $r21
end
document R21
R21 -- display the value of R21
end
#
define R22
    __Rn $r22
end
document R22
R22 -- display the value of R22
end
#
define R23
    __Rn $r23
end
document R23
R23 -- display the value of R23
end
#
define R24
    __Rn $r24
end
document R24
R24 -- display the value of R24
end
#
define R25
    __Rn $r25
end
document R25
R25 -- display the value of R25
end
#
define R26
    __Rn $r26
end
document R26
R26 -- display the value of R26
end
#
define R27
    __Rn $r27
end
document R27
R27 -- display the value of R27
end
#
define R28
    __Rn $r28
end
document R28
R28 -- display the value of R28
end
#
define R29
    __Rn $r29
end
document R29
R29 -- display the value of R29
end
#
define R30
    __Rn $r30
end
document R30
R30 -- display the value of R30
end
#
define R31
    __Rn $r31
end
document R31
R31 -- display the value of R31
end
#
# __rn reg - display a single register value
#
# This is the common routine used by all Rn (n = 0...31) functions.  The
# register arg is the actual register specified ($rn) in lower case (since
# upper case $Ri appears to be a undefined convenience symbol).  This 
# internal routine is placed here since it is only for the singe register
# command displays immediate above here.
#
# The format we use is identical to the DL command.  MacsBug also puts some
# just in parenthesis after the value which I think is of dubious use.  So
# the hell with it.
#
define __Rn
    set $__r = (char *)"$arg0"
    set $__r[1] = 'A' + ($__r[1] - 'a')
    if ($__r[1] == 'P')
    	set $__r[2] = 'A' + ($__r[2] - 'a')
    end
    printf "%s = 0x%.8X   %u    %d    ", &$__r[1], $arg0, $arg0, $arg0
    __print_4 $arg0
    printf "\n"
    set $__lastcmd__ = 41
end
document __Rn
For internal use only -- do not use.
end

###################################################################################
#
# SB addr value1 [... value9]
#
define SB
    if ($argc < 2)
	printf "usage: SB addr value1 [... value9]\n"
	set $e = 1
    else
    	set $addr = $arg0
    	set $e = 0
    end

    set $debug = 0

    set $i = 1
    
    while ($i < $argc && $e == 0)
        if ($i == 1)
    	    set $value = $arg1
    	    __is_string ($arg1)
        else
    	    if ($i == 2)
    	    	set $value = $arg2
    	    	__is_string ($arg2)
    	    else
    	    	if ($i == 3)
		    set $value = $arg3
		    __is_string ($arg3)
    	    	else
    		    if ($i == 4)
    		    	set $value = $arg4
    		    	__is_string ($arg4)
    		    else
    		    	if ($i == 5)
    			    set $value = $arg5
    			    __is_string ($arg5)
    		    	else
    			    if ($i == 6)
    			    	set $value = $arg6
    			    	__is_string ($arg6)
    			    else
    			    	if ($i == 7)
    				    set $value = $arg7
    				    __is_string ($arg7)
    			    	else
    				    if ($i == 8)
    				    	set $value = $arg8
    				    	__is_string ($arg8)
    				    else
    				    	set $value = $arg9
    				    	__is_string ($arg9)
    				    	# gdb limits to 10 args and errors out for us
    				    end
    			    	end
    			    end
    		    	end
    		    end
    	    	end
    	    end
        end
	
	if ($i == 1)
	    printf "Memory set starting at %.8X\n", $addr
	    set $dot = $addr
	end
	
	if ($string)
	    __strlen $string
	    if ($debug)
	    	printf "__memcpy %.8X \"%s\" %d\n", $addr, $string, $strlen
	    else
	    	__memcpy $addr $string $strlen
	    end
	    set $addr = (unsigned char *)$addr + $strlen
	else
	    if ($debug)
	    	printf "%.8X = %.2X\n", $addr, (unsigned long)$value & 0xFF
	    else
	    	set *((unsigned char *)$addr) = (unsigned long)$value & 0xFF
	    end
	    set $addr = (unsigned char *)$addr + 1
	end
	
	set $i = $i + 1
    end
     
    if ($e == 0)
     	set $start = $arg0
      	set $n     = (unsigned long)$addr - (unsigned long)$start
     	if ($debug)
      	    printf "__hexdump %X %d\n", $start, (($n+15)/16)*16
      	else
     	    __hexdump $start (($n+15)/16)*16
    	end
    end
    
    set $__lastcmd__ = 17
end
document SB
SB addr value -- Assign up to 9 values to bytes starting at addr.
String values are fully assigned at the next assignable byte.
Κ
Restrictions: The values value may not have any embedded blanks.  For example
Κ             a value like (unsigned char *)0x1234 is invalid.
Κ
Κ             There is a limit of 9 values that can be set.
Κ
Macsbug features not supported: Double quoted "string" instead of single quoted
Κ                               'string'.
end

# Note, SB, SL, SW, and SM are parse their args exactly the same way.  We could
# generalize SM and let SB, SL, SW call it.  But that would mean taking away one
# or two arguments from the possible total of 10.  So to keep them all consistent
# with the 10 limit we repeat the code in each of these routines.

###################################################################################
#
# SC
#
define SC
    bt
    set $__lastcmd__ = 18
end
document SC
SC -- Display back trace.
end

###################################################################################
#
# SC6
#
define SC6
    bt
    set $__lastcmd__ = 19
end
document SC6
SC6 -- Same as SC.
end

###################################################################################
#
# SC7
#
define SC7
    bt
    set $__lastcmd__ = 20
end
document SC7
SC7 -- Same as SC.
end

###################################################################################
#
# SI [n] [m]
#
define SI
    if ($argc == 0)
    	if ($__lastcmd__ != 16 && $__lastcmd__ != 23)
	    set $__STEP__   = 1
	    set $__WINDOW__ = 4
	end
    else
    	if ($argc == 1)
    	    set $__STEP__   = $arg0
	    set $__WINDOW__ = 4
	else
	    set $__STEP__   = $arg0
	    set $__WINDOW__ = $arg1
	end
    end
    
    stepi $__STEP__
    set $dot = $pc
    __disasmN $pc $__WINDOW__ $pc
    
    set $__lastcmd__ = 16
end
document SI
SI [n] [m] -- Step n (or 1) instruction(s) and disassemble m (or 4) lines from new pc.
See also gdb's next and step instructions, which step by source lines,
not instructions.
Κ
The second argument is a extension to the MacsBug syntax to allow a disassembly
of m lines to show the next instructions to be executed.  This approximates the
disassembly window that MacsBug always shows.
Κ
Macsbug features not supported: S expr
Κ
Κ                               The MacsBug S is SI here.  This was done to preserve
Κ                               gdb's definition of S[tep] to single statement step.
Κ                               There is (was) a gdb SI to which does exactly what
Κ                               this MacsBug SI does except that now the instruction
Κ                               is also displayed at each instruction step.
end

###################################################################################
#
# SL addr value1 [... value9]
#
define SL
    if ($argc < 2)
	printf "usage: SL addr value1 [... value9]\n"
	set $e = 1
    else
    	set $addr = $arg0
    	set $e = 0
    end

    set $debug = 0
    
    set $i = 1
    
    while ($i < $argc && $e == 0)
        if ($i == 1)
    	    set $value = $arg1
    	    __is_string ($arg1)
        else
    	    if ($i == 2)
    	    	set $value = $arg2
    	    	__is_string ($arg2)
    	    else
    	    	if ($i == 3)
		    set $value = $arg3
		    __is_string ($arg3)
    	    	else
    		    if ($i == 4)
    		    	set $value = $arg4
    		    	__is_string ($arg4)
    		    else
    		    	if ($i == 5)
    			    set $value = $arg5
    			    __is_string ($arg5)
    		    	else
    			    if ($i == 6)
    			    	set $value = $arg6
    			    	__is_string ($arg6)
    			    else
    			    	if ($i == 7)
    				    set $value = $arg7
    				    __is_string ($arg7)
    			    	else
    				    if ($i == 8)
    				    	set $value = $arg8
    				    	__is_string ($arg8)
    				    else
    				    	set $value = $arg9
    				    	__is_string ($arg9)
    				    	# gdb limits to 10 args and errors out for us
    				    end
    			    	end
    			    end
    		    	end
    		    end
    	    	end
    	    end
        end
	
	if ($i == 1)
	    printf "Memory set starting at %.8X\n", $addr
	    set $dot = $addr
	end
	
	# Although we probably can use unaligned access, why take chances?  So
	# the following sets memory a byte at a time.
	
	if ($string)
	    __strlen $string
	    if ($debug)
	    	printf "__memcpy %.8X \"%s\" %d\n", $addr, $string, $strlen
	    else
	    	__memcpy $addr $string $strlen
	    end
	    set $addr = (unsigned char *)$addr + $strlen
	else
	    if ($debug)
	    	printf "%.8X = %.8X\n", $addr, (unsigned long)$value
	    	set $addr = (unsigned char *)$addr + 4
	    else
           	set *((unsigned char *)$addr) = ((unsigned long)$value >> 24) & 0xFF
           	set $addr = (unsigned char *)$addr + 1
           
           	set *((unsigned char *)$addr) = ((unsigned long)$value >> 16) & 0xFF
           	set $addr = (unsigned char *)$addr + 1
           
           	set *((unsigned char *)$addr) = ((unsigned long)$value >> 8) & 0xFF
           	set $addr = (unsigned char *)$addr + 1
           
           	set *((unsigned char *)$addr) = (unsigned long)$value & 0xFF
           	set $addr = (unsigned char *)$addr + 1
           end
	end
	
	set $i = $i + 1
    end
     
    if ($e == 0)
      	set $start = $arg0
      	set $n     = (unsigned long)$addr - (unsigned long)$start
    	if ($debug)
     	    printf "__hexdump %X %d\n", $start, (($n+15)/16)*16
     	else
     	    __hexdump $start (($n+15)/16)*16
     	end
    end
    
    set $__lastcmd__ = 21
end
document SL
SL addr value -- Assign up to 9 values to (4-byte) longs starting at addr.
String values are fully assigned at the next assignable byte.
Κ
Restrictions: The values value may not have any embedded blanks.  For example
Κ             a value like (unsigned char *)0x1234 is invalid.
Κ
Κ             There is a limit of 9 values that can be set.
Κ
Macsbug features not supported: Double quoted "string" instead of single quoted
Κ                               'string'.
end

# Note, SB, SL, SW, and SM are parse their args exactly the same way.  We could
# generalize SM and let SB, SL, SW call it.  But that would mean taking away one
# or two arguments from the possible total of 10.  So to keep them all consistent
# with the 10 limit we repeat the code in each of these routines.

###################################################################################
#
# SM addr value1 [... value9]
#
define SM
    if ($argc < 2)
	printf "usage: SM addr value1 [... value9]\n"
	set $e = 1
    else
    	set $addr = $arg0
    	set $e = 0
    end
    
    set $debug = 0
    
    set $i = 1
    
    while ($i < $argc && $e == 0)
        if ($i == 1)
    	    set $value = $arg1
    	    __is_string ($arg1)
        else
    	    if ($i == 2)
    	    	set $value = $arg2
    	    	__is_string ($arg2)
    	    else
    	    	if ($i == 3)
		    set $value = $arg3
		    __is_string ($arg3)
    	    	else
    		    if ($i == 4)
    		    	set $value = $arg4
    		    	__is_string ($arg4)
    		    else
    		    	if ($i == 5)
    			    set $value = $arg5
    			    __is_string ($arg5)
    		    	else
    			    if ($i == 6)
    			    	set $value = $arg6
    			    	__is_string ($arg6)
    			    else
    			    	if ($i == 7)
    				    set $value = $arg7
    				    __is_string ($arg7)
    			    	else
    				    if ($i == 8)
    				    	set $value = $arg8
    				    	__is_string ($arg8)
    				    else
    				    	set $value = $arg9
    				    	__is_string ($arg9)
    				    	# gdb limits to 10 args and errors out for us
    				    end
    			    	end
    			    end
    		    	end
    		    end
    	    	end
    	    end
        end
	
	if ($i == 1)
	    printf "Memory set starting at %.8X\n", $addr
	    set $dot = $addr
	end
	
	# Although we probably can use unaligned access, why take chances?  So
	# the following sets memory a byte at a time.
	
	if ($string)
	    __strlen $string
	    if ($debug)
	    	printf "__memcpy %.8X \"%s\" %d\n", $addr, $string, $strlen
	    else
	    	__memcpy $addr $string $strlen
	    end
	    set $addr = (unsigned char *)$addr + $strlen
	else
    	    if ((long)$value >= -128 && (long)$value <= 255)
    	    	set $size = 1
    	    else
    	    	if ((long)$value >= -32768 && (long)$value <= 65535)
    	    	    set $size = 2
	    	else
	    	    set $size = 4
	    	end
	    end
	    
	    if ($debug)
		if ($size == 4)
		    printf "%.8X = %.8X\n", $addr, (unsigned long)$value
		else
		    if ($size == 2)
		    	printf "%.8X = %.4X\n", $addr, (unsigned long)$value & 0xFFFF
		    else
		    	printf "%.8X = %.2X\n", $addr, (unsigned long)$value & 0xFF
		    end
		end
		set $addr = (unsigned char *)$addr + $size
	    else
	        if ($size == 4)
	           set *((unsigned char *)$addr) = ((unsigned long)$value >> 24) & 0xFF
	           set $addr = (unsigned char *)$addr + 1
	           	
	           set *((unsigned char *)$addr) = ((unsigned long)$value >> 16) & 0xFF
	           set $addr = (unsigned char *)$addr + 1
	        end
	        
	        if ($size == 2 || $size == 4)
	            set *((unsigned char *)$addr) = ((unsigned long)$value >> 8) & 0xFF
	            set $addr = (unsigned char *)$addr + 1
	        end
	        
	        set *((unsigned char *)$addr) = (unsigned long)$value & 0xFF
	        set $addr = (unsigned char *)$addr + 1
	    end
	end
	
	set $i = $i + 1
    end
     
    if ($e == 0)
     	set $start = $arg0
      	set $n     = (unsigned long)$addr - (unsigned long)$start
     	if ($debug)
     	    printf "__hexdump %X %d\n", $start, (($n+15)/16)*16
     	else
     	    __hexdump $start (($n+15)/16)*16
     	end
    end
    
    set $__lastcmd__ = 22
end
document SM
SM addr value -- Assign up to 9 values to memory starting at addr.
Each value determines the assignment size (byte, 2-byte word, or 4-byte
long).  Specific sizes can be set using SB, SW, or SL.  String values
are fully assigned at the next assignable byte.
Κ
Restrictions: The values value may not have any embedded blanks.  For example
Κ             a value like (unsigned char *)0x1234 is invalid.
Κ
Κ             There is a limit of 9 values that can be set.
Κ
Macsbug features not supported: Double quoted "string" instead of single quoted
Κ                               'string'.
end

# Note, SB, SL, SW, and SM are parse their args exactly the same way.  We could
# generalize SM and let SB, SL, SW call it.  But that would mean taking away one
# or two arguments from the possible total of 10.  So to keep them all consistent
# with the 10 limit we repeat the code in each of these routines.

###################################################################################
#
# SO [n] [m]
#
define SO
    if ($argc == 0)
    	if ($__lastcmd__ != 23 && $__lastcmd__ != 16)
	    set $__STEP__   = 1
	    set $__WINDOW__ = 4
	end
    else
    	if ($argc == 1)
    	    set $__STEP__   = $arg0
	    set $__WINDOW__ = 4
	else
	    set $__STEP__   = $arg0
	    set $__WINDOW__ = $arg1
	end
    end
    
    nexti $__STEP__
    set $dot = $pc
    __disasmN $pc $__WINDOW__ $pc
    
    set $__lastcmd__ = 23
end
document SO
SO [n] [m] -- Step over n instructions and disassemble m (or 4) lines from new pc.
See also gdb's next and step instructions, which step by source lines,
not instructions.
Κ
The second argument is a extension to the MacsBug syntax to allow a disassembly
of m lines to show the next instructions to be executed.  This approximates the
disassembly window that MacsBug always shows.
end

###################################################################################
#
# SW addr value1 [... value9]
#
define sw
    if ($argc < 2)
	printf "usage: SW addr value1 [... value9]\n"
	set $e = 1
    else
    	set $addr = $arg0
    	set $e = 0
    end

    set $debug = 0
    
    set $i = 1
    
    while ($i < $argc && $e == 0)
        if ($i == 1)
    	    set $value = $arg1
    	    __is_string ($arg1)
        else
    	    if ($i == 2)
    	    	set $value = $arg2
    	    	__is_string ($arg2)
    	    else
    	    	if ($i == 3)
		    set $value = $arg3
		    __is_string ($arg3)
    	    	else
    		    if ($i == 4)
    		    	set $value = $arg4
    		    	__is_string ($arg4)
    		    else
    		    	if ($i == 5)
    			    set $value = $arg5
    			    __is_string ($arg5)
    		    	else
    			    if ($i == 6)
    			    	set $value = $arg6
    			    	__is_string ($arg6)
    			    else
    			    	if ($i == 7)
    				    set $value = $arg7
    				    __is_string ($arg7)
    			    	else
    				    if ($i == 8)
    				    	set $value = $arg8
    				    	__is_string ($arg8)
    				    else
    				    	set $value = $arg9
    				    	__is_string ($arg9)
    				    	# gdb limits to 10 args and errors out for us
    				    end
    			    	end
    			    end
    		    	end
    		    end
    	    	end
    	    end
        end
	
	if ($i == 1)
	    printf "Memory set starting at %.8X\n", $addr
	    set $dot = $addr
	end
	
	# Although we probably can use unaligned access, why take chances?  So
	# the following sets memory a byte at a time.
	
	if ($string)
	    __strlen $string
	    if ($debug)
	    	printf "__memcpy %.8X \"%s\" %d\n", $addr, $string, $strlen
	    else
	    	__memcpy $addr $string $strlen
	    end
	    set $addr = (unsigned char *)$addr + $strlen
	else
            if ($debug)
	    	printf "%.8X = %.4X\n", $addr, (unsigned long)$value & 0xFFFF
            	set $addr = (unsigned char *)$addr + 2
            else
            	set *((unsigned char *)$addr) = ((unsigned long)$value >> 8) & 0xFF
            	set $addr = (unsigned char *)$addr + 1
            
            	set *((unsigned char *)$addr) = (unsigned long)$value & 0xFF
            	set $addr = (unsigned char *)$addr + 1
            end
        end
                
	set $i = $i + 1
     end
     
     if ($e == 0)
     	set $start = $arg0
      	set $n     = (unsigned long)$addr - (unsigned long)$start
     	if ($debug)
     	    printf "__hexdump %X %d\n", $start, (($n+15)/16)*16
     	else
     	    __hexdump $start (($n+15)/16)*16
     	end
     end
     
    set $__lastcmd__ = 24
end
document SW
SW addr value -- Assign up to 9 values to (2-byte) words starting at addr.
String values are fully assigned at the next assignable byte.
Κ
Restrictions: The values value may not have any embedded blanks.  For example
Κ             a value like (unsigned char *)0x1234 is invalid.
Κ
Κ             There is a limit of 9 values that can be set.
Κ
Macsbug features not supported: Double quoted "string" instead of single quoted
Κ                               'string'.
end

# Note, SB, SL, SW, and SM are parse their args exactly the same way.  We could
# generalize SM and let SB, SL, SW call it.  But that would mean taking away one
# or two arguments from the possible total of 10.  So to keep them all consistent
# with the 10 limit we repeat the code in each of these routines.

###################################################################################
#
# T [n] [m]
#
define T
    if ($argc == 0)
	SO
    else
    	if ($argc == 1)
	    SO $arg0
	else
	    SO $arg0 $arg1
	end
    end
    
    #set $__lastcmd__ = 25
end
document T
T [n] [m] -- Trace n (or 1) instruction(s), disassemble m (or 4) from pc -- same as SO.
end

###################################################################################
#
# TD
#
#PowerPC Registers
#                        CR0  CR1  CR2  CR3  CR4  CR5  CR6  CR7
# PC  = 05AB2950     CR  0100 0010 0000 0000 0000 1000 0100 1000
# LR  = 05AB29A4         <>=O XEVO
# CTR = FFD6A848
# MSR = 00000000         SOC Compare Count
# Int = 0            XER 000   00     00                     MQ  = 00000000
#
# R0  = 00000000     R8  = 00000000      R16 = 05B0FD25      R24 = 05B0FC90
# SP  = 05BCDF00     R9  = 05B150A0      R17 = 05B0FCAC      R25 = 0032822A
# TOC = 05B0AB4B     R10 = 00000000      R18 = 05B0FC8C      R26 = 00000003
# R3  = 0053866F     R11 = 00538E7A      R19 = 05B10668      R27 = 00000000
# R4  = 00000000     R12 = 0002CEA4      R20 = 05B0FCA9      R28 = 05BCE206
# R5  = 05BCDEF8     R13 = 00000000      R21 = 05B0FCAF      R29 = 05B32AD0
# R6  = 05ABAEC4     R14 = 00000000      R22 = 0000001E      R30 = 00538670
# R7  = 05B32AD0     R15 = 00000000      R23 = 00000000      R31 = 05B0FE6C
#
define TD
    printf "PowerPC Registers\n"
    printf "                        CR0  CR1  CR2  CR3  CR4  CR5  CR6  CR7\n"
    printf " PC  = %.8X     CR  ", $pc
    __binary ($cr>>28)    4
    printf " "
    __binary ($cr>>24&15) 4
    printf " "
    __binary ($cr>>20&15) 4
    printf " "
    __binary ($cr>>16&15) 4
    printf " "
    __binary ($cr>>12&15) 4
    printf " "
    __binary ($cr>>8&15)  4
    printf " "
    __binary ($cr>>4&15)  4
    printf " "
    __binary ($cr&15)     4
    printf "\n"
    
    printf " LR  = %.8X         <>=O XEVO\n", $lr
    printf " CTR = %.8X\n", $ctr
    printf " MSR = %.8X         SOC Compare Count\n", $ps
    printf "                    XER "
    __binary ($xer>>29&7) 3
    printf "   %.2X     %.2X                     MQ  = %.8X\n", ($xer>>16&0xFF), ($xer&0x7F), $mq
    
    printf "\n"
    
    printf " R0 = %.8X     R8  = %.8X      R16 = %.8X      R24 = %.8X\n", $r0, $r8,  $r16, $r24
    printf " SP = %.8X     R9  = %.8X      R17 = %.8X      R25 = %.8X\n", $r1, $r9,  $r17, $r25
    printf " R2 = %.8X     R10 = %.8X      R18 = %.8X      R26 = %.8X\n", $r2, $r10, $r18, $r26
    printf " R3 = %.8X     R11 = %.8X      R19 = %.8X      R27 = %.8X\n", $r3, $r11, $r19, $r27
    printf " R4 = %.8X     R12 = %.8X      R20 = %.8X      R28 = %.8X\n", $r4, $r12, $r20, $r28
    printf " R5 = %.8X     R13 = %.8X      R21 = %.8X      R29 = %.8X\n", $r5, $r13, $r21, $r29
    printf " R6 = %.8X     R14 = %.8X      R22 = %.8X      R30 = %.8X\n", $r6, $r14, $r22, $r30
    printf " R7 = %.8X     R15 = %.8X      R23 = %.8X      R31 = %.8X\n", $r7, $r15, $r23, $r31
    
    set $__lastcmd__ = 26
end
document TD
TD -- Display integer and machine registers.
end

###################################################################################
#
# TF
#
#PowerPC FPU Registers
#                                                  S S
#          F           N I I Z I                   O Q C
# FPSCR  F E V O U Z X A S D D M V F F             F R V V O U Z X N
#        X X X X X X X N I I Z Z C R I C < > = ?   T T I E E E E E I RN
#        1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 00
#  
# FPR0  = FFF 8000082004000     -NAN(000) 
# FPR1  = 408 4700000000000      6.540000000000000e+2 
# - - -
# FPR30 = 000 0000000000000      0.000000000000000e+0 
# FPR31 = 000 0000000000000      0.000000000000000e+0
#
# There's no way to display the floating regs in hex like this.  So we'll
# just have to settle with what info registers $fN produces.  It's a
# pretty good approximation so it isn't too bad.
#
define TF
    printf "PowerPC Vector Registers\n"
    printf "                                                  S S\n"
    printf "          F           N I I Z I                   O Q C\n"
    printf " FPSCR  F E V O U Z X A S D D M V F F             F R V V O U Z X N\n"
    printf "        X X X X X X X N I I Z Z C R I C < > = ?   T T I E E E E E I RN\n"
    
    printf "        "
    set $i = 0
    set $r = $fpscr
    while ($i++ < 32)
    	printf "%1d", ($r >> (32-$i)) & 1
    	if ($i < 31)
    	    printf " "
    	end
    end
    printf "\n\n"
    
    info registers $f0
    info registers $f1
    info registers $f2
    info registers $f3
    info registers $f4
    info registers $f5
    info registers $f6
    info registers $f7
    info registers $f8
    info registers $f9
    info registers $f10
    info registers $f11
    info registers $f12
    info registers $f13
    info registers $f14
    info registers $f15
    info registers $f16
    info registers $f17
    info registers $f18
    info registers $f19
    info registers $f20
    info registers $f21
    info registers $f22
    info registers $f23
    info registers $f24
    info registers $f25
    info registers $f26
    info registers $f27
    info registers $f28
    info registers $f29
    info registers $f30
    info registers $f31
    
    set $__lastcmd__ = 27
end
document TF
TF -- Display the floating point registers.
end

###################################################################################
#
# TV
#
#PowerPC Vector Registers
#                                                                      S
# VRsave = 00000000                    N                               A
#                                      J                               T
# VSCR = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
#   
# V0  = 00000000 00000000 00000000 00000000   0.0000e+0   0.0000e+0   0.0000e+0   0.0000e+0 
# V1  = 53706F74 20636865 636B206F 66207472   1.0327e+12  1.9262e-19  4.3373e+21  1.8943e+23 
# - - -
# V30 = 7FFFDEAD 7FFFDEAD 7FFFDEAD 7FFFDEAD   NAN(222)    NAN(222)    NAN(222)    NAN(222) 
# V31 = 7FFFDEAD 7FFFDEAD 7FFFDEAD 7FFFDEAD   NAN(222)    NAN(222)    NAN(222)    NAN(222)
#
define TV
    printf "PowerPC Vector Registers\n"
    printf "%c[31m", 0x1B
    printf " Not available - get get or manipulate the vector registers yet!  Sorry.  Sigh :-(\n"
    printf "\n"
    printf "%c[0m\n", 0x1B
    info registers
    
    set $__lastcmd__ = 28
end
document TV
TV -- Display the vector registers (not yet supported).
end

###################################################################################
###################################################################################

#           ##########################################################
#           # Internal helper functions for the above user functions #
#           ##########################################################

# Because gdb doesn't have the concept of local function variables the convention
# here is to define all "locals" with a double underbar prefix to try to keep them
# distinct from their function's callers.  Indeed, we also follow the convention
# for all these private function names as well.  It makes this stuff almost
# unreadable but that's gdb for you.  Yuk!

#
# __binary value n
#
# Internal function to display $arg0 as $arg1 binary digits.  Only the right-
# most $arg2 binary bits are displayed.  No newline is output here.
#
define __binary
    set $__value = $arg0
    set $__n     = $arg1
    
    set $__i = 0
    while ($__i++ < $__n)
    	printf "%1d", ($__value >> ($__n-$__i)) & 1
    end
end
document __binary
For internal use only -- do not use.
end

###################################################################################
#
# __branch_taken - determine if a conditional branch at $pc will be taken
#
# Returns $branch_taken = 1  if conditional branch will be taken
#			= -1 if conditional branch will not be taken
#			= 0  if not conditional branch at $pc
#
# The algorithm here is based on what is described in the IBM PPC Architecture book.
# To paraphrase what's there in determining whether the branch is taken or not it
# basically says:
#
#   bc[l][a]  (primary = 16)
#   bclr[l]   (primary = 19, extend = 16)
#     cond_ok = BO[0] || (CR[BI] == BO[1])
#     if !BO[2] then CTR = CTR-1
#     ctr_ok = BO[2] || (CTR != 0) ^ BO[3]
#     if ctr_ok && cond_ok then "will branch"
#     else "will not branch"
#
#   bcctr[l]  (primary = 19, extend = 528)
#     cond_ok = BO[0] || (CR[BI] == BO[1])
#     if cond_ok then "will branch"
#     else "will not branch"
#
# where the notation X[i] is bit i in field X.
#
# The implementation of this below is "optimized" to read as:
#     cond_ok = BO[0] || (CR[BI] == BO[1])
#     if (cond_ok && !"bcctr[l]") then cond_ok = BO[2] || (CTR-1 != 0) ^ BO[3]
#     if cond_ok then "will branch"
#     else "will not branch"
#
define __branch_taken
    # First decode the instruction to see if it's a conditional branch...
    set $__pri = *(unsigned long *)$pc >> 26
    if ($__pri == 19)
	set $__ext = (*(unsigned long *)$pc >> 1) & 0x3FF
	if ($__ext != 16 && $__ext != 528)
	    set $__pri = 0
	end
    else
	if ($__pri != 16)
	    set $__pri = 0
	else
	    set $__ext = 0	
	end
    end
    
    # If we have a conditional branch then check it out...
    
    if ($__pri)
	# cond_ok = BO[0] || (CR[BI] == BO[1])
	set $__cond_ok = ((*(unsigned long *)$pc & 0x02000000) != 0)
	if (!$__cond_ok)
	    set $__cond_ok = ((((unsigned long)$cr >> (31-((*(unsigned long *)$pc>>16) & 0x1f))) & 1) == \
			    (((*(unsigned long *)$pc & 0x01000000) >> 24) & 1))
	end
	
	if ($__cond_ok && ($__ext != 528))
	    # cond_ok = BO[2] || (CTR-1 != 0) ^ BO[3]
	    set $__cond_ok = ((*(unsigned long *)$pc & 0x00800000) != 0)
	    if (!$__cond_ok)
		set $__cond_ok = ($ctr-1 != 0) ^ ((*(unsigned long *)$pc & 0x00400000) >> 22)
	    end
	end
	
	if ($__cond_ok)
	    set $branch_taken = 1
	else
	    set $branch_taken = -1
	end
    else
    	set $branch_taken = 0
    end
end
document __branch_taken
For internal use only -- do not use.
end

###################################################################################
#
# __flag_asm_line loc flag color
#
# This is called when a disassembly line for the specified location (loc) is 
# output.  The cursor is positioned back to the start of the disassembly 
# (preceding) line and the location redisplayed to move the cursor to the
# space that follows it (so we don't have to know how long it was).  That space
# is then flagged with the specified flag character in the specified color.
#
# The color value is the standard xterm color value.
#
# Examples: color = 0  ==> normal
#                   1  ==> bold
#                   31 ==> red
#                   34 ==> blue
#
define __flag_asm_line
    printf "%c[1A", 0x1B
    printf "0x%x%c[%dm%c%c[0m\n", $arg0, 0x1B, $arg2, $arg1, 0x1B
end
document __flag_asm_line
For internal use only -- do not use.
end

###################################################################################
#
# __flag_pc - shorthand for __flag_asm_line $pc '*' 31
#
define __flag_pc
    __flag_asm_line $pc '*' 31
end
document __flag_pc
For internal use only -- do not use.
end

###################################################################################
#
# __flag_loc loc - shorthand for __flag_asm_line loc '*' 31
#
define __flag_loc
    set $__loc = $arg0
    __flag_asm_line $__loc '.' 34
end
document __flag_loc
For internal use only -- do not use.
end

###################################################################################
#
# __disasm1 loc flagloc
#
# Disassemble one instruction at loc.  If loc is equal to the flag_loc then flag
# the line with the pc flag if flag_loc == $pc or the non-pc loc flag if loc ==
# flag_loc.
#
define __disasm1
    set $__loc     = $arg0
    set $__flagloc = $arg1
    
    x/1i $__loc
    
    if ($__loc == $pc)
    	__flag_pc
    	__branch_taken
    else
    	if ($__loc == $__flagloc)
    	    __flag_loc $__flagloc
    	end
    end
end
document __disasm1
For internal use only -- do not use.
end

###################################################################################
#
# __disasmN addr n [flagloc]
#
# Disassemble n lines from addr and flag flagloc if it is specified.
#
define __disasmN
    set $__addr = $arg0
    set $__n    = $arg1
    
    if ($argc > 2)
    	set $__flagloc = $arg2
    else
     	set $__flagloc = -1
   end
    
    set $__i = 0
    set $branch_taken = 0
    
    while ($__i < $__n)
    	__disasm1 ((char*)$__addr+4*$__i++) $__flagloc
    end
    
    if ($branch_taken == 1)
    	printf "Will branch\n"
    else 
    	if ($branch_taken == -1)
    	    printf "Will not branch\n"
    	end
    end
    
    if ($__running__)
    	__display_registers_h
    end
end
document __disasmN
For internal use only -- do not use.
end

###################################################################################
#
# __hexdump [addr [n]] - dump n (default 16) bytes starting at addr (default pc)
#
define __hexdump
    if ($argc == 0)
    	set $__addr      = (unsigned char *)$pc
    	set $__addr1     = (unsigned char *)$pc + 16
    else
    	if ($argc == 1)
    	    set $__addr  = (unsigned char *)($arg0)
    	    set $__addr1 = (unsigned char *)$__addr + 16
    	else
    	    set $__addr  = (unsigned char *)($arg0)
   	    set $__addr1 = (unsigned char *)$__addr + ($arg1)
   	end
    end
    
    set $__prevaddr = (unsigned char *)$__addr
    set $__rep_count = 0
    
    while ($__addr < $__addr1)
    	set $__addr2 = $__addr
   	
   	# Only allow full ditto lines and never the last line
   	
    	if ((unsigned char *)$__addr + 16 < $__addr1)
    	    __repeated_dump_line $__prevaddr $__addr 16
    	else
    	    set $repeated = 0
    	end
    	set $__prevaddr = (unsigned char *)$__addr
     	
     	if ($repeated)
     	    if ($__rep_count++ == 0)
     		printf " %.8X: '''' '''' '''' ''''  '''' '''' '''' ''''  ''''''''''''''''\n", $__addr
     	    end
      	    set $__addr = (char *)$__addr + 16
     	else
     	    printf " %.8X: ", $__addr
     	    set $__rep_count = 0
      	    set $__i = 0
    	    while ($__i++ < 8)
      	    	set $__j = 0
    	    	while ($__j++ < 2)
     	    	    if ($__addr < $__addr1)
     	    	    	set $__x = *((unsigned char *)$__addr)++
 		    	printf "%1X%1X", ($__x >> 4) & 0x0F, $__x & 0x0F
 		    else
 		    	printf "  "
 		    end
     	    	end
     	    	printf " "
     	    	if ($__i == 4)
     	    	    printf " "
     	    	end
     	    end
  	    
  	    printf " "
  	    
      	    set $__i = 0
    	    while ($__i++ < 16)
  	    	if ($__addr2 < $__addr1)
    	    	    set $__x = *((unsigned char *)$__addr2)++
    	    	    if ($__x >= 0x20 && $__x <= 0x7F)
    	    	    	printf "%c", $__x
    	    	    else
    	    	    	printf "."
    	    	    end
 	    	else
    		    printf " "
 	    	end
     	    end
    	    printf "\n"
 	end
 	
    end
end
document __hexdump
For internal use only -- do not use.
end

###################################################################################
#
# __repeated_dump_line prev addr n - Check for repeated dump lines
#
# If the n bytes starting at the prev address is the same as the n bytes starting at addr then
# set $repeated to 1.  Otherwise set it to 0.
#				       
# This is used by __hexdump and DMA to control whether repeated lines are to be
# displayed.  This is further controlled by the MSET DITTO setting.
#
define __repeated_dump_line
    set $repeated = 0
    
    # Test $__ditto__ as a single operand just in case it is still undefined. Gdb
    # sets undefined convenience variables to void which tests as false.
    
    if ($__ditto__ && $arg0 < $arg1)
    	set $__p1 = (unsigned char *)$arg0
    	set $__p2 = (unsigned char *)$arg1
    	set $__k  = $arg2
    	
    	set $repeated = 1
     	
    	while ($repeated && $__k--)
    	    if (*((unsigned char *)$__p1)++ != *((unsigned char *)$__p2)++)
    	    	set $repeated = 0
    	    end
    	end
    else
    	set $repeated = 0
    end
end
document __repeated_dump_line
For internal use only -- do not use.
end

###################################################################################
#
# __print_char char [isString] - print a (possibly escaped) character
#
# If isString (actually any 2nd argument) is specified then this character is
# in the context of a "string" as opposed to a 'string' (i.e., the surrounding
# quotes on the string) so that a single quote do not need to be escaped.  On
# the other hand if this is the context of a double-quoted string then double
# quotes need to be escaped.
#
define __print_char
    set $__c = $arg0
    if ($__c <= 0xFF)
	if ($__c == '\n')
	    printf "\\n"
	else
	    if ($__c == '\r')
		printf "\\r"
	    else
		if ($__c == '\t')
		    printf "\\t"
		else 
		    if ($__c == '\a')
		    	printf "\\a"
		    else
		    	if ($__c == '\f')
		    	    printf "\\f"
		    	else
		    	    if ($__c == '\b')
		    	    	printf "\\b"
		    	    else
		    	    	if ($__c == '\v')
		    	    	    printf "\\v"
		    	    	else
		    	    	    if ($__c == '\'' && $argc == 1)
			    	    	printf "\\'"
		    	    	    else
		    	    	    	if ($__c == '"' && $argc > 1)
		    	    	    	    printf "\\\""
		    	    	    	else
			    	    	    if (($__c < 0x20) || ($__c >= 0x7f))
			    	    	    	# show escaped octals in bold
			    	    	    	printf "%c[1m\\%03o%c[0m", 0x1B, $__c, 0x1B
			    	    	    else
			    	    	    	printf "%c", $__c
			    	    	    end
			    	    	end
				    end
			    	end
			    end
			end
		    end
		end
	    end
	end
    end
end
document __print_char
For internal use only -- do not use.
end

###################################################################################
#
# __print_1 value
#
define __print_1
    set $__value = $arg0
    printf "'"
    __print_char ($__value&0xFF)
    printf "'"
end
document __print_1
For internal use only -- do not use.
end

###################################################################################
#
# __print_2 value
#
define __print_2
    set $__value = $arg0
    printf "'"
    __print_char ($__value>>8)&0xFF
    __print_char ($__value&0xFF)
    printf "'"
end
document __print_2
For internal use only -- do not use.
end

###################################################################################
#
# __print_4 value
#
define __print_4
    set $__value = $arg0
    printf "'"
    __print_char (($__value>>24)&0xFF)
    __print_char (($__value>>16)&0xFF)
    __print_char (($__value>>8)&0xFF)
    __print_char ($__value&0xFF)
    printf "'"
end
document __print_4
For internal use only -- do not use.
end

###################################################################################
#
# __strcmp s1 s2 - set $strcmp != 0 if strings match else 0
#
# We could test for the existence of the function strcmp() and use it instead of
# doing all this crap.  While the odds are that it would always be found (I think
# it's part of the System Framework which most everything links in, and I did
# always see it in my testing) having our own gdb strcmp is guaranteed and 100%
# safe.  While the probability is very low, it is not zero that the user defined
# his own strcmp() that doesn't do what the C/C++ strcmp() does.  Ok, I'm being
# overly paranoid.
#
define __strcmp
    set $__s1 = (unsigned char *)($arg0)
    set $__s2 = (unsigned char *)($arg1)
    
    set $strcmp = 1
    
    set $__c1 = *((unsigned char *)$__s1)++
    while ($strcmp && $__c1)
    	set $__c2 = *((unsigned char *)$__s2)++
	if ($__c1 == $__c2)
	    set $__c1 = *((unsigned char *)$__s1)++
	else
	    set $strcmp = 0
	end
    end
    
    set $strcmp &= (*(unsigned char *)$__s2 == 0)
end
document __strcmp
For internal use only -- do not use.
end

###################################################################################
#
# __strncmp s1 s2 n - set $strncmp != 0 if n characters of strings match else 0
#
# Similar to __strcmp except that this one's the equivalent to strncmp().
#
define __strncmp
    set $__s1 = (unsigned char *)($arg0)
    set $__s2 = (unsigned char *)($arg1)
    set $__n  = $arg2 + 1
    
    set $strncmp = 1
    
    while ($strncmp && --$__n)
    	set $__c1 = *((unsigned char *)$__s1)++
    	set $__c2 = *((unsigned char *)$__s2)++
    	
	if ($__c1 != $__c2)
	    set $strncmp = 0
	else
	    if ($__c1 == 0)
	    	set $__n = 1
	    end
	end
    end
end
document __strncmp
For internal use only -- do not use.
end

###################################################################################
#
# __strlen s - return the length of the string (argument) in $strlen
#
define __strlen
    set $strlen = -1
    set $__s = (char *)$arg0
    while ($__s[++$strlen])
    end
end
document __strlen
For internal use only -- do not use.
end

###################################################################################
#
# __memcpy s1 s2 n
#
define __memcpy
    set $__s1 = (unsigned char *)($arg0)
    set $__s2 = (unsigned char *)($arg1)
    set $__n  = $arg2 + 1
    
    while (--$__n)
    	set *((unsigned char *)$__s1)++ = *((unsigned char *)$__s2)++
    end
end
document __memcpy
For internal use only -- do not use.
end

###################################################################################
#
# __lower_case option_arg - lower case an option argument
#
# Returns $lower_case containing the lower cased copy of the option_arg.  The
# option_arg must be an ACTUAL $argN symbol from the caller, not a value set from it.
#
define __lower_case
    set $lower_case = (char *)"$arg0"
    set $__i = 0
    while ($lower_case[$__i])
	if ($lower_case[$__i] >= 'A' && $lower_case[$__i] <= 'Z')
	    set $lower_case[$__i] = 'a' + ($lower_case[$__i] - 'A')
	end
	set ++$__i
    end
end
document __lower_case
For internal use only -- do not use.
end

###################################################################################
#
# __is_string arg - determine if arg is a value or "string"
#
# Returns $string set to the a pointer to the string if arg is a string and $string
# is set to 0 if the arg is not a string.
#
# This function uses the fact (determined after much expirimentation) that assigning
# a value to a variable simply yields that value.  But assigning a string yields a
# new instance of the pointer to the string and thus the resultant pointer will not
# be the same as the original argument pointer.  If someone can figure out a simpler
# way of determining a double quoted "string" argument from a value in this dumb
# command language I'm open to it!
#
# Note, the arg must be an ACTUAL $argN symbol, not a value set from it.  A set
# assignment yields a pointer value.  We need the actual arg as written because
# actual arg substitution is a string substitution which we are assuming here when
# we do the (char *)$arg0 assignment.  We are actually doing (char *)"string" here
# when the arg really was a string which allows us to do what we do here.
#
define __is_string
    if ((long)$arg0 < 0)
    	# Negative values are assumed to be just that, values, and not strings.
    	set $string = 0
    else
    	# If value is not negative, get its value cast as a pointer...
        set $__p = (char *)$arg0
        
        # If original value is same as pointer value then it's a value. Otherwise
        # the set $__p created a new instance of the string (lucky for use) and
        # it won't be the same when it's a string.  What a kludge!  What a language!
        if ($__p == $arg0)
            set $string = 0
        else
            set $string = $__p
        end
    end
end
document __is_string
For internal use only -- do not use.
end

###################################################################################
#
# __save_all_regs_v - save current values of all registers
#
# This is called by __display_registers_v to remember the previous display.
# It is also called by __save_all_regs_h which saved additional registers.
#
define __save_all_regs_v
    set $__lr   = $lr
    set $__ctr  = $ctr
    set $__msr  = $ps
    
    set $__cr0  = ($cr>>28&15)
    set $__cr1  = ($cr>>24&15)
    set $__cr2  = ($cr>>20&15)
    set $__cr3  = ($cr>>16&15)
    set $__cr4  = ($cr>>12&15)
    set $__cr5  = ($cr>>8&15)
    set $__cr6  = ($cr>>4&15)
    set $__cr7  = ($cr&15)
    
    set $__r0  = $r0
    set $__sp  = $r1
    set $__r2  = $r2
    set $__r3  = $r3
    set $__r4  = $r4
    set $__r5  = $r5
    set $__r6  = $r6
    set $__r7  = $r7
    set $__r8  = $r8
    set $__r9  = $r9
    set $__r10 = $r10
    set $__r11 = $r11
    set $__r12 = $r12
    set $__r13 = $r13
    set $__r14 = $r14
    set $__r15 = $r15
    set $__r16 = $r16
    set $__r17 = $r17
    set $__r18 = $r18
    set $__r19 = $r19
    set $__r20 = $r20
    set $__r21 = $r21
    set $__r22 = $r22
    set $__r23 = $r23
    set $__r24 = $r24
    set $__r25 = $r25
    set $__r26 = $r26
    set $__r27 = $r27
    set $__r28 = $r28
    set $__r29 = $r29
    set $__r30 = $r30
    set $__r31 = $r31
end
document __save_all_regs_v
For internal use only -- do not use.
end

###################################################################################
#
# __save_all_regs_h - save current values of all registers
#
# This is called by __display_registers_h to remember the previous display.
#
define __save_all_regs_h
    __save_all_regs_v
    
    set $__so   = $xer>>31 & 1
    set $__ov   = $xer>>30 & 1
    set $__ca   = $xer>>29 & 1
    
    set $__cr00 = $__cr0>>3 & 1
    set $__cr01 = $__cr0>>2 & 1
    set $__cr02 = $__cr0>>1 & 1
    set $__cr03 = $__cr0    & 1
    
    set $__cr10 = $__cr1>>3 & 1
    set $__cr11 = $__cr1>>2 & 1
    set $__cr12 = $__cr1>>1 & 1
    set $__cr13 = $__cr1    & 1
    
    set $__cr20 = $__cr2>>3 & 1
    set $__cr21 = $__cr2>>2 & 1
    set $__cr22 = $__cr2>>1 & 1
    set $__cr23 = $__cr2    & 1
    
    set $__cr30 = $__cr3>>3 & 1
    set $__cr31 = $__cr3>>2 & 1
    set $__cr32 = $__cr3>>1 & 1
    set $__cr33 = $__cr3    & 1
    
    set $__cr40 = $__cr4>>3 & 1
    set $__cr41 = $__cr4>>2 & 1
    set $__cr42 = $__cr4>>1 & 1
    set $__cr43 = $__cr4    & 1
    
    set $__cr50 = $__cr5>>3 & 1
    set $__cr51 = $__cr5>>2 & 1
    set $__cr52 = $__cr5>>1 & 1
    set $__cr53 = $__cr5    & 1
    
    set $__cr60 = $__cr6>>3 & 1
    set $__cr61 = $__cr6>>2 & 1
    set $__cr62 = $__cr6>>1 & 1
    set $__cr63 = $__cr6    & 1
    
    set $__cr70 = $__cr7>>3 & 1
    set $__cr71 = $__cr7>>2 & 1
    set $__cr72 = $__cr7>>1 & 1
    set $__cr73 = $__cr7    & 1
end
document __save_all_regs_h
For internal use only -- do not use.
end

###################################################################################
#
# __display_registers_v [col] - display all registers in a fixed position vertically
#				on the right side of the terminal window (or starting
#				in the specified 1-relative column)
#
# Any register which changes value from the previous display is shown in red.  The
# "previous" display is one for which any compatible command was previously used
# (e.g., so's, si's, il's, etc.).
#
define __display_registers_v
    # Assume we will display in the last 14 columns of a 132-width display starting
    # at the top of the window...
    
    set $screen_width = 132
    set $__row = 1
    
    # We'll generalize this a bit to specify a starting column which defaults to
    # the screen width minus 14.  We don't allow specifying the top row since
    # scrolling always moves the display up when a command is entered and this
    # display looks as best as we can when we start it on row 1.
     
    if ($argc == 1)
	set $__col = $arg0
    else
        set $__col = $screen_width - 14
    end
    
    # If the previous command wasn't one that displayed the registers then init
    # the previous values with the current values.  This also makes sure they 
    # are defined the first time we ever use them.
    
    # Check for ID, IL, IP, SI, and SO...
    if ($__lastcmd__ != 9  && \
        $__lastcmd__ != 11 && \
        $__lastcmd__ != 13 && \
        $__lastcmd__ != 16 && \
        $__lastcmd__ != 23)
	__save_all_regs_v
	set $__saved_regs = 1
    else
        set $__saved_regs = 0
    end
        
    # Finally print all these suckers.  We control the positioning for each registers
    # and make sure we preserve the cursor's original position so we leave it where
    # we found it.
    
    printf "%c7", 0x1B
    printf "%c[%d;%dH+ΡΡΡΡΡΡΡΡΡΡΡΡΡ%c[0K", 0x1B,         $__row, $__col, 0x1B
    #set $__row += 0

    printf "%c[%d;%dH| PC  %.8X%c[0K", 0x1B,             $__row+ 1, $__col, $pc, 0x1B
    printf "%c[%d;%dH| SP  %.8X%c[0K", 0x1B,             $__row+ 2, $__col, $sp, 0x1B
    printf "%c[%d;%dH| %c[0K", 0x1B,                     $__row+ 3, $__col, 0x1B

    printf "%c[%d;%dH| CR  ", 0x1B,                      $__row+ 4, $__col
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr0 != ($cr>>28&15)), ($cr>>28&15), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr1 != ($cr>>24&15)), ($cr>>24&15), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr2 != ($cr>>20&15)), ($cr>>20&15), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr3 != ($cr>>16&15)), ($cr>>16&15), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr4 != ($cr>>12&15)), ($cr>>12&15), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr5 != ($cr>>8&15 )), ($cr>>8&15 ), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr6 != ($cr>>4&15 )), ($cr>>4&15 ), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr7 != ($cr&15    )), ($cr&15    ), 0x1B
    printf "%c[0K", 0x1B
    printf "%c[%d;%dH| %c[0K", 0x1B,                     $__row+ 5, $__col, 0x1B

    printf "%c[%d;%dH| LR  %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+ 6, $__col, 0x1B, ($__lr  != $lr ),  $lr,  0x1B, 0x1B
    printf "%c[%d;%dH| CTR %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+ 7, $__col, 0x1B, ($__ctr != $ctr),  $ctr, 0x1B, 0x1B
    printf "%c[%d;%dH| MSR %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+ 8, $__col, 0x1B, ($__msr != $ps ),  $ps,  0x1B, 0x1B

    printf "%c[%d;%dH| %c[0K", 0x1B,                     $__row+ 9, $__col, 0x1B
    set $__row += 10
    
    printf "%c[%d;%dH| R0  %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+ 0, $__col, 0x1B, ($__r0  != $r0 ), $r0,  0x1B, 0x1B
    printf "%c[%d;%dH| SP  %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+ 1, $__col, 0x1B, ($__sp  != $r1 ), $r1,  0x1B, 0x1B
    printf "%c[%d;%dH| R2  %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+ 2, $__col, 0x1B, ($__r2  != $r2 ), $r2,  0x1B, 0x1B
    printf "%c[%d;%dH| R3  %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+ 3, $__col, 0x1B, ($__r3  != $r3 ), $r3,  0x1B, 0x1B
    printf "%c[%d;%dH| R4  %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+ 4, $__col, 0x1B, ($__r4  != $r4 ), $r4,  0x1B, 0x1B
    printf "%c[%d;%dH| R5  %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+ 5, $__col, 0x1B, ($__r5  != $r5 ), $r5,  0x1B, 0x1B
    printf "%c[%d;%dH| R6  %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+ 6, $__col, 0x1B, ($__r6  != $r6 ), $r6,  0x1B, 0x1B
    printf "%c[%d;%dH| R7  %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+ 7, $__col, 0x1B, ($__r7  != $r7 ), $r7,  0x1B, 0x1B
    printf "%c[%d;%dH| R8  %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+ 8, $__col, 0x1B, ($__r8  != $r8 ), $r8,  0x1B, 0x1B
    printf "%c[%d;%dH| R9  %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+ 9, $__col, 0x1B, ($__r9  != $r9 ), $r9,  0x1B, 0x1B
    printf "%c[%d;%dH| R10 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+10, $__col, 0x1B, ($__r10 != $r10), $r10, 0x1B, 0x1B
    printf "%c[%d;%dH| R11 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+11, $__col, 0x1B, ($__r11 != $r11), $r11, 0x1B, 0x1B
    printf "%c[%d;%dH| R12 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+12, $__col, 0x1B, ($__r12 != $r12), $r12, 0x1B, 0x1B
    printf "%c[%d;%dH| R13 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+13, $__col, 0x1B, ($__r13 != $r13), $r13, 0x1B, 0x1B
    printf "%c[%d;%dH| R14 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+14, $__col, 0x1B, ($__r14 != $r14), $r14, 0x1B, 0x1B
    printf "%c[%d;%dH| R15 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+15, $__col, 0x1B, ($__r15 != $r15), $r15, 0x1B, 0x1B
    printf "%c[%d;%dH| R16 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+16, $__col, 0x1B, ($__r16 != $r16), $r16, 0x1B, 0x1B
    printf "%c[%d;%dH| R17 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+17, $__col, 0x1B, ($__r17 != $r17), $r17, 0x1B, 0x1B
    printf "%c[%d;%dH| R18 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+18, $__col, 0x1B, ($__r18 != $r18), $r18, 0x1B, 0x1B
    printf "%c[%d;%dH| R19 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+19, $__col, 0x1B, ($__r19 != $r19), $r19, 0x1B, 0x1B
    printf "%c[%d;%dH| R20 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+20, $__col, 0x1B, ($__r20 != $r20), $r20, 0x1B, 0x1B
    printf "%c[%d;%dH| R21 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+21, $__col, 0x1B, ($__r21 != $r21), $r21, 0x1B, 0x1B
    printf "%c[%d;%dH| R22 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+22, $__col, 0x1B, ($__r22 != $r22), $r22, 0x1B, 0x1B
    printf "%c[%d;%dH| R23 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+23, $__col, 0x1B, ($__r23 != $r23), $r23, 0x1B, 0x1B
    printf "%c[%d;%dH| R24 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+24, $__col, 0x1B, ($__r24 != $r24), $r24, 0x1B, 0x1B
    printf "%c[%d;%dH| R25 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+25, $__col, 0x1B, ($__r25 != $r25), $r25, 0x1B, 0x1B
    printf "%c[%d;%dH| R26 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+26, $__col, 0x1B, ($__r26 != $r26), $r26, 0x1B, 0x1B
    printf "%c[%d;%dH| R27 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+27, $__col, 0x1B, ($__r27 != $r27), $r27, 0x1B, 0x1B
    printf "%c[%d;%dH| R28 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+28, $__col, 0x1B, ($__r28 != $r28), $r28, 0x1B, 0x1B
    printf "%c[%d;%dH| R29 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+29, $__col, 0x1B, ($__r29 != $r29), $r29, 0x1B, 0x1B
    printf "%c[%d;%dH| R30 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+30, $__col, 0x1B, ($__r30 != $r30), $r30, 0x1B, 0x1B
    printf "%c[%d;%dH| R31 %c[3%dm%.8X%c[0m%c[0K", 0x1B, $__row+31, $__col, 0x1B, ($__r31 != $r31), $r31, 0x1B, 0x1B
    
    printf "%c[%d;%dH+ΡΡΡΡΡΡΡΡΡΡΡΡΡ%c[0K", 0x1B,         $__row+32, $__col, 0x1B
    printf "%c8", 0x1B
    
    # Now that we know what's changed, save the values for the next time
    # through here unless we already saved them.
    
    if (!$__saved_regs)
    	__save_all_regs_v
    end
end
document __display_registers_v
For internal use only -- do not use.
end

###################################################################################
#
# __display_registers_h - display all registers horizontally at the top of the
#			  screen
#
# Any register which changes value from the previous display is shown in red.  The
# "previous" display is one for which any compatible command was previously used
# (e.g., so's, si's, il's, etc.).
#
# PC  00001D18        CR0  CR1  CR2  CR3  CR4  CR5  CR6  CR7
# LR  00001D14    CR  1000 0010 0000 0000 0000 0000 0001 0100
# CTR 5ACE8160     
# MSR 0002D030    XER 000 (SOC)
# 
# R0 00001C48     R8  00000000      R16 00000000      R24 00000000
# SP BFFFF170     R9  BFFFF378      R17 00000000      R25 00000000
# R2 00000000     R10 BFFFF3DF      R18 00000000      R26 BFFFF284
# R3 00000001     R11 BFFFFFFF      R19 00000000      R27 00000008
# R4 BFFFF288     R12 5ACE8160      R20 00000000      R28 00000001
# R5 BFFFF290     R13 00000000      R21 00000000      R29 BFFFF290
# R6 BFFFF370     R14 00000000      R22 00000000      R30 BFFFF170
# R7 0000000A     R15 00000000      R23 00000000      R31 00001D14
#
define __display_registers_h
    # If the previous command wasn't one that displayed the registers then init
    # the previous values with the current values.  This also makes sure they 
    # are defined the first time we ever use them.
    
    # Check for ID, IL, IP, SI, and SO...
    if ($__lastcmd__ != 9  && \
        $__lastcmd__ != 11 && \
        $__lastcmd__ != 13 && \
        $__lastcmd__ != 16 && \
        $__lastcmd__ != 23)
	__save_all_regs_h
	set $__saved_regs = 1
    else
        set $__saved_regs = 0
    end
    
    printf "%c7", 0x1B
    printf "%c[1;1H", 0x1B

    printf "PC  %.8X        CR0  CR1  CR2  CR3  CR4  CR5  CR6  CR7%c[0K\n", $pc, 0x1B
    
    printf "LR  %c[3%dm%.8X%c[0m    CR  ", 0x1B, ($__lr  != $lr),  $lr, 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr00 != ($cr>>31&1)), ($cr>>31&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr01 != ($cr>>30&1)), ($cr>>30&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr02 != ($cr>>29&1)), ($cr>>29&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr03 != ($cr>>28&1)), ($cr>>28&1), 0x1B
    printf " "
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr10 != ($cr>>27&1)), ($cr>>27&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr11 != ($cr>>26&1)), ($cr>>26&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr12 != ($cr>>25&1)), ($cr>>25&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr13 != ($cr>>24&1)), ($cr>>24&1), 0x1B
    printf " "
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr20 != ($cr>>23&1)), ($cr>>23&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr21 != ($cr>>22&1)), ($cr>>22&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr22 != ($cr>>21&1)), ($cr>>21&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr23 != ($cr>>20&1)), ($cr>>20&1), 0x1B
    printf " "
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr30 != ($cr>>19&1)), ($cr>>19&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr31 != ($cr>>18&1)), ($cr>>18&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr32 != ($cr>>17&1)), ($cr>>17&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr33 != ($cr>>16&1)), ($cr>>16&1), 0x1B
    printf " "
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr40 != ($cr>>15&1)), ($cr>>15&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr41 != ($cr>>14&1)), ($cr>>14&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr42 != ($cr>>13&1)), ($cr>>13&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr43 != ($cr>>12&1)), ($cr>>12&1), 0x1B
    printf " "
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr50 != ($cr>>11&1)), ($cr>>11&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr51 != ($cr>>10&1)), ($cr>>10&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr52 != ($cr>>9 &1)), ($cr>>9 &1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr53 != ($cr>>8 &1)), ($cr>>8 &1), 0x1B
    printf " "
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr60 != ($cr>>7 &1)), ($cr>>7 &1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr61 != ($cr>>6 &1)), ($cr>>6 &1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr62 != ($cr>>5 &1)), ($cr>>5 &1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr63 != ($cr>>4 &1)), ($cr>>4 &1), 0x1B
    printf " "
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr70 != ($cr>>3 &1)), ($cr>>3 &1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr71 != ($cr>>2 &1)), ($cr>>2 &1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr72 != ($cr>>1 &1)), ($cr>>1 &1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__cr73 != ($cr    &1)), ($cr    &1), 0x1B
    printf "%c[0K\n", 0x1B

    printf "CTR %c[3%dm%.8X%c[0m%c[0K\n", 0x1B, ($__ctr != $ctr),  $ctr, 0x1B, 0x1B
    
    printf "MSR %c[3%dm%.8X%c[0m    XER ",   0x1B, ($__msr != $ps),  $ps,  0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__so != ($xer>>31&1)), ($xer>>31&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__ov != ($xer>>30&1)), ($xer>>30&1), 0x1B
    printf "%c[3%dm%.1X%c[0m", 0x1B, ($__ca != ($xer>>29&1)), ($xer>>29&1), 0x1B
    printf " (SOC)%c[0K\n", 0x1B

    printf "%c[0K\n", 0x1B
    
    printf "R0 %c[3%dm%.8X%c[0m     ",  0x1B, ($__r0  != $r0 ), $r0,  0x1B
    printf "R8  %c[3%dm%.8X%c[0m     ", 0x1B, ($__r8  != $r8 ), $r8,  0x1B
    printf "R16 %c[3%dm%.8X%c[0m     ", 0x1B, ($__r16 != $r16), $r16, 0x1B
    printf "R24 %c[3%dm%.8X%c[0m", 0x1B, ($__r24 != $r24), $r24, 0x1B
    printf "%c[0K\n", 0x1B
    
    printf "SP %c[3%dm%.8X%c[0m     ",  0x1B, ($__sp  != $r1 ), $r1,  0x1B
    printf "R9  %c[3%dm%.8X%c[0m     ", 0x1B, ($__r9  != $r9 ), $r9,  0x1B
    printf "R17 %c[3%dm%.8X%c[0m     ", 0x1B, ($__r17 != $r17), $r17, 0x1B
    printf "R25 %c[3%dm%.8X%c[0m", 0x1B, ($__r25 != $r25), $r25, 0x1B
    printf "%c[0K\n", 0x1B
    
    printf "R2 %c[3%dm%.8X%c[0m     ",  0x1B, ($__r2  != $r2 ), $r2,  0x1B
    printf "R10 %c[3%dm%.8X%c[0m     ", 0x1B, ($__r10 != $r10), $r10, 0x1B
    printf "R18 %c[3%dm%.8X%c[0m     ", 0x1B, ($__r18 != $r18), $r18, 0x1B
    printf "R26 %c[3%dm%.8X%c[0m",      0x1B, ($__r26 != $r26), $r26, 0x1B
    printf "%c[0K\n", 0x1B
     
    printf "R3 %c[3%dm%.8X%c[0m     ",  0x1B, ($__r3  != $r3 ), $r3,  0x1B
    printf "R11 %c[3%dm%.8X%c[0m     ", 0x1B, ($__r11 != $r11), $r11, 0x1B
    printf "R19 %c[3%dm%.8X%c[0m     ", 0x1B, ($__r19 != $r19), $r19, 0x1B
    printf "R27 %c[3%dm%.8X%c[0m",      0x1B, ($__r27 != $r27), $r27, 0x1B
    printf "%c[0K\n", 0x1B
     
    printf "R4 %c[3%dm%.8X%c[0m     ",  0x1B, ($__r4  != $r4 ), $r4,  0x1B
    printf "R12 %c[3%dm%.8X%c[0m     ", 0x1B, ($__r12 != $r12), $r12, 0x1B
    printf "R20 %c[3%dm%.8X%c[0m     ", 0x1B, ($__r20 != $r20), $r20, 0x1B
    printf "R28 %c[3%dm%.8X%c[0m",      0x1B, ($__r28 != $r28), $r28, 0x1B
    printf "%c[0K\n", 0x1B
     
    printf "R5 %c[3%dm%.8X%c[0m     ",  0x1B, ($__r5  != $r5 ), $r5,  0x1B
    printf "R13 %c[3%dm%.8X%c[0m     ", 0x1B, ($__r13 != $r13), $r13, 0x1B
    printf "R21 %c[3%dm%.8X%c[0m     ", 0x1B, ($__r21 != $r21), $r21, 0x1B
    printf "R29 %c[3%dm%.8X%c[0m",      0x1B, ($__r29 != $r29), $r29, 0x1B
    printf "%c[0K\n", 0x1B
     
    printf "R6 %c[3%dm%.8X%c[0m     ",  0x1B, ($__r6  != $r6 ), $r6,  0x1B
    printf "R14 %c[3%dm%.8X%c[0m     ", 0x1B, ($__r14 != $r14), $r14, 0x1B
    printf "R22 %c[3%dm%.8X%c[0m     ", 0x1B, ($__r22 != $r22), $r22, 0x1B
    printf "R30 %c[3%dm%.8X%c[0m",      0x1B, ($__r30 != $r30), $r30, 0x1B
    printf "%c[0K\n", 0x1B
     
    printf "R7 %c[3%dm%.8X%c[0m     ",  0x1B, ($__r7  != $r7 ), $r7,  0x1B
    printf "R15 %c[3%dm%.8X%c[0m     ", 0x1B, ($__r15 != $r15), $r15, 0x1B
    printf "R23 %c[3%dm%.8X%c[0m     ", 0x1B, ($__r23 != $r23), $r23, 0x1B
    printf "R31 %c[3%dm%.8X%c[0m",      0x1B, ($__r31 != $r31), $r31, 0x1B
    printf "%c[0K", 0x1B

    printf "\nΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ%c[0K", 0x1B
    printf "%c8", 0x1B
    
    # Now that we know what's changed, save the values for the next time
    # through here unless we already saved them.
    
    if (!$__saved_regs)
    	__save_all_regs_h
    end
end
document __display_registers_h
For internal use only -- do not use.
end

###################################################################################
#
# __scroll N - turn scrolling on (N > 0) or off (N < 0)
#
# If turned on, scrolling extends from line 15 through $arg0 to accomodate the
# 14-line register display done by __display_registers_h starting at line 1.  If
# scrolling is turned off, scrolling is set from line 1 through -$arg0
#
define __scroll
    #set $screen_height = 60

    set $__bottom = $arg0
    
    if ($__bottom > 0)
    	if ($__running__)
	    __display_registers_h
	else
    	    printf "%c[1;1HRegisters will be displayed here when program is running.", 0x1B
    	    printf "%c[0J", 0x1B 
	end
    	
    	printf "%c[14;1H", 0x1B
    	printf "ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ%c[0K%c8", 0x1B, 0x1B
    	printf "%c[15;%dr", 0x1B, $__bottom
    	printf "%c[15;1H", 0x1B
    	printf "%c[0J", 0x1B
    else
    	printf "%c7", 0x1B
    	printf "%c[1;%dr", 0x1B, -$__bottom
    	printf "%c8", 0x1B
    end
    
    
end
document __scroll
For internal use only -- do not use.
end

###################################################################################
#
# Intercept the RUN command to initialize our "global" convenience variables.  None
# of the Macsbug commands make sense anyway until the user does a RUN command.  This
# is fortunate since the only way to fire up execution is with a run command and
# there is NO OTHER WAY to initialize convenience variables!  Simply setting them in
# this script doesn't work since gdb wipes out the variables AFTER it runs the
# script.  They also get wiped out when a FILE command is done (and a hook-file is
# run before the variables are clobbered so that won't work either).
#
define hook-run
    set $dot            = 0
    set $__lastcmd__    = -1
    set $__next_addr__  = -1
    set $__prev_dm_n__  = 0
    set $__prev_dma_n__ = 0
    
    if ($__initialized__)
    	# When $__initialized__ is undefined it will test false.  We can only test
    	# undefined gdb convenience variables as shown (i.e., cannot mix with any
    	# operators).  So this path of this if remains empty once we initialize the
    	# state switches.  Of course a FILE command will uninialize everyting again.
    else
    	set $__unmangle__ = 0
    	set $__ditto__    = 0
    	set $__dx__       = 0
    	
    	set $__initialized__ = 1
    	set $__running__ = 1
    end
end

###################################################################################