Release 970120

Sun Jan 19 11:46:48 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [loader/module.c]
	Fixed LoadModule() to always call the DLL initialization code.

	* [windows/event.c]
	Moved all the keyboard stuff to windows/keyboard.c

	* [tools/build.c]
	Fixed Win32 register functions.

Sat Jan 18 22:24:41 1997  David Makepeace  <D.Makepeace@mailbox.uq.oz.au>

        * [tools/makedep.c]
        Fixed bug which causes SEGV on Solaris x86.

Fri Jan 17 18:32:27 1997  Frans van Dorsselaer <dorssel@rulhmpc49.LeidenUniv.nl>

	* [controls/edit.c]
	Implemented WM_UNDO, WM_CONTEXTMENU (temporary using WM_RBUTTONUP),
	WM_COMMAND, WM_INITPOPUPMENU, WM_SYSKEYDOWN.
	Fixed EM_SETSEL and some minor bugs (features).
	Hence: fully functional undo and a win95 menu with the right mouse
		button.

	* [include/resources.h] [resources/TODO] [resources/sysres_??.rc]
	Added a context menu for the edit control.
	Translations, please ...

Fri Jan	17 08:29:52 1997  David Faure <david.faure@ifhamy.insa-lyon.fr>

	* [windows/event.c]
	Move EVENT_ToAscii to windows/keyboard.c (where name ToAscii)
	Fixed Keypad keys 0-9 and . in EVENT_event_to_vkey.
	Added 3-state handling of toggle keys (CapsLock, NumLock) in order
	to make them work with any X server.
	Toggle keys now generate WM_KEYDOWN and WM_KEYUP on each pressing.

	* [include/keyboard.h]
	Totally replaced the file (formerly containing the vkcase definitions)
	by the declaration of 'extern' variables contained by event.c and used
	by keyboard.c
	
	* [windows/keyboard.c]
	Started to rewrite VkKeyScan and MapVirtualKey, to make them use the 
	table keyc2vkey or X functions only.
	ToAscii : added keypad 0-9 and . special case.
	Changed toggle keys active mask from 0x80 to 0x1.

	* [misc/keyboard.c]
	File deleted. Contents moved to windows/keyboard.c.

	* [misc/main.c]
	Added putenv XKB_DISABLE to disable XKB extension (which, when
	present, causes AltGr to change keyboard group instead of being a
	modifier).

Tue Jan 14 22:56:43 1997  Philippe De Muyter  <phdm@info.ucl.ac.be>

	* [windows/event.c]
	Do not assume NumLockMask is Mod2Mask, but compute it by scanning
	output of XGetModifierMapping for XK_Num_Lock.

Tue Jan 14 15:49:49 1997  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [loader/pe_*.c] [include/peexe.h] [include/resource32.h]
	  [debugger/*.c]
	General clean up.
	Changed defines/structures to match Windows NT SDK.

	* [loader/main.c]
	Don't crash on empty command-line.

	* [windows/winpos.c]
	winpos.c made win32 clean.

	* [misc/ntdll.c]
	Some string conversion additions.

	* [files/file.c]
	GetFileAttributes/GetTempFileName fixed.

	* [misc/ver.c]
	VerInstallFile implemented.

Mon Jan 13 15:03:11 1997  Philippe De Muyter  <phdm@info.ucl.ac.be>

	* [tools/build.c]: Use PREFIX also in stabs messages.

Mon Jan 13 10:40:33 1997  John Harvey <john@division.co.uk>

	* [graphics/win16drv/*] [include/win16drv.h]
	Many fixes and some new features.

	* [graphics/x11drv/font.c] [graphics/x11drv/init.c]
	  [include/x11drv.h] [objects/font.c]
	GetTextMetrics() moved to graphics driver.

	* [if1632/gdi.spec] [misc/fontengine.c] [misc/Makefile.in]
	New dummy EngineEnumerateFont, EngineRealizeFont functions.

	* [include/windows.h]
	TEXTFORM16 and FONTINFO16 structure definitions moved here from
	include/win16drv.h
diff --git a/debugger/README b/debugger/README
index 02cad9b..412b7e8 100644
--- a/debugger/README
+++ b/debugger/README
@@ -1,8 +1,7 @@
-	This is the core of the Wine debugger.  Many pieces have been
-shamelessly stolen - the reverse assember was stolen from Mach more or
-less intact.  It turns out that there are two variables that are set
-differently if you are reverse assembling 16 bit code, and on the
-whole it seems to work.
+	This is the core of the Wine debugger.  The reverse assember
+was stolen from Mach more or less intact.  It turns out that there are
+two variables that are set differently if you are reverse assembling
+16 bit code, and on the whole it seems to work.
 
 NEWS:
 
@@ -63,6 +62,16 @@
 automatic display expressions.  An example is at the end of this file.  The
 syntax and usage should be identical to that of gdb.
 
+	8) Type casts can be made from within the debugger, but they currently
+don't work with typedef'ed types.  They only work with builtin types and
+named structures unions, etc.  The problem is that internally we don't always
+record the typedefed names of structures, so we have no guarantee that we
+would know what each type is.  This can be fixed, of course -  it just takes
+more memory.  Note that in some cases, typedefed structures could be cast
+using '(struct typedfname)' instead of '(typedfname)'.   Technically this
+isn't quite correct, but if and when the rest of this stuff gets fixed,
+this would need to get corrected too.
+
 NOTES:
 
 	If it weren't for the fact that gdb doesn't grok the Win32 debug
@@ -73,16 +82,6 @@
 
 LIMITATIONS AND DIFFERENCES FROM GDB:
 
-	You cannot use type casts in expressions that you give to the
-debugger.  The hardest part about adding support for this is fixing
-the parser/lexer to know when it is handling a type cast, and when it
-is handling any other type of parenthesized expression.  With lexer
-states, it may be possible to keep track of what we would expect at
-any given moment, but it would be tedious to go through and make sure
-that the state is set up correctly for all of the different operators
-and characters that we accept, and I am not yet convinced that this would
-even work.
-
 	You cannot set a breakpoint by file and line number as you can
 with gdb.  Adding support for this wouldn't be all that tough, I guess, but
 it would be a nuisance.   You can set a breakpoint given a function and
@@ -348,11 +347,6 @@
 	You can use the set command to set more or less anything.  Note
 however that you cannot use enumerated types on the RHS of the expression.
 
-	Finally, type casts are not yet supported in the expression
-handling.  There is sufficient information stored internally to be
-able to handle this - the main challenge is that the parser would
-need to be fixed to correctly parse the type cast.
-
 *******************************************************************
 
 
diff --git a/debugger/TODO b/debugger/TODO
index 3544b12..c527b922 100644
--- a/debugger/TODO
+++ b/debugger/TODO
@@ -3,10 +3,9 @@
 possible to me right now.   In no particular order.  If someone else
 wants to dig in, feel free.
 
-1) Some kind of watchpoint capability.  Pretty easy once we have a
-	single step capability, but we end up running the program
-	really slowly one instruction at a time.  Use hardware debug
-	registers for this???
+1) Some kind of watchpoint capability.  Pretty easy, but we end up
+        running the program really slowly one instruction at a time.  
+	Use hardware debug registers for this (much harder)???
 
 2) Some kind of .wdbinit file.
 
@@ -31,14 +30,6 @@
 8) Some of the newer displays are still a little bit sparse on information.
 	Make these more like gdb.
 
-9) Don't bother to disassemble an instruction when we stop at a breakpoint
-	and if we have a valid source line we are displaying.
-
-10) Add support for '/i', etc in display command.  Make sure 'display/i $eip'
-	does the correct thing, and then skip automatic disassembly completely.
-
-11)	Limit amount of information displayed with print command.
-
-12)	Make sure operator precedence works OK.
+9) Make sure operator precedence works OK.
 
 ****************
diff --git a/debugger/break.c b/debugger/break.c
index 5cf164f..d84427d 100644
--- a/debugger/break.c
+++ b/debugger/break.c
@@ -252,6 +252,13 @@
         fprintf( stderr, "Invalid breakpoint number %d\n", num );
         return;
     }
+
+    if( breakpoints[num].condition != NULL )
+      {
+	DEBUG_FreeExpr(breakpoints[num].condition);
+	breakpoints[num].condition = NULL;
+      }
+
     breakpoints[num].enabled = FALSE;
     breakpoints[num].in_use  = FALSE;
     breakpoints[num].skipcount = 0;
diff --git a/debugger/dbg.y b/debugger/dbg.y
index 8db0885..f79a3ff 100644
--- a/debugger/dbg.y
+++ b/debugger/dbg.y
@@ -41,6 +41,7 @@
     int              integer;
     struct list_id   listing;
     struct expr *    expression;
+    struct datatype * type;
 }
 
 %token tCONT tSTEP tLIST tNEXT tQUIT tHELP tBACKTRACE tINFO tWALK tUP tDOWN
@@ -48,12 +49,15 @@
 %token tCLASS tMODULE tSTACK tSEGMENTS tREGS tWND tQUEUE tLOCAL
 %token tEOL tSTRING
 %token tFRAME tSHARE tCOND tDISPLAY tUNDISPLAY
-%token tSTEPI tNEXTI tFINISH tSHOW tDIR 
+%token tSTEPI tNEXTI tFINISH tSHOW tDIR
 %token <string> tPATH
 %token <string> tIDENTIFIER tSTRING
 %token <integer> tNUM tFORMAT
 %token <reg> tREG
 
+%token tCHAR tSHORT tINT tLONG tFLOAT tDOUBLE tUNSIGNED tSIGNED 
+%token tSTRUCT tUNION tENUM
+
 /* %left ',' */
 /* %left '=' OP_OR_EQUAL OP_XOR_EQUAL OP_AND_EQUAL OP_SHL_EQUAL \
          OP_SHR_EQUAL OP_PLUS_EQUAL OP_MINUS_EQUAL \
@@ -66,14 +70,15 @@
 %left '&'
 %left OP_EQ OP_NE
 %left '<' '>' OP_LE OP_GE
-%left OP_SHL OP_SHR OP_DRF
+%left OP_SHL OP_SHR
 %left '+' '-'
 %left '*' '/' '%'
 %left OP_SIGN '!' '~' OP_DEREF /* OP_INC OP_DEC OP_ADDR */
-%left '.' '['
+%left '.' '[' OP_DRF
 %nonassoc ':'
 
-%type <expression> expr lval lvalue
+%type <expression> expr lval lvalue 
+%type <type> type_cast type_expr
 %type <address> expr_addr lval_addr
 %type <integer> expr_value
 %type <string> pathname
@@ -129,7 +134,9 @@
     | tSHOW tDIR tEOL	       { DEBUG_ShowDir(); }
     | tDIR pathname tEOL       { DEBUG_AddPath( $2 ); }
     | tDIR tEOL		       { DEBUG_NukePath(); }
-    | tDISPLAY expr tEOL       { DEBUG_AddDisplay($2); }
+    | tDISPLAY tEOL	       { DEBUG_InfoDisplay(); }
+    | tDISPLAY expr tEOL       { DEBUG_AddDisplay($2, 1, 0); }
+    | tDISPLAY tFORMAT expr tEOL { DEBUG_AddDisplay($3, $2 >> 8, $2 & 0xff); }
     | tDELETE tDISPLAY tNUM tEOL { DEBUG_DelDisplay( $3 ); }
     | tDELETE tDISPLAY tEOL    { DEBUG_DelDisplay( -1 ); }
     | tUNDISPLAY tNUM tEOL     { DEBUG_DelDisplay( $2 ); }
@@ -257,6 +264,30 @@
     | tWALK tWND tEOL           { WIN_WalkWindows( 0, 0 ); }
     | tWALK tWND tNUM tEOL      { WIN_WalkWindows( $3, 0 ); }
 
+
+type_cast: 
+      '(' type_expr ')'		{ $$ = $2; }
+
+type_expr:
+      type_expr '*'		{ $$ = DEBUG_FindOrMakePointerType($1); }
+    |  tINT			{ $$ = DEBUG_TypeCast(BASIC, "int"); }
+    | tCHAR			{ $$ = DEBUG_TypeCast(BASIC, "char"); }
+    | tLONG tINT		{ $$ = DEBUG_TypeCast(BASIC, "long int"); }
+    | tUNSIGNED tINT		{ $$ = DEBUG_TypeCast(BASIC, "unsigned int"); }
+    | tLONG tUNSIGNED tINT	{ $$ = DEBUG_TypeCast(BASIC, "long unsigned int"); }
+    | tLONG tLONG tINT		{ $$ = DEBUG_TypeCast(BASIC, "long long int"); }
+    | tLONG tLONG tUNSIGNED tINT { $$ = DEBUG_TypeCast(BASIC, "long long unsigned int"); }
+    | tSHORT tINT		{ $$ = DEBUG_TypeCast(BASIC, "short int"); }
+    | tSHORT tUNSIGNED tINT	{ $$ = DEBUG_TypeCast(BASIC, "short unsigned int"); }
+    | tSIGNED tCHAR		{ $$ = DEBUG_TypeCast(BASIC, "signed char"); }
+    | tUNSIGNED tCHAR		{ $$ = DEBUG_TypeCast(BASIC, "unsigned char"); }
+    | tFLOAT			{ $$ = DEBUG_TypeCast(BASIC, "float"); }
+    | tDOUBLE			{ $$ = DEBUG_TypeCast(BASIC, "double"); }
+    | tLONG tDOUBLE		{ $$ = DEBUG_TypeCast(BASIC, "long double"); }
+    | tSTRUCT tIDENTIFIER	{ $$ = DEBUG_TypeCast(STRUCT, $2); }
+    | tUNION tIDENTIFIER	{ $$ = DEBUG_TypeCast(STRUCT, $2); }
+    | tENUM tIDENTIFIER		{ $$ = DEBUG_TypeCast(ENUM, $2); }
+
 expr_addr:
     expr			 { $$ = DEBUG_EvalExpr($1) }
 
@@ -310,6 +341,7 @@
     | '(' expr ')'               { $$ = $2; }
     | '*' expr %prec OP_DEREF    { $$ = DEBUG_UnopExpr(EXP_OP_DEREF, $2); }
     | '&' expr %prec OP_DEREF    { $$ = DEBUG_UnopExpr(EXP_OP_ADDR, $2); }
+    | type_cast expr %prec OP_DEREF { $$ = DEBUG_TypeCastExpr($1, $2); } 
 	
 /*
  * The lvalue rule builds an expression tree.  This is a limited form
@@ -460,15 +492,18 @@
 	    DEBUG_SilentBackTrace();
 	}
 
-        /* Show where we crashed */
-        curr_frame = 0;
-        DEBUG_PrintAddress( &addr, dbg_mode, TRUE );
-        fprintf(stderr,":  ");
-        if (DBG_CHECK_READ_PTR( &addr, 1 ))
-        {
-            DEBUG_Disasm( &addr, TRUE );
-            fprintf(stderr,"\n");
-        }
+	if( signal != SIGTRAP )
+	  {
+	    /* Show where we crashed */
+	    curr_frame = 0;
+	    DEBUG_PrintAddress( &addr, dbg_mode, TRUE );
+	    fprintf(stderr,":  ");
+	    if (DBG_CHECK_READ_PTR( &addr, 1 ))
+	      {
+		DEBUG_Disasm( &addr, TRUE );
+		fprintf(stderr,"\n");
+	      }
+	  }
 
         ret_ok = 0;
         do
diff --git a/debugger/dbgmain.c b/debugger/dbgmain.c
index 9d3fb8c..7c1992b 100644
--- a/debugger/dbgmain.c
+++ b/debugger/dbgmain.c
@@ -6,15 +6,16 @@
 #include <signal.h>
 
 #include <ldt.h>
-#include <windows.h>
-#include <toolhelp.h>
-#include <module.h>
-#include <debugger.h>
-#include <class.h>
+#include "windows.h"
+#include "toolhelp.h"
+#include "module.h"
+#include "debugger.h"
+#include "class.h"
 #include <X11/Xlib.h>
 
 #include "debugger.h"
 #include "peexe.h"
+#include "pe_image.h"
 
 ldt_copy_entry ldt_copy[LDT_SIZE];
 unsigned char ldt_flags_copy[LDT_SIZE];
@@ -171,7 +172,7 @@
 	int				  dbg_size;
 	struct PE_Debug_dir		* dbgdir;
 	struct pe_data			* pe;
-        struct pe_segment_table         * sectp;
+        LPIMAGE_SECTION_HEADER            sectp;
 	int				  nsect;
 	short int			  dbg_index;			
 	char				  loaded;
@@ -190,7 +191,7 @@
   struct deferred_debug_info deefer;
   struct PE_Debug_dir	dinfo;
   struct CodeViewDebug cdebug;
-  struct pe_segment_table sects[10];
+  IMAGE_SECTION_HEADER  sects[10];
 
   memset(&deefer, 0, sizeof(deefer));
   memset(&dinfo, 0, sizeof(dinfo));
@@ -201,7 +202,7 @@
   dinfo.timestamp = 812932395;
   cdebug.cv_timestamp = 833392137  /* 841951397 */;
   deefer.dbgdir = &dinfo;
-  deefer.sectp = &sects;
+  deefer.sectp = sects;
   deefer.nsect = 10;
 
   DEBUG_InitTypes();
diff --git a/debugger/debug.l b/debugger/debug.l
index 5f6cce2..d33b4c0 100644
--- a/debugger/debug.l
+++ b/debugger/debug.l
@@ -113,7 +113,7 @@
 <INITIAL>list|lis|li|l			{ BEGIN(PATH_EXPECTED); return tLIST; }
 <INITIAL>enable|enabl|enab|ena		{ BEGIN(NOCMD); return tENABLE;}
 <INITIAL>disable|disabl|disab|disa|dis	{ BEGIN(NOCMD); return tDISABLE; }
-<INITIAL,INFO_CMD,DEL_CMD>display|displa|displ|disp	{ BEGIN(NOCMD); return tDISPLAY; }
+<INITIAL,INFO_CMD,DEL_CMD>display|displa|displ|disp	{ BEGIN(FORMAT_EXPECTED); return tDISPLAY; }
 <INITIAL>undisplay|undispla|undispl|undisp|undis|undi|und	{ BEGIN(NOCMD); return tUNDISPLAY; }
 <INITIAL>delete|delet|dele|del		{ BEGIN(DEL_CMD); return tDELETE; }
 <INITIAL>quit|qui|qu|q			{ BEGIN(NOCMD); return tQUIT; }
@@ -155,11 +155,22 @@
 <INITIAL,SHOW_CMD>directories|directorie|directori|director|directo|direct|direc|direc|dir { 
 			BEGIN(PATH_EXPECTED); return tDIR; }
 
+char					{ return tCHAR; }
+short					{ return tSHORT; }
+int					{ return tINT; }
+long					{ return tLONG; }
+float					{ return tFLOAT; }
+double					{ return tDOUBLE; }
+unsigned				{ return tUNSIGNED; }
+signed					{ return tSIGNED; }
+struct					{ return tSTRUCT; }
+union					{ return tUNION; }
+enum					{ return tENUM; }
+
 {IDENTIFIER}	{ yylval.string = make_symbol(yytext); return tIDENTIFIER; }
 
 <PATH_EXPECTED>{PATHNAME}	{ yylval.string = make_symbol(yytext); return tPATH; }
 
-
 [ \t]+        /* Eat up whitespace */
 
 .		{ if (syntax_error == 0)
diff --git a/debugger/display.c b/debugger/display.c
index b170026..fd7e8c6 100644
--- a/debugger/display.c
+++ b/debugger/display.c
@@ -20,10 +20,18 @@
 #include <stdarg.h>
 
 #define MAX_DISPLAY 25
-static struct expr * displaypoints[MAX_DISPLAY];
+
+struct display
+{
+  struct expr *	exp;
+  int		count;
+  char		format;
+};
+
+static struct display displaypoints[MAX_DISPLAY];
 
 int
-DEBUG_AddDisplay(struct expr * exp)
+DEBUG_AddDisplay(struct expr * exp, int count, char format)
 {
   int i;
 
@@ -32,9 +40,11 @@
    */
   for(i=0; i < MAX_DISPLAY; i++ )
     {
-      if( displaypoints[i] == NULL )
+      if( displaypoints[i].exp == NULL )
 	{
-	  displaypoints[i] = DEBUG_CloneExpr(exp);
+	  displaypoints[i].exp = DEBUG_CloneExpr(exp);
+	  displaypoints[i].count  = count;
+	  displaypoints[i].format = format;
 	  break;
 	}
     }
@@ -52,10 +62,10 @@
    */
   for(i=0; i < MAX_DISPLAY; i++ )
     {
-      if( displaypoints[i] != NULL )
+      if( displaypoints[i].exp != NULL )
 	{
 	  fprintf(stderr, "%d : ", i+1);
-	  DEBUG_DisplayExpr(displaypoints[i]);
+	  DEBUG_DisplayExpr(displaypoints[i].exp);
 	  fprintf(stderr, "\n");
 	}
     }
@@ -74,22 +84,33 @@
    */
   for(i=0; i < MAX_DISPLAY; i++ )
     {
-      if( displaypoints[i] != NULL )
+      if( displaypoints[i].exp != NULL )
 	{
-	  addr = DEBUG_EvalExpr(displaypoints[i]);
+	  addr = DEBUG_EvalExpr(displaypoints[i].exp);
 	  if( addr.type == NULL )
 	    {
 	      fprintf(stderr, "Unable to evaluate expression ");
-	      DEBUG_DisplayExpr(displaypoints[i]);
+	      DEBUG_DisplayExpr(displaypoints[i].exp);
 	      fprintf(stderr, "\nDisabling...\n");
 	      DEBUG_DelDisplay(i);
 	    }
 	  else
 	    {
 	      fprintf(stderr, "%d  : ", i + 1);
-	      DEBUG_DisplayExpr(displaypoints[i]);
+	      DEBUG_DisplayExpr(displaypoints[i].exp);
 	      fprintf(stderr, " = ");
-	      DEBUG_Print( &addr, 1, 0, 0);
+	      if( displaypoints[i].format == 'i' )
+		{
+		  DEBUG_ExamineMemory( &addr, 
+			       displaypoints[i].count, 
+			       displaypoints[i].format);
+		}
+	      else
+		{
+		  DEBUG_Print( &addr, 
+			       displaypoints[i].count, 
+			       displaypoints[i].format, 0);
+		}
 	    }
 	}
     }
@@ -111,17 +132,17 @@
     {
       for(i=0; i < MAX_DISPLAY; i++ )
 	{
-	  if( displaypoints[i] != NULL )
+	  if( displaypoints[i].exp != NULL )
 	    {
-	      DEBUG_FreeExpr(displaypoints[i]);
-	      displaypoints[i] = NULL;
+	      DEBUG_FreeExpr(displaypoints[i].exp);
+	      displaypoints[i].exp = NULL;
 	    }
 	}
     }
-  else if( displaypoints[displaynum - 1] != NULL )
+  else if( displaypoints[displaynum - 1].exp != NULL )
     {
-      DEBUG_FreeExpr(displaypoints[displaynum - 1]);
-      displaypoints[displaynum - 1] = NULL;
+      DEBUG_FreeExpr(displaypoints[displaynum - 1].exp);
+      displaypoints[displaynum - 1].exp = NULL;
     }
   return TRUE;
 }
diff --git a/debugger/expr.c b/debugger/expr.c
index 4bf78ef..6ef8d37 100644
--- a/debugger/expr.c
+++ b/debugger/expr.c
@@ -70,6 +70,12 @@
 
     struct
     {
+      struct datatype * cast;
+      struct expr     * expr;
+    } cast;
+
+    struct
+    {
       struct expr * exp1;
       const char * element_name;
       int result;
@@ -103,6 +109,7 @@
 #define EXPR_TYPE_ARRAY		8
 #define EXPR_TYPE_CALL		9
 #define EXPR_TYPE_STRING	10
+#define EXPR_TYPE_CAST		11
 
 static char expr_list[4096];
 static int next_expr_free = 0;
@@ -132,6 +139,18 @@
   next_expr_free = 0;
 }
 
+struct expr *
+DEBUG_TypeCastExpr(struct datatype * dt, struct expr * exp)
+{
+  struct expr * ex;
+
+  ex = DEBUG_GetFreeExpr();
+
+  ex->type        = EXPR_TYPE_CAST;
+  ex->un.cast.cast = dt;
+  ex->un.cast.expr = exp;
+  return ex;
+}
 
 struct expr *
 DEBUG_RegisterExpr(enum debug_regs regno)
@@ -294,6 +313,10 @@
 
   switch(exp->type)
     {
+    case EXPR_TYPE_CAST:
+      rtn = DEBUG_EvalExpr(exp->un.cast.expr);
+      rtn.type = exp->un.cast.cast;
+      break;
     case EXPR_TYPE_STRING:
       rtn.type = DEBUG_TypeString;
       rtn.off = (unsigned int) &exp->un.string.str;
@@ -620,6 +643,13 @@
 
   switch(exp->type)
     {
+    case EXPR_TYPE_CAST:
+      fprintf(stderr, "((");
+      DEBUG_PrintTypeCast(exp->un.cast.cast);
+      fprintf(stderr, ")");
+      DEBUG_DisplayExpr(exp->un.cast.expr);
+      fprintf(stderr, ")");
+      break;
     case EXPR_TYPE_REGISTER:
       DEBUG_PrintRegister(exp->un.rgister.reg);
       break;
@@ -780,6 +810,9 @@
 
   switch(exp->type)
     {
+    case EXPR_TYPE_CAST:
+      rtn->un.cast.expr = DEBUG_CloneExpr(exp->un.cast.expr);
+      break;
     case EXPR_TYPE_REGISTER:
     case EXPR_TYPE_US_CONST:
     case EXPR_TYPE_CONST:
@@ -834,6 +867,9 @@
 
   switch(exp->type)
     {
+    case EXPR_TYPE_CAST:
+      DEBUG_FreeExpr(exp->un.cast.expr);
+      break;
     case EXPR_TYPE_REGISTER:
     case EXPR_TYPE_US_CONST:
     case EXPR_TYPE_CONST:
diff --git a/debugger/hash.c b/debugger/hash.c
index 2684ea0..20f3e64 100644
--- a/debugger/hash.c
+++ b/debugger/hash.c
@@ -18,6 +18,9 @@
 #include "xmalloc.h"
 
 #define NR_NAME_HASH 16384
+#ifndef PATH_MAX
+#define PATH_MAX _MAX_PATH
+#endif
 
 static char * reg_name[] =
 {
diff --git a/debugger/info.c b/debugger/info.c
index 6c5f4de..dd5b76a 100644
--- a/debugger/info.c
+++ b/debugger/info.c
@@ -17,10 +17,10 @@
  */
 void DEBUG_PrintBasic( const DBG_ADDR *addr, int count, char format )
 {
-  char * default_format;
+  char        * default_format;
   long long int value;
 
-    if( addr->type == NULL )
+  if( addr->type == NULL )
     {
       fprintf(stderr, "Unable to evaluate expression\n");
       return;
@@ -32,16 +32,22 @@
   switch(format)
     {
     case 'x':
-      if (addr->seg) fprintf( stderr, "0x%04lx", (long unsigned int) value );
-      else fprintf( stderr, "0x%08lx", (long unsigned int) value );
+      if (addr->seg) 
+	{
+	  DEBUG_nchar += fprintf( stderr, "0x%04lx", (long unsigned int) value );
+	}
+      else 
+	{
+	  DEBUG_nchar += fprintf( stderr, "0x%08lx", (long unsigned int) value );
+	}
       break;
       
     case 'd':
-      fprintf( stderr, "%ld\n", (long int) value );
+      DEBUG_nchar += fprintf( stderr, "%ld\n", (long int) value );
       break;
       
     case 'c':
-      fprintf( stderr, "%d = '%c'",
+      DEBUG_nchar += fprintf( stderr, "%d = '%c'",
 	       (char)(value & 0xff), (char)(value & 0xff) );
       break;
       
@@ -53,11 +59,10 @@
     case 0:
       if( default_format != NULL )
 	{
-	  fprintf( stderr, default_format, value );
+	  DEBUG_nchar += fprintf( stderr, default_format, value );
 	}
       break;
     }
-
 }
 
 
diff --git a/debugger/msc.c b/debugger/msc.c
index 1c1817b..90bf0fd 100644
--- a/debugger/msc.c
+++ b/debugger/msc.c
@@ -512,9 +512,9 @@
 	char				* module_name;
 	char				* dbg_info;
 	int				  dbg_size;
-	struct PE_Debug_dir		* dbgdir;
+	LPIMAGE_DEBUG_DIRECTORY           dbgdir;
 	struct pe_data			* pe;
-        struct pe_segment_table         * sectp;
+        LPIMAGE_SECTION_HEADER	          sectp;
 	int				  nsect;
 	short int			  dbg_index;			
 	char				  loaded;
@@ -747,17 +747,24 @@
 	    }
 	  memset(symname, 0, sizeof(symname));
 	  memcpy(symname, type->structure.name, type->structure.namelen);
-	  typeptr = DEBUG_NewDataType(STRUCT, symname);
+	  if( strcmp(symname, "__unnamed") == 0 )
+	    {
+	      typeptr = DEBUG_NewDataType(STRUCT, NULL);
+	    }
+	  else
+	    {
+	      typeptr = DEBUG_NewDataType(STRUCT, symname);
+	    }
 	  cv_defined_types[curr_type - 0x1000] = typeptr;
 
 	  /*
 	   * Now copy the relevant bits from the fieldlist that we specified.
 	   */
 	  subtype = DEBUG_GetCVType(type->structure.fieldlist);
-	  DEBUG_SetStructSize(typeptr, type->structure.structlen);
 
 	  if( subtype != NULL )
 	    {
+	      DEBUG_SetStructSize(typeptr, type->structure.structlen);
 	      DEBUG_CopyFieldlist(typeptr, subtype);
 	    }
 	  break;
@@ -773,17 +780,26 @@
 	    }
 	  memset(symname, 0, sizeof(symname));
 	  memcpy(symname, type->t_union.name, type->t_union.namelen);
-	  typeptr = DEBUG_NewDataType(STRUCT, symname);
+
+	  if( strcmp(symname, "__unnamed") == 0 )
+	    {
+	      typeptr = DEBUG_NewDataType(STRUCT, NULL);
+	    }
+	  else
+	    {
+	      typeptr = DEBUG_NewDataType(STRUCT, symname);
+	    }
+
 	  cv_defined_types[curr_type - 0x1000] = typeptr;
 
 	  /*
 	   * Now copy the relevant bits from the fieldlist that we specified.
 	   */
 	  subtype = DEBUG_GetCVType(type->t_union.field);
-	  DEBUG_SetStructSize(typeptr, type->t_union.un_len);
 
 	  if( subtype != NULL )
 	    {
+	      DEBUG_SetStructSize(typeptr, type->t_union.un_len);
 	      DEBUG_CopyFieldlist(typeptr, subtype);
 	    }
 	  break;
@@ -874,14 +890,14 @@
   int			  has_codeview = FALSE;
   int			  rtn = FALSE;
   int			  orig_size;
-  struct PE_Debug_dir	* dbgptr;
+  LPIMAGE_DEBUG_DIRECTORY dbgptr;
   struct deferred_debug_info * deefer;
 
   orig_size = size;
-  dbgptr = (struct PE_Debug_dir *) (load_addr + v_addr);
+  dbgptr = (LPIMAGE_DEBUG_DIRECTORY) (load_addr + v_addr);
   for(; size > 0; size -= sizeof(*dbgptr), dbgptr++ )
     {
-      switch(dbgptr->type)
+      switch(dbgptr->Type)
 	{
 	case IMAGE_DEBUG_TYPE_CODEVIEW:
 	case IMAGE_DEBUG_TYPE_MISC:
@@ -891,10 +907,10 @@
     }
 
   size = orig_size;
-  dbgptr = (struct PE_Debug_dir *) (load_addr + v_addr);
+  dbgptr = (LPIMAGE_DEBUG_DIRECTORY) (load_addr + v_addr);
   for(; size > 0; size -= sizeof(*dbgptr), dbgptr++ )
     {
-      switch(dbgptr->type)
+      switch(dbgptr->Type)
 	{
 	case IMAGE_DEBUG_TYPE_COFF:
 	  /*
@@ -921,8 +937,8 @@
 	   * means that this entry points to a .DBG file.  Otherwise,
 	   * it just points to itself, and we can ignore this.
 	   */
-	  if(    (dbgptr->type == IMAGE_DEBUG_TYPE_MISC)
-	      && (pe->pe_header->coff.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) == 0 )
+	  if(    (dbgptr->Type == IMAGE_DEBUG_TYPE_MISC)
+	      && (pe->pe_header->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) == 0 )
 	    {
 	      break;
 	    }
@@ -938,9 +954,9 @@
 	   * upon the type, but this is always enough so we are able
 	   * to proceed if we know what we need to do next.
 	   */
-	  deefer->dbg_size = dbgptr->dbgsize;
-	  deefer->dbg_info = (char *) xmalloc(dbgptr->dbgsize);
-	  lseek(fd, dbgptr->dbgoff, SEEK_SET);
+	  deefer->dbg_size = dbgptr->SizeOfData;
+	  deefer->dbg_info = (char *) xmalloc(dbgptr->SizeOfData);
+	  lseek(fd, dbgptr->PointerToRawData, SEEK_SET);
 	  read(fd, deefer->dbg_info, deefer->dbg_size);
 
 	  deefer->load_addr = (char *) load_addr;
@@ -951,7 +967,7 @@
 	  deefer->module_name = xstrdup(DEBUG_curr_module);
 
 	  deefer->sectp = pe->pe_seg;
-	  deefer->nsect = pe->pe_header->coff.NumberOfSections;
+	  deefer->nsect = pe->pe_header->FileHeader.NumberOfSections;
 
 	  dbglist = deefer;
 	  break;
@@ -1538,7 +1554,7 @@
   DBG_ADDR		  new_addr;
   int			  nsect;
   union any_size	  ptr;
-  struct pe_segment_table * sectp;
+  IMAGE_SECTION_HEADER  * sectp;
   union	codeview_symbol	* sym;
   char			  symname[PATH_MAX];
   struct name_hash	* thunk_sym = NULL;
@@ -1601,7 +1617,7 @@
 	  new_addr.seg = 0;
 	  new_addr.type = DEBUG_GetCVType(sym->data.symtype);
 	  new_addr.off = (unsigned int) deefer->load_addr + 
-	    sectp[sym->data.seg - 1].Virtual_Address + 
+	    sectp[sym->data.seg - 1].VirtualAddress + 
 	    sym->data.offset;
 	  DEBUG_AddSymbol( symname, &new_addr, NULL, SYM_WIN32 | SYM_DATA );
 	  break;
@@ -1615,7 +1631,7 @@
 	  new_addr.seg = 0;
 	  new_addr.type = NULL;
 	  new_addr.off = (unsigned int) deefer->load_addr + 
-	    sectp[sym->thunk.segment - 1].Virtual_Address + 
+	    sectp[sym->thunk.segment - 1].VirtualAddress + 
 	    sym->thunk.offset;
 	  thunk_sym = DEBUG_AddSymbol( symname, &new_addr, NULL, 
 				       SYM_WIN32 | SYM_FUNC);
@@ -1630,7 +1646,7 @@
 	  new_addr.seg = 0;
 	  new_addr.type = DEBUG_GetCVType(sym->proc.proctype);
 	  new_addr.off = (unsigned int) deefer->load_addr + 
-	    sectp[sym->proc.segment - 1].Virtual_Address + 
+	    sectp[sym->proc.segment - 1].VirtualAddress + 
 	    sym->proc.offset;
 	  /*
 	   * See if we can find a segment that this goes with.  If so,
@@ -1640,10 +1656,10 @@
 	  for(i=0; linetab[i].linetab != NULL; i++)
 	    {
 	      if(     ((unsigned int) deefer->load_addr 
-		       + sectp[linetab[i].segno - 1].Virtual_Address 
+		       + sectp[linetab[i].segno - 1].VirtualAddress 
 		       + linetab[i].start <= new_addr.off)
 		  &&  ((unsigned int) deefer->load_addr 
-		       + sectp[linetab[i].segno - 1].Virtual_Address 
+		       + sectp[linetab[i].segno - 1].VirtualAddress 
 		       + linetab[i].end > new_addr.off) )
 		{
 		  break;
@@ -2119,8 +2135,8 @@
   int				j;
   struct codeview_linetab_hdr * linetab;
   int				nsect;
-  struct PE_DBG_FileHeader    * pdbg = NULL;
-  struct pe_segment_table     * sectp;
+  LPIMAGE_SEPARATE_DEBUG_HEADER pdbg = NULL;
+  IMAGE_SECTION_HEADER        * sectp;
   struct stat			statbuf;
   int				status;
   
@@ -2148,9 +2164,9 @@
   addr = mmap(0, statbuf.st_size, PROT_READ, 
 	      MAP_PRIVATE, fd, 0);
 
-  pdbg = (struct PE_DBG_FileHeader *) addr;
+  pdbg = (LPIMAGE_SEPARATE_DEBUG_HEADER) addr;
 
-  if( pdbg->TimeDateStamp != deefer->dbgdir->timestamp )
+  if( pdbg->TimeDateStamp != deefer->dbgdir->TimeDateStamp )
     {
       fprintf(stderr, "Warning - %s has incorrect internal timestamp\n",
 	      filename);
@@ -2160,10 +2176,10 @@
   fprintf(stderr, "Processing symbols from %s...\n", filename);
 
   dbghdr = (struct PE_Debug_dir *) (  addr + sizeof(*pdbg) 
-		 + pdbg->NumberOfSections * sizeof(struct pe_segment_table) 
+		 + pdbg->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) 
 		 + pdbg->ExportedNamesSize);
 
-  sectp = (struct pe_segment_table *) ((char *) pdbg + sizeof(*pdbg));
+  sectp = (LPIMAGE_SECTION_HEADER) ((char *) pdbg + sizeof(*pdbg));
   nsect = pdbg->NumberOfSections;
 
   for( i=0; i < pdbg->DebugDirectorySize / sizeof(*pdbg); i++, dbghdr++ )
@@ -2300,7 +2316,7 @@
 	  last_proc = deefer->dbg_index;
 	}
 
-      switch(deefer->dbgdir->type)
+      switch(deefer->dbgdir->Type)
 	{
 	case IMAGE_DEBUG_TYPE_COFF:
 	  /*
diff --git a/debugger/registers.c b/debugger/registers.c
index 7c68f6a..5ed74dd 100644
--- a/debugger/registers.c
+++ b/debugger/registers.c
@@ -188,7 +188,7 @@
 #ifdef GS_sig
     GS_sig(sigcontext)  = GS_reg(&DEBUG_context);
 #else
-    __asm__("movw %w0,%%gs"::"r" (FS_reg(&DEBUG_context)));
+    __asm__("movw %w0,%%gs"::"r" (GS_reg(&DEBUG_context)));
 #endif
 }
 
diff --git a/debugger/source.c b/debugger/source.c
index d80d386..4ece937 100644
--- a/debugger/source.c
+++ b/debugger/source.c
@@ -93,7 +93,7 @@
 }
 
 static
-void
+int
 DEBUG_DisplaySource(char * sourcefile, int start, int end)
 {
   char			      * addr;
@@ -103,6 +103,7 @@
   struct open_filelist	      * ol;
   int				nlines;
   char			      * pnt;
+  int				rtn;
   struct searchlist	      * sl;
   struct stat			statbuf;
   int				status;
@@ -217,7 +218,7 @@
 		  ol->linelist = NULL;
 		  ofiles = ol;
 		  fprintf(stderr,"Unable to open file %s\n", tmppath);
-		  return;
+		  return FALSE;
 		}
 	    }
 	}
@@ -239,13 +240,13 @@
       fd = open(tmppath, O_RDONLY);
       if( fd == -1 )
 	{
-	  return;
+	  return FALSE;
 	}
 
       addr = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
       if( addr == (char *) -1 )
 	{
-	  return;
+	  return FALSE;
 	}
 
       /*
@@ -285,19 +286,20 @@
       fd = open(ol->real_path, O_RDONLY);
       if( fd == -1 )
 	{
-	  return;
+	  return FALSE;
 	}
       
       addr = mmap(0, ol->size, PROT_READ, MAP_PRIVATE, fd, 0);
       if( addr == (char *) -1 )
 	{
-	  return;
+	  return FALSE;
 	}
     }
   
   /*
    * All we need to do is to display the source lines here.
    */
+  rtn = FALSE;
   for(i=start - 1; i <= end - 1; i++)
     {
       if( i < 0 || i >= ol->nlines - 1)
@@ -305,6 +307,7 @@
 	  continue;
 	}
 
+      rtn = TRUE;
       memset(&buffer, 0, sizeof(buffer));
       if( ol->linelist[i+1] != ol->linelist[i] )
 	{
@@ -317,6 +320,8 @@
   munmap(addr, ol->size);
   close(fd);
 
+  return rtn;
+
 }
 
 void
@@ -324,6 +329,7 @@
 			 int delta)
 {
   int    end;
+  int    rtn;
   int    start;
   char * sourcefile;
 
@@ -406,7 +412,7 @@
   /*
    * Now call this function to do the dirty work.
    */
-  DEBUG_DisplaySource(sourcefile, start, end);
+  rtn = DEBUG_DisplaySource(sourcefile, start, end);
 
   if( sourcefile != (char *) &DEBUG_current_sourcefile )
     {
diff --git a/debugger/stabs.c b/debugger/stabs.c
index 0c1ddf1..a52c467 100644
--- a/debugger/stabs.c
+++ b/debugger/stabs.c
@@ -75,6 +75,44 @@
   unsigned long n_value;
 };
 
+/*
+ * This is used to keep track of known datatypes so that we don't redefine
+ * them over and over again.  It sucks up lots of memory otherwise.
+ */
+struct known_typedef
+{
+  struct known_typedef * next;
+  char		       * name;
+  int			 ndefs;
+  struct datatype      * types[0];
+};
+
+#define NR_STAB_HASH 521
+
+struct known_typedef * ktd_head[NR_STAB_HASH];
+
+static unsigned int stab_hash( const char * name )
+{
+    unsigned int hash = 0;
+    unsigned int tmp;
+    const char * p;
+
+    p = name;
+
+    while (*p) 
+      {
+	hash = (hash << 4) + *p++;
+
+	if( (tmp = (hash & 0xf0000000)) )
+	  {
+	    hash ^= tmp >> 24;
+	  }
+	hash &= ~tmp;
+      }
+    return hash % NR_STAB_HASH;
+}
+
+
 static void stab_strcpy(char * dest, const char * source)
 {
   /*
@@ -89,6 +127,179 @@
   *dest++ = '\0';
 }
 
+#define MAX_TD_NESTING	128
+
+static
+int
+DEBUG_RegisterTypedef(const char * name, struct datatype ** types, int ndef)
+{
+  int			 hash;
+  struct known_typedef * ktd;
+
+  if( ndef == 1 )
+    {
+      return TRUE;
+    }
+
+  ktd = (struct known_typedef *) malloc(sizeof(struct known_typedef) 
+					+ ndef * sizeof(struct datatype *));
+  
+  hash = stab_hash(name);
+
+  ktd->name = xstrdup(name);
+  ktd->ndefs = ndef;
+  memcpy(&ktd->types[0], types, ndef * sizeof(struct datatype *));
+  ktd->next = ktd_head[hash];
+  ktd_head[hash] = ktd;
+
+  return TRUE;
+}
+
+static
+int
+DEBUG_HandlePreviousTypedef(const char * name, const char * stab)
+{
+  int			 count;
+  enum debug_type	 expect;
+  int			 hash;
+  struct known_typedef * ktd;
+  char		       * ptr;
+  char		       * tc;
+  int			 typenum;
+
+  hash = stab_hash(name);
+
+  for(ktd = ktd_head[hash]; ktd; ktd = ktd->next)
+    {
+      if(    (ktd->name[0] == name[0])
+	  && (strcmp(name, ktd->name) == 0) )
+	{
+	  break;
+	}
+    }
+
+  /*
+   * Didn't find it.  This must be a new one.
+   */
+  if( ktd == NULL )
+    {
+      return FALSE;
+    }
+
+  /*
+   * Examine the stab to make sure it has the same number of definitions.
+   */
+  count = 0;
+  for(ptr = strchr(stab, '='); ptr; ptr = strchr(ptr+1, '='))
+    {
+      if( count >= ktd->ndefs )
+	{
+	  return FALSE;
+	}
+
+      /*
+       * Make sure the types of all of the objects is consistent with
+       * what we have already parsed.
+       */
+      switch(ptr[1])
+	{
+	case '*':
+	  expect = POINTER;
+	  break;
+	case 's':
+	case 'u':
+	  expect = STRUCT;
+	  break;
+	case 'a':
+	  expect = ARRAY;
+	  break;
+	case '1':
+	case 'r':
+	  expect = BASIC;
+	  break;
+	case 'x':
+	  expect = STRUCT;
+	  break;
+	case 'e':
+	  expect = ENUM;
+	  break;
+	case 'f':
+	  expect = FUNC;
+	  break;
+	default:
+	  fprintf(stderr, "Unknown type.\n");
+          return FALSE;
+	}
+      if( expect != DEBUG_GetType(ktd->types[count]) )
+	{
+	  return FALSE;
+	}
+      count++;
+    }
+
+  if( ktd->ndefs != count )
+    {
+      return FALSE;
+    }
+
+  /*
+   * OK, this one is safe.  Go through, dig out all of the type numbers,
+   * and substitute the appropriate things.
+   */
+  count = 0;
+  for(ptr = strchr(stab, '='); ptr; ptr = strchr(ptr+1, '='))
+    {
+      /*
+       * Back up until we get to a non-numeric character.  This is the type
+       * number.
+       */
+      tc = ptr - 1;
+      while( *tc >= '0' && *tc <= '9' )
+	{
+	  tc--;
+	}
+      
+      typenum = atol(tc + 1);
+      if( num_stab_types <= typenum )
+	{
+	  num_stab_types = typenum + 32;
+	  stab_types = (struct datatype **) xrealloc(stab_types, 
+						     num_stab_types * sizeof(struct datatype *));
+	  if( stab_types == NULL )
+	    {
+	      return FALSE;
+	    }
+	}
+
+      stab_types[typenum] = ktd->types[count++];
+    }
+
+  return TRUE;
+}
+
+static int DEBUG_FreeRegisteredTypedefs()
+{
+  int			 count;
+  int			 j;
+  struct known_typedef * ktd;
+  struct known_typedef * next;
+
+  count = 0;
+  for(j=0; j < NR_STAB_HASH; j++ )
+    {
+      for(ktd = ktd_head[j]; ktd; ktd = next)
+	{
+	  count++;
+	  next = ktd->next;
+	  free(ktd->name);
+	  free(ktd);
+	}  
+      ktd_head[j] = NULL;
+    }
+
+  return TRUE;
+
+}
 
 static 
 int
@@ -96,21 +307,33 @@
 {
   int		    arrmax;
   int		    arrmin;
-  char * c;
+  char		  * c;
   struct datatype * curr_type;
   struct datatype * datatype;
+  struct datatype * curr_types[MAX_TD_NESTING];
   char	            element_name[1024];
+  int		    ntypes = 0;
   int		    offset;
+  const char	  * orig_typename;
   int		    rtn = FALSE;
   int		    size;
   char		  * tc;
   char		  * tc2;
   int		    typenum;
 
-  /*
-   * Go from back to front.  First we go through and figure out what type numbers
-   * we need, and register those types.  Then we go in and fill the details.
+  orig_typename = typename;
+
+  if( DEBUG_HandlePreviousTypedef(typename, ptr) == TRUE )
+    {
+      return TRUE;
+    }
+
+  /* 
+   * Go from back to front.  First we go through and figure out what
+   * type numbers we need, and register those types.  Then we go in
+   * and fill the details.  
    */
+
   for( c = strchr(ptr, '='); c != NULL; c = strchr(c + 1, '=') )
     {
       /*
@@ -134,31 +357,47 @@
 	    }
 	}
 
+      if( ntypes >= MAX_TD_NESTING )
+	{
+	  /*
+	   * If this ever happens, just bump the counter.
+	   */
+	  fprintf(stderr, "Typedef nesting overflow\n");
+	  return FALSE;
+	}
+
       switch(c[1])
 	{
 	case '*':
 	  stab_types[typenum] = DEBUG_NewDataType(POINTER, NULL);
+	  curr_types[ntypes++] = stab_types[typenum];
 	  break;
 	case 's':
 	case 'u':
 	  stab_types[typenum] = DEBUG_NewDataType(STRUCT, typename);
+	  curr_types[ntypes++] = stab_types[typenum];
 	  break;
 	case 'a':
 	  stab_types[typenum] = DEBUG_NewDataType(ARRAY, NULL);
+	  curr_types[ntypes++] = stab_types[typenum];
 	  break;
 	case '1':
 	case 'r':
 	  stab_types[typenum] = DEBUG_NewDataType(BASIC, typename);
+	  curr_types[ntypes++] = stab_types[typenum];
 	  break;
 	case 'x':
 	  stab_strcpy(element_name, c + 3);
 	  stab_types[typenum] = DEBUG_NewDataType(STRUCT, element_name);
+	  curr_types[ntypes++] = stab_types[typenum];
 	  break;
 	case 'e':
 	  stab_types[typenum] = DEBUG_NewDataType(ENUM, NULL);
+	  curr_types[ntypes++] = stab_types[typenum];
 	  break;
 	case 'f':
 	  stab_types[typenum] = DEBUG_NewDataType(FUNC, NULL);
+	  curr_types[ntypes++] = stab_types[typenum];
 	  break;
 	default:
 	  fprintf(stderr, "Unknown type.\n");
@@ -166,154 +405,184 @@
       typename = NULL;
     }
 
-     /*
-      * OK, now take a second sweep through.  Now we will be digging out the definitions
-      * of the various components, and storing them in the skeletons that we have already
-      * allocated.  We take a right-to left search as this is much easier to parse.
-      */
-  for( c = strrchr(ptr, '='); c != NULL; c = strrchr(ptr, '=') )
-    {
       /*
-       * Back up until we get to a non-numeric character.  This is the type
-       * number.
-       */
-      tc = c - 1;
-      while( *tc >= '0' && *tc <= '9' )
-	{
-	  tc--;
-	}
-      typenum = atol(tc + 1);
-      curr_type = stab_types[typenum];
+      * Now register the type so that if we encounter it again, we will know
+      * what to do.
+      */
+     DEBUG_RegisterTypedef(orig_typename, curr_types, ntypes);
 
-      switch(c[1])
-	{
-	case 'x':
-	  tc = c + 3;
-	  while( *tc != ':' )
-	    {
-	      tc ++;
-	    }
-	  tc++;
-	  if( *tc == '\0' )
-	    {
-	      *c = '\0';
-	    }
-	  else
-	    {
-	      strcpy(c, tc);
-	    }
+     /* 
+      * OK, now take a second sweep through.  Now we will be digging
+      * out the definitions of the various components, and storing
+      * them in the skeletons that we have already allocated.  We take
+      * a right-to left search as this is much easier to parse.  
+      */
+     for( c = strrchr(ptr, '='); c != NULL; c = strrchr(ptr, '=') )
+       {
+	 /*
+	  * Back up until we get to a non-numeric character.  This is the type
+	  * number.
+	  */
+	 tc = c - 1;
+	 while( *tc >= '0' && *tc <= '9' )
+	   {
+	     tc--;
+	   }
+	 typenum = atol(tc + 1);
+	 curr_type = stab_types[typenum];
+	 
+	 switch(c[1])
+	   {
+	   case 'x':
+	     tc = c + 3;
+	     while( *tc != ':' )
+	       {
+		 tc ++;
+	       }
+	     tc++;
+	     if( *tc == '\0' )
+	       {
+		 *c = '\0';
+	       }
+	     else
+	       {
+		 strcpy(c, tc);
+	       }
+	     
+	     break;
+	   case '*':
+	   case 'f':
+	     tc = c + 2;
+	     datatype = stab_types[strtol(tc, &tc, 10)];
+	     DEBUG_SetPointerType(curr_type, datatype);
+	     if( *tc == '\0' )
+	       {
+		 *c = '\0';
+	       }
+	     else
+	       {
+		 strcpy(c, tc);
+	       }
+	     break;
+	   case '1':
+	   case 'r':
+	     /*
+	      * We have already handled these above.
+	      */
+	     *c = '\0';
+	     break;
+	   case 'a':
+	     tc  = c + 5;
+	     arrmin = strtol(tc, &tc, 10);
+	     tc++;
+	     arrmax = strtol(tc, &tc, 10);
+	     tc++;
+	     datatype = stab_types[strtol(tc, &tc, 10)];
+	     if( *tc == '\0' )
+	       {
+		 *c = '\0';
+	       }
+	     else
+	       {
+		 strcpy(c, tc);
+	       }
+	     
+	     DEBUG_SetArrayParams(curr_type, arrmin, arrmax, datatype);
+	     break;
+	   case 's':
+	   case 'u':
+	     tc = c + 2;
+	     if( DEBUG_SetStructSize(curr_type, strtol(tc, &tc, 10)) == FALSE )
+	       {
+		 /*
+		  * We have already filled out this structure.  Nothing to do,
+		  * so just skip forward to the end of the definition.
+		  */
+		 while( tc[0] != ';' && tc[1] != ';' )
+		   {
+		     tc++;
+		   }
+		 
+		 tc += 2;
+		 
+		 if( *tc == '\0' )
+		   {
+		     *c = '\0';
+		   }
+		 else
+		   {
+		     strcpy(c, tc + 1);
+		   }
+		 continue;
+	       }
 
-	  break;
-	case '*':
-	case 'f':
-	  tc = c + 2;
-	  datatype = stab_types[strtol(tc, &tc, 10)];
-	  DEBUG_SetPointerType(curr_type, datatype);
-	  if( *tc == '\0' )
-	    {
-	      *c = '\0';
-	    }
-	  else
-	    {
-	      strcpy(c, tc);
-	    }
-	  break;
-	case '1':
-	case 'r':
-	  /*
-	   * We have already handled these above.
-	   */
-	  *c = '\0';
-	  break;
-	case 'a':
-	  tc  = c + 5;
- 	  arrmin = strtol(tc, &tc, 10);
-	  tc++;
- 	  arrmax = strtol(tc, &tc, 10);
-	  tc++;
-	  datatype = stab_types[strtol(tc, &tc, 10)];
-	  if( *tc == '\0' )
-	    {
-	      *c = '\0';
-	    }
-	  else
-	    {
-	      strcpy(c, tc);
-	    }
-	  
-	  DEBUG_SetArrayParams(curr_type, arrmin, arrmax, datatype);
-	  break;
-	case 's':
-	case 'u':
-	  tc = c + 2;
-	  DEBUG_SetStructSize(curr_type, strtol(tc, &tc, 10));
-	  /*
-	   * Now parse the individual elements of the structure/union.
-	   */
-	  while(*tc != ';')
-	    {
-	      tc2 = element_name;
-	      while(*tc != ':')
-		{
-		  *tc2++ = *tc++;
-		}
-	      tc++;
-	      *tc2++ = '\0';
-	      datatype = stab_types[strtol(tc, &tc, 10)];
-	      tc++;
-	      offset  = strtol(tc, &tc, 10);
-	      tc++;
-	      size  = strtol(tc, &tc, 10);
-	      tc++;
-	      DEBUG_AddStructElement(curr_type, element_name, datatype, offset, size);
-	    }
-	  if( *tc == '\0' )
-	    {
-	      *c = '\0';
-	    }
-	  else
-	    {
-	      strcpy(c, tc + 1);
-	    }
-	  break;
-	case 'e':
-	  tc = c + 2;
-	  /*
-	   * Now parse the individual elements of the structure/union.
-	   */
-	  while(*tc != ';')
-	    {
-	      tc2 = element_name;
-	      while(*tc != ':')
-		{
-		  *tc2++ = *tc++;
-		}
-	      tc++;
-	      *tc2++ = '\0';
-	      offset  = strtol(tc, &tc, 10);
-	      tc++;
-	      DEBUG_AddStructElement(curr_type, element_name, NULL, offset, 0);
-	    }
-	  if( *tc == '\0' )
-	    {
-	      *c = '\0';
-	    }
-	  else
-	    {
-	      strcpy(c, tc + 1);
-	    }
-	  break;
-	default:
-	  fprintf(stderr, "Unknown type.\n");
-	  break;
-	}
-    }
-
-  rtn = TRUE;
-
+	     /*
+	      * Now parse the individual elements of the structure/union.
+	      */
+	     while(*tc != ';')
+	       {
+		 tc2 = element_name;
+		 while(*tc != ':')
+		   {
+		     *tc2++ = *tc++;
+		   }
+		 tc++;
+		 *tc2++ = '\0';
+		 datatype = stab_types[strtol(tc, &tc, 10)];
+		 tc++;
+		 offset  = strtol(tc, &tc, 10);
+		 tc++;
+		 size  = strtol(tc, &tc, 10);
+		 tc++;
+		 DEBUG_AddStructElement(curr_type, element_name, datatype, offset, size);
+	       }
+	     if( *tc == '\0' )
+	       {
+		 *c = '\0';
+	       }
+	     else
+	       {
+		 strcpy(c, tc + 1);
+	       }
+	     break;
+	   case 'e':
+	     tc = c + 2;
+	     /*
+	      * Now parse the individual elements of the structure/union.
+	      */
+	     while(*tc != ';')
+	       {
+		 tc2 = element_name;
+		 while(*tc != ':')
+		   {
+		     *tc2++ = *tc++;
+		   }
+		 tc++;
+		 *tc2++ = '\0';
+		 offset  = strtol(tc, &tc, 10);
+		 tc++;
+		 DEBUG_AddStructElement(curr_type, element_name, NULL, offset, 0);
+	       }
+	     if( *tc == '\0' )
+	       {
+		 *c = '\0';
+	       }
+	     else
+	       {
+		 strcpy(c, tc + 1);
+	       }
+	     break;
+	   default:
+	     fprintf(stderr, "Unknown type.\n");
+	     break;
+	   }
+       }
+     
+     rtn = TRUE;
+     
 leave:
-
-  return rtn;
+     
+     return rtn;
 
 }
 
@@ -676,6 +945,9 @@
       num_stab_types = 0;
     }
 
+
+  DEBUG_FreeRegisteredTypedefs();
+
   return TRUE;
 }
 
diff --git a/debugger/types.c b/debugger/types.c
index 581d096..0b26d50 100644
--- a/debugger/types.c
+++ b/debugger/types.c
@@ -11,8 +11,11 @@
 #include <stdlib.h>
 
 #include <assert.h>
+#ifndef __EMX__
 #include <sys/mman.h>
+#endif
 #include <fcntl.h>
+#include <sys/types.h>
 #include <sys/stat.h>
 #include <limits.h>
 #include <strings.h>
@@ -28,6 +31,9 @@
 
 #define NR_TYPE_HASH 521
 
+int		  DEBUG_nchar;
+static int	  DEBUG_maxchar = 1024;
+
 struct en_values
 {
   struct en_values* next;
@@ -177,6 +183,32 @@
   return dt;
 }
 
+static
+struct datatype *
+DEBUG_LookupDataType(enum debug_type xtype, int hash, const char * typename)
+{
+  struct datatype * dt = NULL;
+
+  if( typename != NULL )
+    {
+      for( dt = type_hash_table[hash]; dt; dt = dt->next )
+	{
+	  if( xtype != dt->type || dt->name == NULL 
+	      || dt->name[0] != typename[0])
+	    {
+	      continue;
+	    }
+	  	  
+	  if( strcmp(dt->name, typename) == 0 )
+	    {
+	      return dt;
+	    }
+	}
+    }
+
+  return dt;
+}
+
 struct datatype *
 DEBUG_NewDataType(enum debug_type xtype, const char * typename)
 {
@@ -195,22 +227,7 @@
       hash = type_hash(typename);
     }
 
-  if( typename != NULL )
-    {
-      for( dt = type_hash_table[hash]; dt; dt = dt->next )
-	{
-	  if( xtype != dt->type || dt->name == NULL 
-	      || dt->name[0] != typename[0])
-	    {
-	      continue;
-	    }
-	  	  
-	  if( strcmp(dt->name, typename) == 0 )
-	    {
-	      return dt;
-	    }
-	}
-    }
+  dt = DEBUG_LookupDataType(xtype, hash, typename);
 
   if( dt == NULL )
     {
@@ -347,6 +364,11 @@
   switch(addr->type->type)
     {
     case BASIC:
+      if (!DBG_CHECK_READ_PTR( addr,  addr->type->un.basic.basic_size)) 
+	{
+	  return 0;
+	}
+
       memcpy(&rtn, (char *) addr->off, addr->type->un.basic.basic_size);
       if(    (addr->type->un.basic.b_signed)
 	  && ((addr->type->un.basic.basic_size & 3) != 0)
@@ -495,6 +517,12 @@
 DEBUG_SetStructSize(struct datatype * dt, int size)
 {
   assert(dt->type == STRUCT);
+
+  if( dt->un.structure.members != NULL )
+    {
+      return FALSE;
+    }
+
   dt->un.structure.size = size;
   dt->un.structure.members = NULL;
 
@@ -710,7 +738,8 @@
  *
  * Implementation of the 'print' command.
  */
-void DEBUG_Print( const DBG_ADDR *addr, int count, char format, int level )
+void
+DEBUG_Print( const DBG_ADDR *addr, int count, char format, int level )
 {
   DBG_ADDR	  addr1;
   int		  i;
@@ -728,9 +757,20 @@
   if( addr->type == NULL )
     {
       fprintf(stderr, "Unable to evaluate expression\n");
-      return;
+      goto leave;
     }
   
+  if( level == 0 )
+    {
+      DEBUG_nchar = 0;
+    }
+
+  if( DEBUG_nchar > DEBUG_maxchar )
+    {
+      fprintf(stderr, "...");
+      goto leave;
+    }
+
   if( format == 'i' || format == 's' || format == 'w' || format == 'b' )
     {
       fprintf( stderr, "Format specifier '%c' is meaningless in 'print' command\n", format );
@@ -746,20 +786,25 @@
       DEBUG_PrintBasic(addr, 1, format);
       break;
     case STRUCT:
-      fprintf(stderr, "{");
+      DEBUG_nchar += fprintf(stderr, "{");
       for(m = addr->type->un.structure.members; m; m = m->next)
 	{
 	  addr1 = *addr;
 	  DEBUG_FindStructElement(&addr1, m->name,
 				  (int *) &value);
-	  fprintf(stderr, "%s=", m->name);
+	  DEBUG_nchar += fprintf(stderr, "%s=", m->name);
 	  DEBUG_Print(&addr1, 1, format, level + 1);
 	  if( m->next != NULL )
 	    {
-	      fprintf(stderr, ", ");
+	      DEBUG_nchar += fprintf(stderr, ", ");
+	    }
+	  if( DEBUG_nchar > DEBUG_maxchar )
+	    {
+	      fprintf(stderr, "...}");
+	      goto leave;
 	    }
 	}
-      fprintf(stderr, "}");
+      DEBUG_nchar += fprintf(stderr, "}");
       break;
     case ARRAY:
       /*
@@ -772,28 +817,39 @@
 	   * Special handling for character arrays.
 	   */
 	  pnt = (char *) addr->off;
-	  fprintf(stderr, "\"");
+	  DEBUG_nchar += fprintf(stderr, "\"");
 	  for( i=addr->type->un.array.start; i < addr->type->un.array.end; i++ )
 	    {
 	      fputc(*pnt++, stderr);
+	      DEBUG_nchar++;
+	      if( DEBUG_nchar > DEBUG_maxchar )
+		{
+		  fprintf(stderr, "...\"");
+		  goto leave;
+		}
 	    }
-	  fprintf(stderr, "\"");
+	  DEBUG_nchar += fprintf(stderr, "\"");
 	  break;
 	}
       addr1 = *addr;
       addr1.type = addr->type->un.array.basictype;
-      fprintf(stderr, "{");
+      DEBUG_nchar += fprintf(stderr, "{");
       for( i=addr->type->un.array.start; i <= addr->type->un.array.end; i++ )
 	{
 	  DEBUG_Print(&addr1, 1, format, level + 1);
 	  addr1.off += size;
 	  if( i == addr->type->un.array.end )
 	    {
-	      fprintf(stderr, "}");
+	      DEBUG_nchar += fprintf(stderr, "}");
 	    }
 	  else
 	    {
-	      fprintf(stderr, ", ");
+	      DEBUG_nchar += fprintf(stderr, ", ");
+	    }
+	  if( DEBUG_nchar > DEBUG_maxchar )
+	    {
+	      fprintf(stderr, "...}");
+	      goto leave;
 	    }
 	}
       break;
@@ -802,8 +858,157 @@
       break;
     }
 
+leave:
+
   if( level == 0 )
     {
-      fprintf(stderr, "\n");
+      DEBUG_nchar += fprintf(stderr, "\n");
     }
+  return;
 }
+
+int
+DEBUG_DumpTypes()
+{
+  struct datatype * dt = NULL;
+  struct member * m;
+  int hash;
+  int nm;
+  char * name;
+  char * member_name;
+
+  for(hash = 0; hash < NR_TYPE_HASH + 1; hash++)
+    {
+      for( dt = type_hash_table[hash]; dt; dt = dt->next )
+	{
+	  name =  "none";
+	  if( dt->name != NULL )
+	    {
+	      name = dt->name;
+	    }
+	  switch(dt->type)
+	    {
+	    case BASIC:
+	      fprintf(stderr, "0x%p - BASIC(%s)\n",
+		      dt, name);
+	      break;
+	    case POINTER:
+	      fprintf(stderr, "0x%p - POINTER(%s)(%p)\n",
+		      dt, name, dt->un.pointer.pointsto);
+	      break;
+	    case STRUCT:
+	      member_name = "none";
+	      nm = 0;
+	      if( dt->un.structure.members != NULL
+		  && dt->un.structure.members->name != NULL )
+		{
+		  member_name = dt->un.structure.members->name;
+		  for( m = dt->un.structure.members; m; m = m->next)
+		    {
+		      nm++;
+		    }
+		}
+	      fprintf(stderr, "0x%p - STRUCT(%s) %d %d %s\n", dt, name,
+		      dt->un.structure.size, nm, member_name);
+	      break;
+	    case ARRAY:
+	      fprintf(stderr, "0x%p - ARRAY(%s)(%p)\n",
+		      dt, name, dt->un.array.basictype);
+	      break;
+	    case ENUM:
+	      fprintf(stderr, "0x%p - ENUM(%s)\n",
+		      dt, name);
+	      break;
+	    case BITFIELD:
+	      fprintf(stderr, "0x%p - BITFIELD(%s)\n", dt, name);
+	      break;
+	    case FUNC:
+	      fprintf(stderr, "0x%p - FUNC(%s)(%p)\n",
+		      dt, name, dt->un.funct.rettype);
+	      break;
+	    case CONST:
+	    case TYPEDEF:
+	      fprintf(stderr, "What???\n");
+	      break;
+	    }
+	}
+    }
+  return TRUE;
+}
+
+
+enum debug_type DEBUG_GetType(struct datatype * dt)
+{
+  return dt->type;
+}
+
+struct datatype *
+DEBUG_TypeCast(enum debug_type type, const char * name)
+{
+  int			  hash;
+  struct datatype	* rtn;
+
+  /*
+   * The last bucket is special, and is used to hold typeless names.
+   */
+  if( name == NULL )
+    {
+      hash = NR_TYPE_HASH;
+    }
+  else
+    {
+      hash = type_hash(name);
+    }
+
+  rtn = DEBUG_LookupDataType(type, hash, name);
+
+  return rtn;
+
+}
+
+int
+DEBUG_PrintTypeCast(struct datatype * dt)
+{
+  char		* name;
+
+  name =  "none";
+  if( dt->name != NULL )
+    {
+      name = dt->name;
+    }
+
+  switch(dt->type)
+    {
+    case BASIC:
+      fprintf(stderr, "%s", name);
+      break;
+    case POINTER:
+      DEBUG_PrintTypeCast(dt->un.pointer.pointsto);
+      fprintf(stderr, "*");
+      break;
+    case STRUCT:
+      fprintf(stderr, "struct %s", name);
+      break;
+    case ARRAY:
+      fprintf(stderr, "%s[]", name);
+      break;
+    case ENUM:
+      fprintf(stderr, "enum %s", name);
+      break;
+    case BITFIELD:
+      fprintf(stderr, "unsigned %s", name);
+      break;
+    case FUNC:
+      DEBUG_PrintTypeCast(dt->un.funct.rettype);
+      fprintf(stderr, "(*%s)()", name);
+      break;
+    case CONST:
+    case TYPEDEF:
+      fprintf(stderr, "What???\n");
+      break;
+    }
+
+  return TRUE;
+}
+
+