diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index eacb0129f6b6fd17f7dc654d8c280814eee884a3..c4cb0df1c569979b5bb47e500dd5cdf2d5318b6a 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -7,7 +7,7 @@
  * Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.56 1999/03/17 22:52:45 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.57 1999/03/25 03:49:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -605,8 +605,28 @@ DefineAttr(char *name, char *type, int attnum)
 			printf("<%s %s> ", attrtypes[attnum]->attname.data, type);
 		attrtypes[attnum]->attnum = 1 + attnum; /* fillatt */
 		attlen = attrtypes[attnum]->attlen = Procid[typeoid].len;
-		attrtypes[attnum]->attbyval = (attlen == 1) || (attlen == 2) || (attlen == 4);
-		attrtypes[attnum]->attalign = 'i';
+		/* Cheat like mad to fill in these items from the length only.
+		 * This only has to work for types used in the system catalogs...
+		 */
+		switch (attlen)
+		{
+			case 1:
+				attrtypes[attnum]->attbyval = true;
+				attrtypes[attnum]->attalign = 'c';
+				break;
+			case 2:
+				attrtypes[attnum]->attbyval = true;
+				attrtypes[attnum]->attalign = 's';
+				break;
+			case 4:
+				attrtypes[attnum]->attbyval = true;
+				attrtypes[attnum]->attalign = 'i';
+				break;
+			default:
+				attrtypes[attnum]->attbyval = false;
+				attrtypes[attnum]->attalign = 'i';
+				break;
+		}
 	}
 	attrtypes[attnum]->attcacheoff = -1;
 	attrtypes[attnum]->atttypmod = -1;
diff --git a/src/include/access/tupmacs.h b/src/include/access/tupmacs.h
index c9cb759221bf353bf0f0c23742861e0324cfd25d..6dd499c60b98167f0d9bc8db26d7a76739e5f4f1 100644
--- a/src/include/access/tupmacs.h
+++ b/src/include/access/tupmacs.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: tupmacs.h,v 1.8 1999/02/13 23:20:59 momjian Exp $
+ * $Id: tupmacs.h,v 1.9 1999/03/25 03:49:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -62,43 +62,22 @@
 	(char *) (T) \
 )
 
+/* att_align aligns the given offset as needed for a datum of length attlen
+ * and alignment requirement attalign.  In practice we don't need the length.
+ * The attalign cases are tested in what is hopefully something like their
+ * frequency of occurrence.
+ */
 #define att_align(cur_offset, attlen, attalign) \
 ( \
-	((attlen) < sizeof(int32)) ? \
-	( \
-		((attlen) == -1) ? \
-		( \
-			((attalign) == 'd') ? 	DOUBLEALIGN(cur_offset) : \
-									INTALIGN(cur_offset) \
-		) \
-		: \
-		( \
-			((attlen) == sizeof(char)) ? \
-			( \
-				(long)(cur_offset) \
-			) \
-			: \
-			( \
-				AssertMacro((attlen) == sizeof(short)), \
-				SHORTALIGN(cur_offset) \
-			) \
-		) \
-	) \
-	: \
-	( \
-		((attlen) == sizeof(int32)) ? \
-		( \
-			INTALIGN(cur_offset) \
-		) \
-		: \
+	((attalign) == 'i') ? INTALIGN(cur_offset) : \
+	 (((attalign) == 'c') ? ((long)(cur_offset)) : \
+	  (((attalign) == 'd') ? DOUBLEALIGN(cur_offset) : \
 		( \
-			AssertMacro((attlen) > sizeof(int32)), \
-			((attalign) == 'd') ? 	DOUBLEALIGN(cur_offset) : \
-									LONGALIGN(cur_offset) \
-		) \
-	) \
+			AssertMacro((attalign) == 's'), \
+			SHORTALIGN(cur_offset) \
+		))) \
 )
-	
+
 #define att_addlength(cur_offset, attlen, attval) \
 ( \
 	((attlen) != -1) ? \
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index a185a1912d47b1372f525016837d636cd4fb6dda..2abfa643032bab26b3e9b9e28e1206e52ce84d72 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_type.h,v 1.55 1999/03/10 05:02:34 tgl Exp $
+ * $Id: pg_type.h,v 1.56 1999/03/25 03:49:25 tgl Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -21,7 +21,7 @@
 #include <utils/rel.h>
 
 /* ----------------
- *		postgres.h contains the system type definintions and the
+ *		postgres.h contains the system type definitions and the
  *		CATALOG(), BOOTSTRAP and DATA() sugar words so this file
  *		can be read by both genbki.sh and the C compiler.
  * ----------------
@@ -53,36 +53,30 @@ CATALOG(pg_type) BOOTSTRAP
 
 	/*
 	 * typbyval determines whether internal Postgres routines pass a value
-	 * of this type by value or by reference.  Postgres uses a 4 byte area
-	 * for passing a field value info, so if the value is not 1, 2, or 4
-	 * bytes long, Postgres does not have the option of passing by value
-	 * and ignores typbyval.
-	 *
-	 * (I don't understand why this column exists.  The above description may
-	 * be an oversimplification.  Also, there appear to be bugs in which
-	 * Postgres doesn't ignore typbyval when it should, but I'm afraid to
-	 * change them until I see proof of damage. -BRYANH 96.08).
-	 *
-	 * (Postgres crashes if typbyval is true, the declared length is 8, and
-	 * the I/O routines are written to expect pass by reference. Note that
-	 * float4 is written for pass by reference and has a declared length
-	 * of 4 bytes, so it looks like pass by reference must be consistant
-	 * with the declared length, and typbyval is used somewhere. - tgl
-	 * 1997-03-20).
+	 * of this type by value or by reference.  Only char, short, and int-
+	 * equivalent items can be passed by value, so if the type is not
+	 * 1, 2, or 4 bytes long, Postgres does not have the option of passing
+	 * by value and so typbyval had better be FALSE.  Variable-length types
+	 * are always passed by reference.
+	 * Note that typbyval can be false even if the length would allow
+	 * pass-by-value; this is currently true for type float4, for example.
 	 */
 	char		typtype;
+
+	/*
+	 * typtype is 'b' for a basic type and 'c' for a catalog type (ie a class).
+	 * If typtype is 'c', typrelid is the OID of the class' entry in pg_class.
+	 * (Why do we need an entry in pg_type for classes, anyway?)
+	 */
 	bool		typisdefined;
 	char		typdelim;
-	Oid			typrelid;
+	Oid			typrelid;		/* 0 if not a class type */
 	Oid			typelem;
 
 	/*
-	 * typelem is NULL if this is not an array type.  If this is an array
+	 * typelem is 0 if this is not an array type.  If this is an array
 	 * type, typelem is the OID of the type of the elements of the array
 	 * (it identifies another row in Table pg_type).
-	 *
-	 * (Note that zero ("0") rather than _null_ is used in the declarations.
-	 * - tgl 97/03/20)
 	 */
 	regproc		typinput;
 	regproc		typoutput;
@@ -90,7 +84,7 @@ CATALOG(pg_type) BOOTSTRAP
 	regproc		typsend;
 	char		typalign;
 
-	/*
+	/* ----------------
 	 * typalign is the alignment required when storing a value of this
 	 * type.  It applies to storage on disk as well as most
 	 * representations of the value inside Postgres.  When multiple values
@@ -99,11 +93,18 @@ CATALOG(pg_type) BOOTSTRAP
 	 * type so that it begins on the specified boundary.  The alignment
 	 * reference is the beginning of the first datum in the sequence.
 	 *
-	 * 'c' = 1 byte alignment. 's' = 2 byte alignment. 'i' = 4 byte
-	 * alignment. 'd' = 8 byte alignment.
+	 * 'c' = CHAR alignment, ie no alignment needed.
+	 * 's' = SHORT alignment (2 bytes on most machines).
+	 * 'i' = INT alignment (4 bytes on most machines).
+	 * 'd' = DOUBLE alignment (8 bytes on many machines, but by no means all).
+	 *
+	 * See include/utils/memutils.h for the macros that compute these
+	 * alignment requirements.
 	 *
-	 * (This might actually be flexible depending on machine architecture,
-	 * but I doubt it - BRYANH 96.08).
+	 * NOTE: for types used in system tables, it is critical that the
+	 * size and alignment defined in pg_type agree with the way that the
+	 * compiler will lay out the field in a struct representing a table row.
+	 * ----------------
 	 */
 	text		typdefault;		/* VARIABLE LENGTH FIELD */
 } FormData_pg_type;
@@ -218,21 +219,21 @@ DESCR("array of 8 oid, used in system tables");
 DATA(insert OID = 32 (	SET		   PGUID -1  -1 f r t \054 0  -1 textin textout textin textout i _null_ ));
 DESCR("set of tuples");
 
-DATA(insert OID = 71 (	pg_type		 PGUID -1 -1 t b t \054 1247 0 foo bar foo bar c _null_));
-DATA(insert OID = 75 (	pg_attribute PGUID -1 -1 t b t \054 1249 0 foo bar foo bar c _null_));
-DATA(insert OID = 81 (	pg_proc		 PGUID -1 -1 t b t \054 1255 0 foo bar foo bar c _null_));
-DATA(insert OID = 83 (	pg_class	 PGUID -1 -1 t b t \054 1259 0 foo bar foo bar c _null_));
-DATA(insert OID = 86 (	pg_shadow	 PGUID -1 -1 t b t \054 1260 0 foo bar foo bar c _null_));
-DATA(insert OID = 87 (	pg_group	 PGUID -1 -1 t b t \054 1261 0 foo bar foo bar c _null_));
-DATA(insert OID = 88 (	pg_database  PGUID -1 -1 t b t \054 1262 0 foo bar foo bar c _null_));
-DATA(insert OID = 90 (	pg_variable  PGUID -1 -1 t b t \054 1264 0 foo bar foo bar c _null_));
-DATA(insert OID = 99 (	pg_log		 PGUID -1 -1 t b t \054 1269 0 foo bar foo bar c _null_));
+DATA(insert OID = 71 (	pg_type		 PGUID 4 4 t c t \054 1247 0 foo bar foo bar i _null_));
+DATA(insert OID = 75 (	pg_attribute PGUID 4 4 t c t \054 1249 0 foo bar foo bar i _null_));
+DATA(insert OID = 81 (	pg_proc		 PGUID 4 4 t c t \054 1255 0 foo bar foo bar i _null_));
+DATA(insert OID = 83 (	pg_class	 PGUID 4 4 t c t \054 1259 0 foo bar foo bar i _null_));
+DATA(insert OID = 86 (	pg_shadow	 PGUID 4 4 t c t \054 1260 0 foo bar foo bar i _null_));
+DATA(insert OID = 87 (	pg_group	 PGUID 4 4 t c t \054 1261 0 foo bar foo bar i _null_));
+DATA(insert OID = 88 (	pg_database  PGUID 4 4 t c t \054 1262 0 foo bar foo bar i _null_));
+DATA(insert OID = 90 (	pg_variable  PGUID 4 4 t c t \054 1264 0 foo bar foo bar i _null_));
+DATA(insert OID = 99 (	pg_log		 PGUID 4 4 t c t \054 1269 0 foo bar foo bar i _null_));
 
 /* OIDS 100 - 199 */
 
-DATA(insert OID = 109 (  pg_attrdef  PGUID -1 -1 t b t \054 1215 0 foo bar foo bar c _null_));
-DATA(insert OID = 110 (  pg_relcheck PGUID -1 -1 t b t \054 1216 0 foo bar foo bar c _null_));
-DATA(insert OID = 111 (  pg_trigger  PGUID -1 -1 t b t \054 1219 0 foo bar foo bar c _null_));
+DATA(insert OID = 109 (  pg_attrdef  PGUID 4 4 t c t \054 1215 0 foo bar foo bar i _null_));
+DATA(insert OID = 110 (  pg_relcheck PGUID 4 4 t c t \054 1216 0 foo bar foo bar i _null_));
+DATA(insert OID = 111 (  pg_trigger  PGUID 4 4 t c t \054 1219 0 foo bar foo bar i _null_));
 
 /* OIDS 200 - 299 */
 
diff --git a/src/include/postgres.h b/src/include/postgres.h
index ed625cd07d0863fa63de634dc3a0e3a329d461cb..ab57059295f081fab5da4edcfc4a218e2b091fd5 100644
--- a/src/include/postgres.h
+++ b/src/include/postgres.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1995, Regents of the University of California
  *
- * $Id: postgres.h,v 1.20 1999/02/13 23:20:46 momjian Exp $
+ * $Id: postgres.h,v 1.21 1999/03/25 03:49:28 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -92,9 +92,14 @@ typedef struct varlena text;
 typedef int2 int28[8];
 typedef Oid oid8[8];
 
-typedef struct nameData
+/* We want NameData to have length NAMEDATALEN and int alignment,
+ * because that's how the data type 'name' is defined in pg_type.
+ * Use a union to make sure the compiler agrees.
+ */
+typedef union nameData
 {
 	char		data[NAMEDATALEN];
+	int			alignmentDummy;
 } NameData;
 typedef NameData *Name;
 
diff --git a/src/include/utils/memutils.h b/src/include/utils/memutils.h
index 2d25f2ebdc9ba865071a3964602640e2b8d04529..58db49693ee721206436f52649b997da44d5a04e 100644
--- a/src/include/utils/memutils.h
+++ b/src/include/utils/memutils.h
@@ -15,7 +15,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: memutils.h,v 1.21 1999/02/13 23:22:25 momjian Exp $
+ * $Id: memutils.h,v 1.22 1999/03/25 03:49:34 tgl Exp $
  *
  * NOTES
  *	  some of the information in this file will be moved to
@@ -27,76 +27,52 @@
 #define MEMUTILS_H
 
 
-#ifdef NOT_USED
-/*****************************************************************************
- *		align.h			- alignment macros									 *
- ****************************************************************************
- [TRH] Let the compiler decide what alignment it uses instead of
-tending
-   we know better.
-   GCC (at least v2.5.8 and up) has an __alignof__ keyword.
-   However, we cannot use it here since on some architectures it reports
-   just a _recommended_ alignment instead of the actual alignment used in
-   padding structures (or at least, this is how I understand gcc).
-   So define a macro that gives us the _actual_ alignment inside a struct.
-   {{note: assumes that alignment size is always a power of 2.}}
+/* ----------------
+ * Alignment macros: align a length or address appropriately for a given type.
+ *
+ * It'd be best to use offsetof to check how the compiler aligns stuff,
+ * but not all compilers support that (still true)?  So we make the
+ * conservative assumption that a type must be aligned on a boundary equal
+ * to its own size, except on a few architectures where we know better.
+ *
+ * CAUTION: for the system tables, the struct declarations found in
+ * src/include/pg_*.h had better be interpreted by the compiler in a way
+ * that agrees with the workings of these macros.  In practice that means
+ * being careful to lay out the columns of a system table in a way that avoids
+ * wasted pad space.
+ *
+ * CAUTION: _ALIGN will not work if sizeof(TYPE) is not a power of 2.
+ * There are machines where sizeof(double) is not, for example.
+ * But such a size is almost certainly not an alignment boundary anyway.
+ * ----------------
  */
-#define _ALIGNSIZE(TYPE)		offsetof(struct { char __c; TYPE __t;}, __t)
-#define _ALIGN(TYPE, LEN) \
-		(((long)(LEN) + (_ALIGNSIZE(TYPE) - 1)) & ~(_ALIGNSIZE(TYPE) - 1))
-#define SHORTALIGN(LEN)			_ALIGN(short, (LEN))
-#define INTALIGN(LEN)			_ALIGN(int, (LEN))
-#define LONGALIGN(LEN)			_ALIGN(long, (LEN))
-#define DOUBLEALIGN(LEN)		_ALIGN(double, (LEN))
-#define MAXALIGN(LEN)			_ALIGN(double, (LEN))
 
-#endif	 /* 0 */
+#define _ALIGN(TYPE,LEN) \
+		(((long)(LEN) + (sizeof(TYPE) - 1)) & ~(sizeof(TYPE) - 1))
 
-/*
- *		SHORTALIGN(LEN) - length (or address) aligned for shorts
- */
-#define SHORTALIGN(LEN)\
-		(((long)(LEN) + (sizeof (short) - 1)) & ~(sizeof (short) - 1))
+#define SHORTALIGN(LEN)			_ALIGN(short, (LEN))
 
 #if defined(m68k)
-#define INTALIGN(LEN)	 SHORTALIGN(LEN)
+#define INTALIGN(LEN)			_ALIGN(short, (LEN))
 #else
-#define INTALIGN(LEN)\
-		(((long)(LEN) + (sizeof (int) - 1)) & ~(sizeof (int) -1))
+#define INTALIGN(LEN)			_ALIGN(int, (LEN))
 #endif
 
-/*
- *		LONGALIGN(LEN)	- length (or address) aligned for longs
- */
 #if (defined(sun) && ! defined(sparc)) || defined(m68k)
-#define LONGALIGN(LEN)	SHORTALIGN(LEN)
-#elif defined (__alpha)
-
- /*
-  * even though "long alignment" should really be on 8-byte boundaries for
-  * linuxalpha, we want the strictest alignment to be on 4-byte (int)
-  * boundaries, because otherwise things break when they try to use the
-  * FormData_pg_* structures.  --djm 12/12/96
-  */
-#define LONGALIGN(LEN)\
-		(((long)(LEN) + (sizeof (int) - 1)) & ~(sizeof (int) -1))
+#define LONGALIGN(LEN)			_ALIGN(short, (LEN))
 #else
-#define LONGALIGN(LEN)\
-		(((long)(LEN) + (sizeof (long) - 1)) & ~(sizeof (long) -1))
+#define LONGALIGN(LEN)			_ALIGN(long, (LEN))
 #endif
 
 #if defined(m68k)
-#define DOUBLEALIGN(LEN) SHORTALIGN(LEN)
-#define MAXALIGN(LEN)	 SHORTALIGN(LEN)
-#elif ! defined(sco)
-#define DOUBLEALIGN(LEN)\
-		(((long)(LEN) + (sizeof (double) - 1)) & ~(sizeof (double) -1))
-
-#define MAXALIGN(LEN)\
-		(((long)(LEN) + (sizeof (double) - 1)) & ~(sizeof (double) -1))
+#define DOUBLEALIGN(LEN)		_ALIGN(short, (LEN))
+#define MAXALIGN(LEN)			_ALIGN(short, (LEN))
+#elif defined(sco)
+#define DOUBLEALIGN(LEN)		_ALIGN(int, (LEN))
+#define MAXALIGN(LEN)			_ALIGN(int, (LEN))
 #else
-#define DOUBLEALIGN(LEN) INTALIGN(LEN)
-#define MAXALIGN(LEN)	 INTALIGN(LEN)
+#define DOUBLEALIGN(LEN)		_ALIGN(double, (LEN))
+#define MAXALIGN(LEN)			_ALIGN(double, (LEN))
 #endif
 
 /*****************************************************************************