diff -uw ups-old/ups/ao_symcb.c ups-new/ups/ao_symcb.c
--- ups-old/ups/ao_symcb.c	Tue Jun 15 15:58:46 1999
+++ ups-new/ups/ao_symcb.c	Sun Nov 25 15:14:27 2001
@@ -280,7 +280,8 @@
 		s = acb->strings[i].string;
 		name = parse_name(&symrec, &s, st->st_apool, 0, CT_UNKNOWN, FALSE);
 		scheck(&symrec, &s, ':');
-		type = Class(acb->stf, &symrec, &s, &class);
+		type = Class(acb->stf, &symrec, &s, &class,
+			     acb->stf->stf_fmap, acb->stf->stf_mapsize);

 		if (class != CL_NOCLASS && class != CL_FUNC) {
 			v = ci_make_var(st->st_apool, name, class, type,
diff -uw ups-old/ups/ao_symload.c ups-new/ups/ao_symload.c
--- ups-old/ups/ao_symload.c	Fri May 18 20:54:44 2001
+++ ups-new/ups/ao_symload.c	Sun Nov 25 15:52:19 2001
@@ -114,7 +114,7 @@
 	maxhf = stf->stf_fmap + stf->stf_mapsize;
 	hdrstf = NULL;
 	for (p_hf = stf->stf_fmap; p_hf < maxhf; ++p_hf) {
-		if ((*p_hf)->hf_id == id) {
+		if ((*p_hf) && (*p_hf)->hf_id == id) {
 			if (symno != -1 && (*p_hf)->hf_stf->stf_symno != symno)
 				continue;
 			hdrstf = (*p_hf)->hf_stf;
@@ -433,7 +433,8 @@
 		      user_wants_stop(TRUE)) /* RGA peek in queue */
 		    stop_pressed(1, 0);	/* set */

-		type = Class(stf, &symrec, &s, &class);
+		type = Class(stf, &symrec, &s, &class,
+			     stf->stf_fmap, stf->stf_mapsize);

 		if (!type)	/* RGA for C++ */
 		  continue;
@@ -516,11 +517,11 @@

 	}

-	wrapup_types(stf);
-
 	if (!is_header) {
 		int i;
		
+		wrapup_types(stf);
+
 		for (i = 1; i < stf->stf_mapsize; ++i) {
 			stf_t *hstf;

@@ -717,7 +718,8 @@
 			continue;
 		++s;

-		type = Class(stf, &symrec, &s, &class);
+		type = Class(stf, &symrec, &s, &class,
+			     stf->stf_fmap, stf->stf_mapsize);

 		/* RGA: from Russell Browne:
 		   When compiled with SC4 as a C rather than C++ program, UPS
@@ -1268,7 +1270,8 @@
 			if (*s == ' ') /* RGA for C++  */
 				break;
 			field_scheck(&symrec, &s, ':');
-			type = Class(stf, &symrec, &s, &class);
+			type = Class(stf, &symrec, &s, &class,
+				     stf->stf_fmap, stf->stf_mapsize);

 			if ((class == CL_FUNC) &&
 			    (symrec.symno == AO_FSYMDATA(f)->fs_symno) &&
diff -uw ups-old/ups/ao_symparse.c ups-new/ups/ao_symparse.c
--- ups-old/ups/ao_symparse.c	Fri Nov 23 19:51:30 2001
+++ ups-new/ups/ao_symparse.c	Sun Nov 25 15:12:15 2001
@@ -97,18 +97,21 @@
 static void notimp PROTO((const char *s));
 static int parse_signed_num PROTO((stf_t *stf, Symrec *sr, const char **p_s));
 static type_t *TypeDef PROTO((stf_t *stf, Symrec *sr, const char **p_s,
-							int tnum, bool eval));
+			      int tnum, bool eval, hf_t **fmap, int mapsize));
 static aggr_or_enum_def_t *EnumList PROTO((stf_t *stf, symtab_t *st, Symrec *sr,
 					   const char **p_s, type_t *type));
 static void Enum PROTO((stf_t *stf, symtab_t *st, const char **p_s,
 			aggr_or_enum_def_t *ae, Symrec *sr));
 static aggr_or_enum_def_t *Record PROTO((stf_t *stf, Symrec *sr, const char **p_s,
-					 bool is_struct, bool eval, type_t *type));
+					 bool is_struct, bool eval, type_t *type,
+					 hf_t **fmap, int mapsize));
 static var_t *GnuBaseClass PROTO((stf_t *stf, Symrec *sr, const char **p_s,
-			   bool eval, Compiler_type compiler));
+				  bool eval, Compiler_type compiler,
+				  hf_t **fmap, int mapsize));
 static void GnuStructMethods PROTO((stf_t *stf, Symrec *sr, const char **p_s));
 static var_t *SunProBaseClass PROTO((stf_t *stf, Symrec *sr, const char **p_s,
-			   bool eval, Compiler_type compiler));
+				     bool eval, Compiler_type compiler,
+				     hf_t **fmap, int mapsize));
 static void SunProStructMethods PROTO((stf_t *stf, Symrec *sr, const char **p_s));
 static void SkipPastSemi PROTO((stf_t *stf, Symrec *sr, const char **p_s));
 static void SkipToSplChar PROTO((stf_t *stf, Symrec *sr, const char **p_s, const char* chars));
@@ -118,9 +121,11 @@
 			   var_t* next, Compiler_type compiler));
 static var_t *Field PROTO((stf_t *stf, Symrec *sr, const char **p_s,
 			   int is_struct, var_t *next, bool eval,
-			   Compiler_type compiler, bool *terminate));
+			   Compiler_type compiler, bool *terminate,
+			   hf_t **fmap, int mapsize));
 static dim_t *Subrange PROTO((stf_t *stf, Symrec *sr, const char **p_s,
-					bool eval, bool want_subrange_type));
+			      bool eval, bool want_subrange_type,
+			      hf_t **fmap, int mapsize));

 static void get_basic_type PROTO((stf_t *stf, language_t language, symtab_t *st,
 				  const Symrec *sr, dim_t *dim, type_t *type));
@@ -521,7 +526,8 @@
 	}
 	s += ft->u.defpos.offset;

-	type_id = TypeId(stf, &symrec, &s, TRUE, *(s - 1));
+	type_id = TypeId(stf, &symrec, &s, TRUE, *(s - 1),
+			 stf->stf_fmap, stf->stf_mapsize);
 	if (s2)
 	  free(s2);
 	return type_id;
@@ -604,18 +610,8 @@
 		type = &ft->u.type;
 	}
 	else {
-		stf_t *search_stf;
-#ifdef AO_ELF
-		search_stf = stf->stf_fmap[0]->hf_stf;
-#else
-		/* RCB: gcc version 2.8 or later under sun 4 */
-		if (stf->stf_compiler_type == CT_GNU_CC)
-		    search_stf = stf->stf_fmap[0]->hf_stf;
-		else
-		    search_stf = stf;
-#endif
 		type = get_type(stf, sr, symio, ft, tnum, have_undef_tag,
-				stf->stf_symno, search_stf->stf_symlim - 1);
+				stf->stf_symno, stf->stf_symlim - 1);
 	}

 	return type;
@@ -671,11 +667,13 @@
  *   class of the variable followed by a TypeId.
  */
 type_t *
-Class(stf, sr, p_s, p_class)
+Class(stf, sr, p_s, p_class, fmap, mapsize)
 stf_t *stf;
 Symrec *sr;
 const char **p_s;
 class_t *p_class;
+hf_t **fmap;
+int mapsize;
 {
 	const char *s;
 	char prior_chr;
@@ -805,7 +803,7 @@
 	prior_chr = *s == '\\' ? *(s-1) : *s;
 	bump_str(sr, &s);
 	if (prior_chr != 'Y')
-		rtype = TypeId(stf, sr, &s, TRUE, prior_chr);
+		rtype = TypeId(stf, sr, &s, TRUE, prior_chr, fmap, mapsize);
 	if (rtype == NULL)
 		return rtype;

@@ -1044,12 +1042,14 @@
  *
  */
 type_t *
-TypeId(stf, sr, p_s, eval, prior_chr)
+TypeId(stf, sr, p_s, eval, prior_chr, fmap, mapsize)
 stf_t *stf;
 Symrec *sr;
 const char **p_s;
 bool eval;
 int prior_chr;
+hf_t **fmap;
+int mapsize;
 {
     stf_t *nstf;
     typecode_t utypecode;
@@ -1074,7 +1074,7 @@

     if (have_typenum) {
 	Typenum(stf, sr, FALSE, &s, &fnum, &tnum);
-	if (fnum >= stf->stf_mapsize)
+	if (fnum >= mapsize)
 	{
 	    /* RGA for yacc garbage */
 	    errf ("fnum %d out of range %d in TypeId", fnum, stf->stf_mapsize);
@@ -1086,7 +1086,7 @@
 	    *p_s = s;
 	    return rtype;
 	}
-	nstf = stf->stf_fmap[fnum]->hf_stf;
+	nstf = fmap[fnum]->hf_stf;

 	if (*s == '=' && s[1] == 'x' && char_to_utypecode(s[2], &utypecode)) {
 	    bump_str(sr, &s);
@@ -1103,6 +1103,9 @@
 	    tag = NULL;
 	}
 	rtype = lookup_tnum(nstf, tnum);
+	if (rtype &&
+	    (rtype->ty_code == TY_U_STRUCT || rtype->ty_code == TY_U_UNION))
+		rtype = NULL;
     }
     else {
 	rtype = NULL;
@@ -1124,9 +1127,9 @@
 	        bump_str(sr, &s);

 	    if (rtype == NULL)
-		rtype = TypeDef(nstf, sr, &s, tnum, eval);
+		rtype = TypeDef(nstf, sr, &s, tnum, eval, fmap, mapsize);
 	    else if (!is_typedefed)
-		(void) TypeDef(nstf, sr, &s, tnum, FALSE);
+		(void) TypeDef(nstf, sr, &s, tnum, FALSE, fmap, mapsize);
 	}
 	else if (eval || !rtype)  /*RGA*/ {
 	    rtype = tnum_to_type(nstf, sr, sr->symio, tnum, tag != NULL);
@@ -1141,7 +1144,7 @@
 	}
     }
     else {
-	rtype = TypeDef(nstf, sr, &s, -1, eval);
+	rtype = TypeDef(nstf, sr, &s, -1, eval, fmap, mapsize);
     }

     *p_s = s;
@@ -1449,11 +1452,13 @@
  *	'o' NAME ',' TypeId		{ NI }
  */
 static type_t *
-TypeDef(stf, sr, p_s, tnum, eval)
+TypeDef(stf, sr, p_s, tnum, eval, fmap, mapsize)
 stf_t *stf;
 Symrec *sr;
 const char **p_s;
 int tnum, eval;
+hf_t **fmap;
+int mapsize;
 {
 	Ftype *ft, dummy_ftype;
 	aggr_or_enum_def_t *ae;
@@ -1499,7 +1504,7 @@
 	    prior_chr = *s == '\\' ? *(s-1) : *s;
 	    bump_str(sr, p_s);
 	  }
-	  return TypeId(stf, sr, p_s, eval, prior_chr);
+	  return TypeId(stf, sr, p_s, eval, prior_chr, fmap, mapsize);
 	}
 #endif /* AO_ELF */

@@ -1523,7 +1528,7 @@
 	        bump_str(sr, &s);
 		ft->u.type.ty_code = DT_PTR_TO;
 		ft->u.type.ty_qualifiers = 0;
-		ft->u.type.ty_base = TypeId(stf, sr, &s, eval, prior_chr);
+		ft->u.type.ty_base = TypeId(stf, sr, &s, eval, prior_chr, fmap, mapsize);
 		break;

 	/*  Typenum.  We assume this is a special case basic type (e.g. void).
@@ -1541,7 +1546,7 @@

 		  if (*(s-1) == 'k')
 		    const_type = 1;
-		  rtype = TypeId(stf, sr, &s, eval, *(s - 1));
+		  rtype = TypeId(stf, sr, &s, eval, *(s - 1), fmap, mapsize);
 		  if (!rtype)
 		  {
 		    s = s_old;
@@ -1602,7 +1607,7 @@
 	/*  Subrange.  We assume this means a basic type.
 	 */
 	case 'r':
-		dim = Subrange(stf, sr, &s, eval, FALSE);
+		dim = Subrange(stf, sr, &s, eval, FALSE, fmap, mapsize);
 		get_basic_type(stf, stf->stf_language, stf->stf_symtab,
 			       sr, dim, &ft->u.type);

@@ -1620,10 +1625,10 @@
 	case 'a':
 	        bump_str(sr, &s);
 		ft->u.type.ty_code = DT_ARRAY_OF;
-		ft->u.type.ty_dim = Subrange(stf, sr, &s, eval, TRUE);
+		ft->u.type.ty_dim = Subrange(stf, sr, &s, eval, TRUE, fmap, mapsize);
 		prior_chr = *s == '\\' ? *(s-1) : *s;
 		scheck(sr, &s, ';');
-		ft->u.type.ty_base = TypeId(stf, sr, &s, eval, prior_chr);
+		ft->u.type.ty_base = TypeId(stf, sr, &s, eval, prior_chr, fmap, mapsize);
 		break;

 	/*  ProcedureType.
@@ -1636,7 +1641,7 @@
 		ft->u.type.ty_code = DT_FUNC_RETURNING;
 		ft->u.type.ty_funcret = ci_make_funcret(ap, FDT_IDLIST, 0,
 							FALSE);
-		ft->u.type.ty_base = TypeId(stf, sr, &s, eval, prior_chr);
+		ft->u.type.ty_base = TypeId(stf, sr, &s, eval, prior_chr, fmap, mapsize);
 		break;

 	/*  Record.
@@ -1656,9 +1661,8 @@
 			errf("\bFound aggregate with eval FALSE");
 		is_struct = (prior_chr == 'c' || prior_chr == 'C') ? 2 :
 		  (prior_chr == 's' || prior_chr == 'S') ? 1 : 0;
-		ft->u.type.ty_code = is_struct ? TY_STRUCT : TY_UNION;
 		s1 = s; /* RCB*/
-		ae = Record(stf, sr, &s, is_struct, eval, &ft->u.type);
+		ae = Record(stf, sr, &s, is_struct, eval, &ft->u.type, fmap, mapsize);
 		if (stf->stf_compiler_type == CT_GNU_CC &&
 		    s1[-2]=='@' &&  /* RCB */
 		    ae->ae_aggr_members == NULL)
@@ -1668,7 +1672,7 @@
 		  if ( *s != '-' )
 		  {
 		     *p_s = s;
-		     return TypeDef(stf, sr, p_s, tnum, eval);
+		     return TypeDef(stf, sr, p_s, tnum, eval, fmap, mapsize);
 		  }

 		  dim_dummy.di_low = 0;
@@ -1807,13 +1811,15 @@
  *  TypeDef above has already skipped the 's' or 'u'.
  */
 static aggr_or_enum_def_t *
-Record(stf, sr, p_s, is_struct, eval, type)
+Record(stf, sr, p_s, is_struct, eval, type, fmap, mapsize)
 stf_t *stf;
 Symrec *sr;
 const char **p_s;
 int is_struct;
 bool eval;
 type_t *type;
+hf_t **fmap;
+int mapsize;
 {
 	const char *s;
 	aggr_or_enum_def_t *ae;
@@ -1829,8 +1835,16 @@
 	  compiler = stf->stf_compiler_type;
 	s = *p_s;
 	typecode = is_struct ? TY_STRUCT : TY_UNION;
+	if (type &&
+	    ((typecode == TY_STRUCT && type->ty_code == TY_U_STRUCT) ||
+	     (typecode == TY_UNION && type->ty_code == TY_U_UNION))) {
+		type->ty_code = typecode;
+		ae = type->ty_aggr_or_enum;
+	}
+	else {
-	ae = ci_make_aggr_or_enum_def(stf->stf_symtab->st_apool,
-				      (const char *)NULL, typecode, type);
+		ae = ci_make_aggr_or_enum_def(stf->stf_symtab->st_apool,
+					      (const char *)NULL, typecode, type);
+	}
 	ae->ae_is_complete = AE_COMPLETE;
 	ae->ae_size = parse_num(stf, sr, &s);

@@ -1839,11 +1853,11 @@
 	{
 	  sun_pro = TRUE;
 	  field_scheck(sr, &s, ';');
-          members = SunProBaseClass(stf,sr,&s, eval, compiler);
+          members = SunProBaseClass(stf,sr,&s, eval, compiler, fmap, mapsize);
 	} else if ( *s == '!')
 	{
 	  bump_str(sr, &s);
-          members = GnuBaseClass(stf,sr,&s, eval, compiler);
+          members = GnuBaseClass(stf,sr,&s, eval, compiler, fmap, mapsize);
 	} else
 	{
 	    members = NULL;
@@ -1867,7 +1881,7 @@
 		  break;

 		members = Field(stf, sr, &s, is_struct, members,
-				eval, compiler, &terminate);
+				eval, compiler, &terminate, fmap, mapsize);
 		if (members)
 		  last_members = members;
 	}
@@ -1921,12 +1935,14 @@
 **     Added by Russ Browne (russ@amc.com)
 */
 static var_t*
-GnuBaseClass(stf,sr, p_s, eval, compiler)
+GnuBaseClass(stf,sr, p_s, eval, compiler, fmap, mapsize)
 stf_t *stf;
 Symrec *sr;
 const char **p_s;
 bool eval;
 Compiler_type compiler;
+hf_t **fmap;
+int mapsize;
 {
     /*
     **    Parse C++ base class as output by g++ -g
@@ -1963,7 +1979,7 @@
         offset = parse_num(stf, sr, &s);
 	scheck(sr,&s, ',');

-	rtype = TypeId(stf, sr, &s, eval, 0);
+	rtype = TypeId(stf, sr, &s, eval, 0, fmap, mapsize);
 	if ( *s == '=' )
 	{
 	    abort();
@@ -1992,7 +2008,7 @@
     while ( nvirtual-- && (*s == '$' || *s == '.') && !strncmp(s+1, "vb",2))
     {
 	    field_scheck(sr, &s, ':'); /* Skip over name */
-	    rtype = TypeId(stf, sr, &s, eval, 0);
+	    rtype = TypeId(stf, sr, &s, eval, 0, fmap, mapsize);
 	    scheck(sr,&s, ',');
             offset = parse_num(stf, sr, &s);

@@ -2119,12 +2135,14 @@
 **     Added by Russ Browne (russ@amc.com)
 */
 static var_t*
-SunProBaseClass(stf,sr, p_s, eval, compiler)
+SunProBaseClass(stf,sr, p_s, eval, compiler, fmap, mapsize)
 stf_t *stf;
 Symrec *sr;
 const char **p_s;
 bool eval;
 Compiler_type compiler;
+hf_t **fmap;
+int mapsize;
 {
     /* Parse base class info as output by the SC4 compiler
     **  Input for each base class is of the form
@@ -2161,7 +2179,7 @@
 	}
 	bump_str(sr, &s);
 	offset = parse_num(stf, sr, &s);
-	rtype = TypeId(stf, sr, &s, eval, 0);
+	rtype = TypeId(stf, sr, &s, eval, 0, fmap, mapsize);

 	/* For the SC5 compiler, -offset is an index into the vtbl to
 	** find the offset of the virtual base class.  Discard
@@ -2378,7 +2396,7 @@
  *	NAME ':' TypeId ',' BitOffset ',' BitSize ';'
  */
 static var_t *
-Field(stf, sr, p_s, is_struct, next, eval, compiler, terminate)
+Field(stf, sr, p_s, is_struct, next, eval, compiler, terminate, fmap, mapsize)
 stf_t *stf;
 Symrec *sr;
 const char **p_s;
@@ -2387,6 +2405,8 @@
 bool eval;
 Compiler_type compiler;
 bool *terminate;
+hf_t **fmap;
+int mapsize;
 {
 	const char *s;
 	char prior_chr;
@@ -2481,7 +2501,7 @@
 	if (*s == '/')
 	  s += 2;

-	type = TypeId(stf, sr, &s, eval, prior_chr);
+	type = TypeId(stf, sr, &s, eval, prior_chr, fmap, mapsize);
 	/*
 	** RCB:  This can occur when the type is currently
 	**       under construction by one of the callers of
@@ -2500,7 +2520,7 @@
 	{
 	  prior_chr = *s == '\\' ? *(s-1) : *s;
 	  bump_str(sr, &s);
-	  type1 = TypeId(stf, sr, &s, eval, prior_chr); /* just ignore it */
+	  type1 = TypeId(stf, sr, &s, eval, prior_chr, fmap, mapsize); /* just ignore it */
 	}

 	if (*s == ':' )   /*   g++ static member */
@@ -2623,11 +2643,13 @@
  *  Interface document.
  */
 static dim_t *
-Subrange(stf, sr, p_s, eval, want_subrange_type)
+Subrange(stf, sr, p_s, eval, want_subrange_type, fmap, mapsize)
 stf_t *stf;
 Symrec *sr;
 const char **p_s;
 bool eval, want_subrange_type;
+hf_t **fmap;
+int mapsize;
 {
 	const char *s;
 	char prior_chr;
@@ -2639,7 +2661,7 @@
 	dim = (dim_t *) alloc(stf->stf_symtab->st_apool, sizeof(dim_t));

 	if (want_subrange_type) {
-		dim->di_type = TypeId(stf, sr, &s, eval, prior_chr);
+		dim->di_type = TypeId(stf, sr, &s, eval, prior_chr, fmap, mapsize);
 	}
 	else {
 		int junk;
diff -uw ups-old/ups/ao_symparse.h ups-new/ups/ao_symparse.h
--- ups-old/ups/ao_symparse.h	Tue Jun 15 15:57:29 1999
+++ ups-new/ups/ao_symparse.h	Sun Nov 25 15:02:27 2001
@@ -11,11 +11,11 @@

 #ifndef ST_TE
 type_t *TypeId PROTO((stf_t *stf, Symrec *sr, const char **p_s,
-		      int eval, int prior_chr));
+		      int eval, int prior_chr, hf_t **fmap, int mapsize));
 void Typenum PROTO((stf_t *stf, Symrec *sr, bool assume_paren,
 		    const char **p_s, int *p_fnum, int *p_tnum));
 type_t *Class PROTO((stf_t *stf, Symrec *sr, const char **p_s,
-		     class_t *p_class));
+		     class_t *p_class, hf_t **fmap, int mapsize));
 int parse_num PROTO((stf_t *stf, Symrec *sr, const char **p_s));
 void scheck PROTO((Symrec *sr, const char **p_s, int ch));
 int field_scheck PROTO((Symrec *sr, const char **p_s, int ch));
